Compare commits

...

51 Commits

Author SHA1 Message Date
huangqizhen 60bf3424c8 7.2汇率合并 5 hours ago
sunjiabei 5206832e34 退款逻辑 20 hours ago
jianlin c7cebb823c Merge branch 'refs/heads/lijianlin/feature-20250623120104-工作台与审核' into milestone-20250702-金币重构一期 20 hours ago
jianlin 05cf4c5983 7-1审核统计数,工作台优化 20 hours ago
huangqizhen d884849dc4 Merge remote-tracking branch 'origin/milestone-20250702-金币重构一期' into milestone-20250702-金币重构一期 21 hours ago
huangqizhen dc95d625e6 可跑(不合并) 21 hours ago
sunjiabei ba19635520 退款逻辑 21 hours ago
sunjiabei 8bc41b60d6 楼上接口+商品查询修改 22 hours ago
jianlin bbed22916d Merge remote-tracking branch 'refs/remotes/origin/lijianlin/feature-20250623120104-工作台与审核' into milestone-20250702-金币重构一期 1 day ago
jianlin 04b61d2687 6-30审核相关接口(缺统计数据) 1 day ago
sunjiabei f4f7406fc6 楼上接口+商品查询修改 2 days ago
huangqizhen e56cb9744f 可跑(不合并) 2 days ago
sunjiabei 979abbd622 楼上接口+商品查询修改 2 days ago
huangqizhen 6bb3f5a45d 权限 2 days ago
sunjiabei 77e0a6e31f 新增退款及附属接口 2 days ago
sunjiabei 056c957f75 新增充值和活动查询 3 days ago
sunjiabei cb5e5687f5 充值详情 3 days ago
sunjiabei 22171610c6 排序修改 3 days ago
sunjiabei 78af78ec42 Merge branch 'milestone-20250702-金币重构一期' into sunjiabei/feature-20250623130922-消费功能 3 days ago
huangqizhen 31d62c576c 6.26 查询接口修复 4 days ago
jianlin f09eb9bc92 Merge remote-tracking branch 'refs/remotes/origin/lijianlin/feature-20250623120104-工作台与审核' into milestone-20250702-金币重构一期 5 days ago
jianlin 98bb1296e1 6-27工作台卡片及图表数据(缺图表统计) 5 days ago
sunjiabei 407e01397d Merge branch 'milestone-20250702-金币重构一期' into sunjiabei/feature-20250623130922-消费功能 5 days ago
sunjiabei 88c6492230 bug修改 5 days ago
sunjiabei 786d281c0e 测试git 5 days ago
sunjiabei 637be279e9 退款接口 5 days ago
sunjiabei 18e3c4521e 修改bug 6 days ago
sunjiabei fd6ecaf537 新增消耗修改和退款框架 6 days ago
sunjiabei e8921ddca0 新增消耗金币校验 7 days ago
sunjiabei 339410fc7c 新增消耗 7 days ago
sunjiabei 2ed53a5326 消耗更正以及用户卡片信息 1 week ago
sunjiabei c61f9f6eaf 用户信息 1 week ago
huangqizhen 58f24b11fd Merge remote-tracking branch 'origin/milestone-20250702-金币重构一期' into milestone-20250702-金币重构一期 1 week ago
huangqizhen ceb65f8110 6.24 合并冲突部分修复 1 week ago
jianlin 67508049dc Merge remote-tracking branch 'origin/milestone-20250702-金币重构一期' into milestone-20250702-金币重构一期 1 week ago
huangqizhen ed6ef8996e Merge remote-tracking branch 'origin/milestone-20250702-金币重构一期' into milestone-20250702-金币重构一期 1 week ago
huangqizhen cdd1c51dbd Merge remote-tracking branch 'refs/remotes/origin/huangqizheng/feature-20250623110001-客户金币明细' into milestone-20250702-金币重构一期 1 week ago
jianlin a4c8cb6875 Merge branch 'refs/heads/lijianlin/feature-20250623120104-工作台与审核' into milestone-20250702-金币重构一期 1 week ago
huangqizhen 3dcdb9f7b5 6.24 客户金币余额,异步部分 1 week ago
jianlin 5496460df7 6-24更新统计数据part2(余量外属性) 1 week ago
sunjiabei 9ad7f3af69 消费模块,筛选查询详情 1 week ago
sunjiabei 99a0b0f800 消费模块,消费详情分页,商品查询 1 week ago
sunjiabei 0341bc2ab3 Merge remote-tracking branch 'origin/milestone-20250702-金币重构一期' into milestone-20250702-金币重构一期 1 week ago
huangqizhen f827e86e7a Merge branch 'refs/heads/huangqizheng/feature-20250623110001-客户金币明细' into milestone-20250702-金币重构一期 1 week ago
huangqizhen e885ab526a 6.23 客户金币明细页面查询与合计 1 week ago
sunjiabei be8c77e80e 消费模块,消费金币统计接口 1 week ago
sunjiabei b8a58b038a 消费模块,消费金币统计接口 1 week ago
sunjiabei 9cffd95b79 消费模块,消息详情接口 1 week ago
sunjiabei d4c77f990d 消费模块,消息详情接口 1 week ago
sunjiabei 4fddb8ad5f 消费模块,消息详情接口 1 week ago
sunjiabei e9464c8998 测试 1 week ago
  1. 51
      pom.xml
  2. 2
      src/main/java/com/example/demo/DemoApplication.java
  3. 25
      src/main/java/com/example/demo/Export/ExportService.java
  4. 177
      src/main/java/com/example/demo/Export/ExportServiceImpl.java
  5. 31
      src/main/java/com/example/demo/Util/BusinessException.java
  6. 200
      src/main/java/com/example/demo/Util/ExcelUploadUtil.java
  7. 227
      src/main/java/com/example/demo/Util/ExecutionContextUtil.java
  8. 173
      src/main/java/com/example/demo/Util/FeiShuAlertUtil.java
  9. 37
      src/main/java/com/example/demo/Util/RedisLockUtil.java
  10. 189
      src/main/java/com/example/demo/Util/RedisUtil.java
  11. 18
      src/main/java/com/example/demo/config/EnvConfig.java
  12. 2
      src/main/java/com/example/demo/config/RedisConfig.java
  13. 43
      src/main/java/com/example/demo/controller/AdminController.java
  14. 55
      src/main/java/com/example/demo/controller/AuditController.java
  15. 103
      src/main/java/com/example/demo/controller/ConsumeController.java
  16. 99
      src/main/java/com/example/demo/controller/ExportController.java
  17. 12
      src/main/java/com/example/demo/controller/GeneralController.java
  18. 111
      src/main/java/com/example/demo/controller/GoldDetailController.java
  19. 70
      src/main/java/com/example/demo/controller/PermissionController.java
  20. 69
      src/main/java/com/example/demo/controller/RateController.java
  21. 93
      src/main/java/com/example/demo/controller/RechargeController.java
  22. 101
      src/main/java/com/example/demo/controller/RefundController.java
  23. 28
      src/main/java/com/example/demo/controller/StatisticsController.java
  24. 41
      src/main/java/com/example/demo/controller/UserController.java
  25. 49
      src/main/java/com/example/demo/controller/WorkbenchController.java
  26. 42
      src/main/java/com/example/demo/domain/DTO/ConsumeDTO.java
  27. 44
      src/main/java/com/example/demo/domain/DTO/GoldDetailDTO.java
  28. 42
      src/main/java/com/example/demo/domain/DTO/GoldUserDTO.java
  29. 43
      src/main/java/com/example/demo/domain/DTO/RechargeDTO.java
  30. 42
      src/main/java/com/example/demo/domain/DTO/RefundDTO.java
  31. 67
      src/main/java/com/example/demo/domain/entity/Admin.java
  32. 33
      src/main/java/com/example/demo/domain/entity/Export.java
  33. 8
      src/main/java/com/example/demo/domain/entity/Statistics.java
  34. 3
      src/main/java/com/example/demo/domain/entity/User.java
  35. 28
      src/main/java/com/example/demo/domain/export/Goldmingxi.java
  36. 28
      src/main/java/com/example/demo/domain/vo/AiEmotionExportRecordVO.java
  37. 18
      src/main/java/com/example/demo/domain/vo/AuditRequest.java
  38. 50
      src/main/java/com/example/demo/domain/vo/ConsumeUser.java
  39. 25
      src/main/java/com/example/demo/domain/vo/ExecutionContext.java
  40. 26
      src/main/java/com/example/demo/domain/vo/ExportVo.java
  41. 27
      src/main/java/com/example/demo/domain/vo/Gold.java
  42. 42
      src/main/java/com/example/demo/domain/vo/GoldDetail.java
  43. 41
      src/main/java/com/example/demo/domain/vo/GoldUser.java
  44. 30
      src/main/java/com/example/demo/domain/vo/Page.java
  45. 27
      src/main/java/com/example/demo/domain/vo/Permission.java
  46. 30
      src/main/java/com/example/demo/domain/vo/RateDetail.java
  47. 57
      src/main/java/com/example/demo/domain/vo/RechargeAudit.java
  48. 51
      src/main/java/com/example/demo/domain/vo/RechargeUser.java
  49. 54
      src/main/java/com/example/demo/domain/vo/RefundAudit.java
  50. 50
      src/main/java/com/example/demo/domain/vo/RefundUser.java
  51. 64
      src/main/java/com/example/demo/domain/vo/Result.java
  52. 17
      src/main/java/com/example/demo/domain/vo/TestRequest.java
  53. 25
      src/main/java/com/example/demo/domain/vo/Total.java
  54. 45
      src/main/java/com/example/demo/domain/vo/WorkbenchCard.java
  55. 65
      src/main/java/com/example/demo/domain/vo/WorkbenchMarketCard.java
  56. 13
      src/main/java/com/example/demo/exception/SystemException.java
  57. 17
      src/main/java/com/example/demo/mapper/AdminMapper.java
  58. 25
      src/main/java/com/example/demo/mapper/AiEmotionMapper.java
  59. 25
      src/main/java/com/example/demo/mapper/AuditMapper.java
  60. 28
      src/main/java/com/example/demo/mapper/ConsumeMapper.java
  61. 23
      src/main/java/com/example/demo/mapper/ExportMapper.java
  62. 2
      src/main/java/com/example/demo/mapper/GeneralMapper.java
  63. 39
      src/main/java/com/example/demo/mapper/GoldDetailMapper.java
  64. 31
      src/main/java/com/example/demo/mapper/PermissionMapper.java
  65. 18
      src/main/java/com/example/demo/mapper/RateMapper.java
  66. 27
      src/main/java/com/example/demo/mapper/RechargeMapper.java
  67. 32
      src/main/java/com/example/demo/mapper/RefundMapper.java
  68. 62
      src/main/java/com/example/demo/mapper/StatisticsMapper.java
  69. 25
      src/main/java/com/example/demo/mapper/UserMapper.java
  70. 23
      src/main/java/com/example/demo/mapper/WorkBenchMapper.java
  71. 8
      src/main/java/com/example/demo/security/SecurityConfig.java
  72. 256
      src/main/java/com/example/demo/security/TokenFilter.java
  73. 43
      src/main/java/com/example/demo/security/UploadFilter.java
  74. 15
      src/main/java/com/example/demo/service/AdminService.java
  75. 19
      src/main/java/com/example/demo/service/AiEmotionService.java
  76. 15
      src/main/java/com/example/demo/service/AuditService.java
  77. 28
      src/main/java/com/example/demo/service/ConsumeService.java
  78. 22
      src/main/java/com/example/demo/service/ExportExcelService.java
  79. 19
      src/main/java/com/example/demo/service/GeneralService.java
  80. 31
      src/main/java/com/example/demo/service/GoldDetailService.java
  81. 30
      src/main/java/com/example/demo/service/PermissionService.java
  82. 16
      src/main/java/com/example/demo/service/RateService.java
  83. 26
      src/main/java/com/example/demo/service/RechargeService.java
  84. 35
      src/main/java/com/example/demo/service/RefundService.java
  85. 22
      src/main/java/com/example/demo/service/StatisticsService.java
  86. 19
      src/main/java/com/example/demo/service/UserService.java
  87. 22
      src/main/java/com/example/demo/service/WorkbenchService.java
  88. 84
      src/main/java/com/example/demo/service/listen/AiEmotionExportListener.java
  89. 81
      src/main/java/com/example/demo/service/listen/ConsumeListener.java
  90. 82
      src/main/java/com/example/demo/service/listen/GoldListener.java
  91. 81
      src/main/java/com/example/demo/service/listen/RechargeListener.java
  92. 81
      src/main/java/com/example/demo/service/listen/RefundListener.java
  93. 69
      src/main/java/com/example/demo/service/queue/AbstractMessageListener.java
  94. 74
      src/main/java/com/example/demo/serviceImpl/AdminServiceImpl.java
  95. 35
      src/main/java/com/example/demo/serviceImpl/AiEmotionServiceImpl.java
  96. 173
      src/main/java/com/example/demo/serviceImpl/AuditServiceImpl.java
  97. 169
      src/main/java/com/example/demo/serviceImpl/ConsumeServiceImpl.java
  98. 1102
      src/main/java/com/example/demo/serviceImpl/ExportExcelServiceImpl.java
  99. 71
      src/main/java/com/example/demo/serviceImpl/GeneralServiceImpl.java
  100. 168
      src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java

51
pom.xml

@ -31,15 +31,48 @@
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.24</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
@ -79,11 +112,27 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>3.3.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.2</version> <!-- Jakarta Validation规范版本 -->
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.0.Final</version> <!-- 对应Spring Boot 3的实现版本 -->
</dependency>
</dependencies>
<build>

2
src/main/java/com/example/demo/DemoApplication.java

@ -2,8 +2,10 @@ package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling // 启用调度功能
public class DemoApplication {
public static void main(String[] args) {

25
src/main/java/com/example/demo/Export/ExportService.java

@ -0,0 +1,25 @@
package com.example.demo.Export;
import com.example.demo.domain.DTO.ConsumeDTO;
import com.example.demo.domain.DTO.GoldDetailDTO;
import com.example.demo.domain.DTO.RechargeDTO;
import com.example.demo.domain.DTO.RefundDTO;
import com.example.demo.domain.vo.Result;
/**
* @program: GOLD
* @ClassName ExportService
* @description:
* @author: huangqizhen
* @create: 202507-01 16:06
* @Version 1.0
**/
public interface ExportService {
//充值导出
Result addExportRecharge(RechargeDTO dto);
//退款导出
Result addExportRefund(RefundDTO dto);
//消费导出
Result addExportConsume(ConsumeDTO dto);
}

177
src/main/java/com/example/demo/Export/ExportServiceImpl.java

@ -0,0 +1,177 @@
package com.example.demo.Export;
import com.example.demo.domain.DTO.ConsumeDTO;
import com.example.demo.domain.DTO.RechargeDTO;
import com.example.demo.domain.DTO.RefundDTO;
import com.example.demo.domain.vo.Result;
import com.example.demo.exception.SystemException;
import com.example.demo.mapper.GoldDetailMapper;
import com.example.demo.Util.RedisUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
/**
* @program: GOLD
* @ClassName ExportServiceImpl
* @description:
* @author: huangqizhen
* @create: 202507-01 16:11
* @Version 1.0
**/
@Service
public class ExportServiceImpl implements ExportService{
@Autowired
private GoldDetailMapper goldDetailMapper;
@Autowired
private RedisUtil redisUtil;
@Override
public Result addExportRecharge(RechargeDTO dto) {
// 生成文件名
String fileName = String.format("%s_%s_%s.xlsx",
"充值明细",
"操作人",
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
System.out.println(fileName);
dto.setAccount(123456);
dto.setUrl("");
dto.setFileName(fileName);
dto.setDataNum(0);
try{
// 调用方式
GoldDetailMapper.ExportRecordIdHolder idHolder = new GoldDetailMapper.ExportRecordIdHolder();
goldDetailMapper.insertExportRecord(
idHolder, // 用于接收主键
dto.getAccount(),
dto.getType(),
dto.getState(),
dto.getUrl(),
dto.getFileName(),
dto.getDataNum()
);
// 获取主键
Long recordId = idHolder.getId();
// 2. 构造完整的 JSON 数据包含所有请求参数
Map<String, Object> exportData = new HashMap<>();
exportData.put("recordId", recordId);
// 手动构造请求数据避免 toString() 只返回部分字段
Map<String, Object> requestData = new HashMap<>();
requestData.put("text", dto.getText());
requestData.put("sort", dto.getSort());
requestData.put("field", dto.getField());
requestData.put("deptId", dto.getDeptid());
exportData.put("requestData", requestData);
// 3. 发送到 Redis 消息队列
String jsonData = new ObjectMapper().writeValueAsString(exportData);
redisUtil.sendMessage("recharge:queue:export_queue", jsonData);
}catch (Exception e){
e.printStackTrace();
throw new SystemException("导出数据异常,请稍后重试", e);
}
return Result.success();
}
@Override
public Result addExportRefund(RefundDTO dto) {
// 生成文件名
String fileName = String.format("%s_%s_%s.xlsx",
"退款明细",
"操作人",
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
System.out.println(fileName);
dto.setAccount(123456);
dto.setUrl("");
dto.setFileName(fileName);
dto.setDataNum(0);
try{
// 调用方式
GoldDetailMapper.ExportRecordIdHolder idHolder = new GoldDetailMapper.ExportRecordIdHolder();
goldDetailMapper.insertExportRecord(
idHolder, // 用于接收主键
dto.getAccount(),
dto.getType(),
dto.getState(),
dto.getUrl(),
dto.getFileName(),
dto.getDataNum()
);
// 获取主键
Long recordId = idHolder.getId();
// 2. 构造完整的 JSON 数据包含所有请求参数
Map<String, Object> exportData = new HashMap<>();
exportData.put("recordId", recordId);
// 手动构造请求数据避免 toString() 只返回部分字段
Map<String, Object> requestData = new HashMap<>();
requestData.put("text", dto.getText());
requestData.put("sort", dto.getSort());
requestData.put("field", dto.getField());
requestData.put("deptId", dto.getDeptid());
exportData.put("requestData", requestData);
// 3. 发送到 Redis 消息队列
String jsonData = new ObjectMapper().writeValueAsString(exportData);
redisUtil.sendMessage("refund:queue:export_queue", jsonData);
}catch (Exception e){
e.printStackTrace();
throw new SystemException("导出数据异常,请稍后重试", e);
}
return Result.success();
}
@Override
public Result addExportConsume(ConsumeDTO dto) {
// 生成文件名
String fileName = String.format("%s_%s_%s.xlsx",
"消费明细",
"操作人",
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
System.out.println(fileName);
dto.setAccount(123456);
dto.setUrl("");
dto.setFileName(fileName);
dto.setDataNum(0);
try{
// 调用方式
GoldDetailMapper.ExportRecordIdHolder idHolder = new GoldDetailMapper.ExportRecordIdHolder();
goldDetailMapper.insertExportRecord(
idHolder, // 用于接收主键
dto.getAccount(),
dto.getType(),
dto.getState(),
dto.getUrl(),
dto.getFileName(),
dto.getDataNum()
);
// 获取主键
Long recordId = idHolder.getId();
// 2. 构造完整的 JSON 数据包含所有请求参数
Map<String, Object> exportData = new HashMap<>();
exportData.put("recordId", recordId);
// 手动构造请求数据避免 toString() 只返回部分字段
Map<String, Object> requestData = new HashMap<>();
requestData.put("text", dto.getText());
requestData.put("sort", dto.getSort());
requestData.put("field", dto.getField());
requestData.put("deptId", dto.getDeptid());
exportData.put("requestData", requestData);
// 3. 发送到 Redis 消息队列
String jsonData = new ObjectMapper().writeValueAsString(exportData);
redisUtil.sendMessage("refund:queue:export_queue", jsonData);
}catch (Exception e){
e.printStackTrace();
throw new SystemException("导出数据异常,请稍后重试", e);
}
return Result.success();
}
}

31
src/main/java/com/example/demo/Util/BusinessException.java

@ -0,0 +1,31 @@
package com.example.demo.Util;
/**
* @program: GOLD
* @ClassName BusinessException
* @description:
* @author: huangqizhen
* @create: 202506-23 14:58
* @Version 1.0
**/
import lombok.Getter;
/**
* 业务异常可抛出到前端
*/
@Getter
public class BusinessException extends RuntimeException {
private int code; // 业务状态码
// 使用默认状态码0的构造方法
public BusinessException(String message) {
this(400, message); // 默认状态码400
}
// 指定状态码的构造方法
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
}

200
src/main/java/com/example/demo/Util/ExcelUploadUtil.java

@ -0,0 +1,200 @@
package com.example.demo.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
/**
* Excel文件上传工具类
*/
public class ExcelUploadUtil {
private static final Logger logger = LoggerFactory.getLogger(ExcelUploadUtil.class);
// 默认配置
private static final int DEFAULT_CONNECT_TIMEOUT = 30000; // 30秒
private static final int DEFAULT_READ_TIMEOUT = 60000; // 60秒
private final RestTemplate restTemplate;
private final String uploadUrl;
private final Map<String, String> defaultHeaders;
private final Map<String, String> defaultParams;
/**
* 构造方法
*
* @param uploadUrl 上传接口URL
*/
public ExcelUploadUtil(String uploadUrl) {
this(uploadUrl, new HashMap<>(), new HashMap<>());
}
/**
* 构造方法
*
* @param uploadUrl 上传接口URL
* @param defaultHeaders 默认请求头
* @param defaultParams 默认请求参数
*/
public ExcelUploadUtil(String uploadUrl, Map<String, String> defaultHeaders, Map<String, String> defaultParams) {
this.uploadUrl = uploadUrl;
this.defaultHeaders = new HashMap<>(defaultHeaders);
this.defaultParams = new HashMap<>(defaultParams);
this.restTemplate = createRestTemplate(DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT);
}
/**
* 创建RestTemplate (Spring Boot 1.x 兼容版本)
*/
private RestTemplate createRestTemplate(int connectTimeout, int readTimeout) {
RestTemplate restTemplate = new RestTemplate();
// 添加字符串消息转换器 (Spring 1.x 使用Charset而不是StandardCharsets)
restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));
// 设置超时 (Spring 1.x 方式)
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(connectTimeout);
factory.setReadTimeout(readTimeout);
restTemplate.setRequestFactory(factory);
return restTemplate;
}
/**
* 上传Excel文件
*
* @param excelFile Excel文件
* @param targetDir 目标目录
* @return 上传结果
* @throws IOException 文件操作异常
* @throws UploadException 上传异常
*/
public String uploadExcel(File excelFile, String targetDir) throws IOException, UploadException {
return uploadExcel(excelFile, targetDir, new HashMap<>(), new HashMap<>());
}
/**
* 上传Excel文件带自定义参数
*
* @param excelFile Excel文件
* @param targetDir 目标目录
* @param customHeaders 自定义请求头
* @param customParams 自定义请求参数
* @return 上传结果
* @throws IOException 文件操作异常
* @throws UploadException 上传异常
*/
public String uploadExcel(File excelFile, String targetDir,
Map<String, String> customHeaders,
Map<String, String> customParams) throws IOException, UploadException {
// 验证文件
validateFile(excelFile);
try {
// 准备请求
HttpEntity<MultiValueMap<String, Object>> requestEntity = prepareRequest(excelFile, targetDir, customHeaders, customParams);
// 执行上传
ResponseEntity<String> response = restTemplate.exchange(
uploadUrl,
HttpMethod.POST,
requestEntity,
String.class
);
// 处理响应
return handleResponse(response, excelFile.getName());
} catch (Exception e) {
logger.error("Excel文件上传失败: {}", excelFile.getAbsolutePath(), e);
throw new UploadException("文件上传失败: " + e.getMessage(), e);
}
}
/**
* 验证文件
*/
private void validateFile(File file) throws IOException {
if (file == null) {
throw new IOException("文件不能为null");
}
if (!file.exists()) {
throw new IOException("文件不存在: " + file.getAbsolutePath());
}
if (!file.isFile()) {
throw new IOException("不是有效的文件: " + file.getAbsolutePath());
}
if (file.length() == 0) {
throw new IOException("文件内容为空: " + file.getAbsolutePath());
}
if (!file.getName().toLowerCase().endsWith(".xlsx") &&
!file.getName().toLowerCase().endsWith(".xls")) {
throw new IOException("仅支持Excel文件(.xlsx, .xls)");
}
}
/**
* 准备请求
*/
private HttpEntity<MultiValueMap<String, Object>> prepareRequest(File file, String targetDir,
Map<String, String> customHeaders,
Map<String, String> customParams) {
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
// 添加默认和自定义请求头
defaultHeaders.forEach(headers::set);
customHeaders.forEach(headers::set);
// 准备请求体
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file", new FileSystemResource(file));
body.add("dir", targetDir);
// 添加默认和自定义参数
defaultParams.forEach(body::add);
customParams.forEach(body::add);
return new HttpEntity<>(body, headers);
}
/**
* 处理响应
*/
private String handleResponse(ResponseEntity<String> response, String filename) throws UploadException {
if (response.getStatusCode() == HttpStatus.OK) {
logger.info("文件上传成功: {}", filename);
return response.getBody();
} else {
String errorMsg = String.format("上传接口返回错误状态码: %d, 响应: %s",
response.getStatusCodeValue(), response.getBody());
logger.error(errorMsg);
throw new UploadException(errorMsg);
}
}
/**
* 自定义上传异常
*/
public static class UploadException extends Exception {
public UploadException(String message) {
super(message);
}
public UploadException(String message, Throwable cause) {
super(message, cause);
}
}
}

227
src/main/java/com/example/demo/Util/ExecutionContextUtil.java

@ -0,0 +1,227 @@
package com.example.demo.Util;
import com.example.demo.domain.vo.ExecutionContext;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.*;
import java.util.stream.Collectors;
public class ExecutionContextUtil {
/**
* 获取当前执行环境信息
* @param request 如果是Web请求传入HttpServletRequest
* @return 执行环境信息对象
*/
/**
* 从Spring上下文获取当前HttpServletRequest
*/
public static ExecutionContext getExecutionContext() {
ExecutionContext context = new ExecutionContext();
context.setExecutionTime(new Date());
HttpServletRequest request = getCurrentHttpRequest();
if (isWebEnvironment(request)) {
// Web API 环境
context.setExecutionType("API");
context.setApiUrl(getRealRequestUrl(request));
context.setRequestParams(getRequestParams(request));
context.setToken(getRequestToken(request));
context.setMethod(request.getMethod());
} else {
// 脚本环境
context.setExecutionType("SCRIPT");
context.setScriptFile(getMainClassFile());
}
return context;
}
private static HttpServletRequest getCurrentHttpRequest() {
try {
return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
} catch (IllegalStateException e) {
// 不在Web请求上下文中
return null;
}
}
private static boolean isWebEnvironment(HttpServletRequest request) {
return request != null;
}
private static String getRealRequestUrl(HttpServletRequest request) {
// 1. 获取协议优先从代理头获取
String protocol = getHeaderWithFallback(request,
Arrays.asList("X-Forwarded-Proto", "X-Forwarded-Protocol"),
request.getScheme()
);
// 2. 获取真实域名优先从代理头获取原始域名
String domain = getHeaderWithFallback(request,
Arrays.asList(
"X-Original-Host", // 一些代理服务器设置的原始终端
"X-Real-Host", // 另一个可能的原始主机头
"X-Forwarded-Host", // 转发的主机头
"Host" // 最后回退到常规主机头
),
request.getServerName()
);
// 3. 获取端口智能处理默认端口
Integer port = getRealPort(request, protocol);
// 4. 获取原始路径包括QueryString
String path = getOriginalUri(request);
// 组装完整URL
return String.format("%s://%s:%s%s",
protocol,
domain,
port,
path
);
}
// 辅助方法带fallback的header获取
// 方法1保持强类型推荐
private static String getHeaderWithFallback(
HttpServletRequest request,
List<String> headerNames, // 明确要求String列表
String defaultValue
) {
return headerNames.stream()
.map(request::getHeader)
.filter(Objects::nonNull)
.findFirst()
.orElse(defaultValue);
}
// 获取真实端口处理代理情况
private static int getRealPort(HttpServletRequest request, String protocol) {
// 优先从代理头获取
String forwardedPort = request.getHeader("X-Forwarded-Port");
if (forwardedPort != null) {
return Integer.parseInt(forwardedPort);
}
// 其次从请求获取
int port = request.getServerPort();
// 处理反向代理场景
if (port == 80 && "https".equals(protocol)) {
return 443;
}
if (port == 443 && "http".equals(protocol)) {
return 80;
}
return port;
}
// 获取原始URI包含QueryString
private static String getOriginalUri(HttpServletRequest request) {
// 优先从代理头获取原始URI
String originalUri = request.getHeader("X-Original-URI");
if (originalUri != null) {
return originalUri;
}
// 默认从request获取
String queryString = request.getQueryString();
return request.getRequestURI() +
(queryString != null ? "?" + queryString : "");
}
private static String getRequestParams(HttpServletRequest request) {
try {
// 1. 优先读取Query String无需缓存
String queryString = request.getQueryString();
if (queryString != null) return queryString;
// 2. 检查表单参数GET/POST都适用
Map<String, String[]> params = request.getParameterMap();
if (!params.isEmpty()) return formatParams(params);
// 3. 只有明确是JSON请求时才尝试读取body
if (isJsonRequest(request)) {
return readJsonBodyOnDemand(request);
}
return "{}";
} catch (Exception e) {
return "{\"error\":\"failed to read params\"}";
}
}
private static String readJsonBodyOnDemand(HttpServletRequest request) throws IOException {
// 关键点直接读取原始InputStream不缓存
try (BufferedReader reader = request.getReader()) {
String body = reader.lines().collect(Collectors.joining());
return body.isEmpty() ? "{}" : body;
}
}
private static boolean isJsonRequest(HttpServletRequest request) {
String contentType = request.getContentType();
return contentType != null && contentType.contains("application/json");
}
private static String formatParams(Map<String, String[]> params) {
// 优化后的参数格式化方法
return params.entrySet().stream()
.map(entry -> {
String key = escapeJson(entry.getKey());
String[] values = entry.getValue();
if (values.length == 1) {
return "\"" + key + "\":\"" + escapeJson(values[0]) + "\"";
}
return "\"" + key + "\":[" +
Arrays.stream(values)
.map(v -> "\"" + escapeJson(v) + "\"")
.collect(Collectors.joining(",")) +
"]";
})
.collect(Collectors.joining(",", "{", "}"));
}
private static String escapeJson(String raw) {
return raw.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n");
}
private static String getRequestToken(HttpServletRequest request) {
String token = request.getHeader("Authorization");
if (token == null) {
token = request.getHeader("token");
}
return token;
}
private static String getMainClassFile() {
try {
// 获取主类名
String mainClass = ManagementFactory.getRuntimeMXBean().getSystemProperties().get("sun.java.command");
if (mainClass != null) {
// 简单处理提取主类名
String className = mainClass.split(" ")[0];
// 转换为文件路径
return className.replace('.', File.separatorChar) + ".java";
}
} catch (Exception e) {
e.printStackTrace();
}
return "UnknownScript";
}
}

173
src/main/java/com/example/demo/Util/FeiShuAlertUtil.java

@ -0,0 +1,173 @@
package com.example.demo.Util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.domain.vo.ExecutionContext;
import com.example.demo.config.EnvConfig;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* 飞书报警信息发送工具类
*/
@Component
public class FeiShuAlertUtil {
private static final String FEISHU_WEBHOOK_URL_PROD = "https://open.feishu.cn/open-apis/bot/v2/hook/1a515b19-b64f-46b7-9486-35842b9539fe";
private static final String FEISHU_WEBHOOK_URL_TEST = "https://open.feishu.cn/open-apis/bot/v2/hook/384c78aa-8df1-498b-9c47-04e890ed9877";
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static {
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
}
/**
* 发送报警信息到飞书群紧凑单行格式
*
* @param context 请求接口
* @param errorFile 错误文件
* @param errorLine 错误行数
* @param errorMsg 错误信息
* @param params 脚本执行时需要手动传参如果时API请求则无需传自动获取参数
* @return 是否发送成功
*/
public static boolean sendAlertMessage(ExecutionContext context,
String errorFile, int errorLine,
String errorMsg, String params) {
JSONObject message = new JSONObject();
message.put("msg_type", "post");
JSONObject content = new JSONObject();
JSONObject post = new JSONObject();
JSONObject zhCn = new JSONObject();
String title = "⚠️ 系统异常报警 ⚠️";
zhCn.put("title", title);
List<List<JSONObject>> contentList = new ArrayList<>();
List<JSONObject> elements = new ArrayList<>();
StringBuilder contentBuilder = new StringBuilder();
contentBuilder.append("------------------------------\n\n");
if ("API".equals(context.getExecutionType())) {
contentBuilder.append("**执行类型**: API请求\n\n");
contentBuilder.append("**请求接口**: ").append(context.getApiUrl()).append("\n\n");
contentBuilder.append("**请求参数**: ").append(params).append("\n\n");
contentBuilder.append("**请求方法**: ").append(context.getMethod()).append("\n\n");
if (context.getToken() != null) {
contentBuilder.append("**请求Token**: ")
.append(context.getToken().length() > 10 ?
context.getToken().substring(0, 10) + "..." :
context.getToken())
.append("\n\n");
}
} else {
contentBuilder.append("**执行类型**: 脚本执行\n\n");
contentBuilder.append("**脚本文件**: ").append(context.getScriptFile()).append("\n\n");
contentBuilder.append("**请求参数**: ").append(params).append("\n\n");
}
contentBuilder.append("**错误位置**: ").append(errorFile).append(":").append(errorLine).append("\n\n");
contentBuilder.append("**错误信息**: ").append(errorMsg).append("\n\n");
contentBuilder.append("**执行时间**: ").append(formatDate(context.getExecutionTime())).append("\n\n");
contentBuilder.append("**报警时间**: ").append(formatDate(new Date())).append("\n\n");
contentBuilder.append("------------------------------");
addContentElement(elements, "text", contentBuilder.toString());
contentList.add(elements);
zhCn.put("content", contentList);
post.put("zh_cn", zhCn);
content.put("post", post);
message.put("content", content);
return sendMessage(message);
}
private static String formatDate(Date date) {
// 实现日期格式化方法
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
}
private static void addContentElement(List<JSONObject> elements, String tag, String text) {
JSONObject element = new JSONObject();
element.put("tag", tag);
element.put("text", text);
elements.add(element);
}
private static boolean sendMessage(JSONObject message) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
String FEISHU_WEBHOOK_URL;
String environment = EnvConfig.ENV;
System.out.println("当前环境变量:" + environment);
if (Objects.equals(environment, "unknown") || environment.equals("dev")) {
FEISHU_WEBHOOK_URL = FEISHU_WEBHOOK_URL_TEST;
} else {
FEISHU_WEBHOOK_URL = FEISHU_WEBHOOK_URL_PROD;
}
HttpPost httpPost = new HttpPost(FEISHU_WEBHOOK_URL);
httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
StringEntity entity = new StringEntity(message.toJSONString(), "UTF-8");
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String result = EntityUtils.toString(response.getEntity());
JSONObject obj = JSON.parseObject(result);
return obj.getInteger("code") == 0;
}
} catch (IOException e) {
System.out.println("发送飞书异常" + e.getMessage());
e.printStackTrace();
}
return false;
}
/**
* 发送普通信息到飞书群
*
* @param title 消息标题
* @param content 消息内容
* @return 是否发送成功
*/
public static boolean sendNormalMessage(String title, String content) {
JSONObject message = new JSONObject();
message.put("msg_type", "post");
JSONObject messageContent = new JSONObject();
JSONObject post = new JSONObject();
JSONObject zhCn = new JSONObject();
zhCn.put("title", title);
List<List<JSONObject>> contentList = new ArrayList<>();
List<JSONObject> elements = new ArrayList<>();
StringBuilder contentBuilder = new StringBuilder();
contentBuilder.append("------------------------------\n\n");
contentBuilder.append(content).append("\n\n");
contentBuilder.append("**发送时间**: ").append(formatDate(new Date())).append("\n\n");
contentBuilder.append("------------------------------");
addContentElement(elements, "text", contentBuilder.toString());
contentList.add(elements);
zhCn.put("content", contentList);
post.put("zh_cn", zhCn);
messageContent.put("post", post);
message.put("content", messageContent);
return sendMessage(message);
}
}

37
src/main/java/com/example/demo/Util/RedisLockUtil.java

@ -0,0 +1,37 @@
package com.example.demo.Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisLockUtil {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 尝试获取分布式锁
* @param lockKey 锁的 Key
* @param requestId 请求 ID可用 UUID
* @param expireTime 锁的过期时间毫秒
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String requestId, long expireTime) {
return redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, expireTime, TimeUnit.MILLISECONDS);
}
/**
* 释放分布式锁
* @param lockKey 锁的 Key
* @param requestId 请求 ID
*/
public void unlock(String lockKey, String requestId) {
String currentValue = redisTemplate.opsForValue().get(lockKey);
if (requestId.equals(currentValue)) {
redisTemplate.delete(lockKey);
}
}
}

189
src/main/java/com/example/demo/Util/RedisUtil.java

@ -0,0 +1,189 @@
package com.example.demo.Util;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Set;
import java.util.concurrent.*;
@Component
public class RedisUtil {
@Resource
private RedisTemplate<String, Object> redisTemplate;
// 线程池用于处理延迟消息
private ExecutorService delayMessageExecutor;
// 延迟消息处理线程数
private static final int DELAY_THREAD_POOL_SIZE = 4;
// 延迟队列轮询间隔(毫秒)
private static final long DELAY_QUEUE_POLL_INTERVAL = 1000L;
@PostConstruct
public void init() {
// 初始化线程池
delayMessageExecutor = Executors.newFixedThreadPool(DELAY_THREAD_POOL_SIZE);
}
/**
* 发送消息到队列
* @param queueName 队列名称
* @param message 消息内容
*/
public void sendMessage(String queueName, Object message) {
redisTemplate.opsForList().rightPush(queueName, message);
}
/**
* 阻塞获取消息(优化版增加重试机制)
* @param queueName 队列名称
* @param timeout 超时时间()
* @return 消息内容
*/
public Object blockingGetMessage(String queueName, long timeout) {
// 分段获取避免长时间阻塞
long endTime = System.currentTimeMillis() + timeout * 1000;
while (System.currentTimeMillis() < endTime) {
Object message = redisTemplate.opsForList().leftPop(queueName, 1, TimeUnit.SECONDS);
if (message != null) {
return message;
}
}
return null;
}
/**
* 非阻塞获取消息
* @param queueName 队列名称
* @return 消息内容
*/
public Object getMessage(String queueName) {
return redisTemplate.opsForList().leftPop(queueName);
}
/**
* 获取队列长度
* @param queueName 队列名称
* @return 队列长度
*/
public Long getQueueSize(String queueName) {
return redisTemplate.opsForList().size(queueName);
}
/**
* 发送延迟消息(优化版)
* @param queueName 队列名称
* @param message 消息内容
* @param delay 延迟时间()
*/
public void sendDelayMessage(String queueName, Object message, long delay) {
String delayQueueKey = getDelayQueueKey(queueName);
String messageId = generateMessageId();
redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) {
connection.openPipeline();
// 直接存储消息内容到ZSet的value中
connection.zAdd(
delayQueueKey.getBytes(),
System.currentTimeMillis() + delay * 1000,
serializeMessage(messageId, message)
);
connection.closePipeline();
return null;
}
});
}
/**
* 启动延迟消息处理任务
*/
@Scheduled(fixedRate = DELAY_QUEUE_POLL_INTERVAL)
public void processDelayMessages() {
Set<String> delayQueues = redisTemplate.keys("delay:*");
if (delayQueues != null) {
for (String delayQueue : delayQueues) {
delayMessageExecutor.execute(() -> {
String queueName = delayQueue.substring(6); // 去掉"delay:"前缀
processSingleDelayQueue(queueName);
});
}
}
}
/**
* 处理单个延迟队列
*/
private void processSingleDelayQueue(String queueName) {
String delayQueueKey = getDelayQueueKey(queueName);
long now = System.currentTimeMillis();
// 获取所有已到期的消息
Set<ZSetOperations.TypedTuple<Object>> messages = redisTemplate.opsForZSet()
.rangeByScoreWithScores(delayQueueKey, 0, now);
if (messages != null && !messages.isEmpty()) {
for (ZSetOperations.TypedTuple<Object> tuple : messages) {
Object messageWithId = tuple.getValue();
if (messageWithId != null) {
// 反序列化消息
Object message = deserializeMessage(messageWithId.toString());
// 发送到实际队列
sendMessage(queueName, message);
// 从延迟队列中移除
redisTemplate.opsForZSet().remove(delayQueueKey, messageWithId);
}
}
}
}
// 生成消息ID
private String generateMessageId() {
return java.util.UUID.randomUUID().toString();
}
// 获取延迟队列key
private String getDelayQueueKey(String queueName) {
return "delay:" + queueName;
}
// 序列化消息(可根据实际需求实现)
private byte[] serializeMessage(String messageId, Object message) {
// 这里简单实现实际项目中可以使用JSON序列化等
return (messageId + ":" + message.toString()).getBytes();
}
// 反序列化消息(可根据实际需求实现)
private Object deserializeMessage(String serialized) {
// 简单实现根据实际序列化方式调整
int separatorIndex = serialized.indexOf(':');
if (separatorIndex > 0) {
return serialized.substring(separatorIndex + 1);
}
return serialized;
}
}

18
src/main/java/com/example/demo/config/EnvConfig.java

@ -0,0 +1,18 @@
package com.example.demo.config;
import org.springframework.context.annotation.Configuration;
/**
* @program: GOLD
* @ClassName EnvConfig
* @description:
* @author: huangqizhen
* @create: 202506-29 13:55
* @Version 1.0
**/
@Configuration
public class EnvConfig {
public static final String ENV = "dev";
public static final String ENV_PROD = "prod";
public static final String ENV_TEST = "test";
}

2
src/main/java/com/example/demo/config/RedisConfig.java

@ -1,3 +1,4 @@
package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
@ -44,3 +45,4 @@ public class RedisConfig {
}

43
src/main/java/com/example/demo/controller/AdminController.java

@ -0,0 +1,43 @@
package com.example.demo.controller;
import com.example.demo.Util.JWTUtil;
import com.example.demo.domain.entity.Admin;
import com.example.demo.domain.vo.Result;
import com.example.demo.service.AdminService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @program: GOLD
* @ClassName AdminController
* @description:
* @author: huangqizhen
* @create: 202507-01 10:39
* @Version 1.0
**/
@RestController
@RequestMapping("/admin")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin
public class AdminController {
@Autowired
private AdminService adminService;
@PostMapping("/login")
public Result login(@RequestBody Admin admin){
try {
admin = adminService.login(admin);
admin.setPassword(null);
System.out.println("达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达瓦达");
return Result.success(admin);
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage());
return Result.error(e.getMessage());
}
}
}

55
src/main/java/com/example/demo/controller/AuditController.java

@ -1,11 +1,14 @@
package com.example.demo.controller;
import com.example.demo.domain.vo.*;
import com.example.demo.service.AuditService;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* @program: gold-java
@ -23,4 +26,50 @@ import org.springframework.web.bind.annotation.RestController;
@Transactional
@CrossOrigin
public class AuditController {
@Autowired
private AuditService auditService;
//审核订单
@PostMapping("audit")
public ResponseEntity<Boolean> auditOrder(
@RequestBody AuditRequest request) {
boolean result = auditService.auditOrder(request.getToken(),request.getOrderCode(), request.getAuditId(), request.getAction(),request.getRejectReason());
return ResponseEntity.ok(result);
}
//多条件查询充值审核订单列表
@PostMapping("selectRecharge")
public PageInfo<RechargeAudit> searchRechargeAudit(
@RequestBody Page page) {
Integer pageNum = page.getPageNum();
Integer pageSize = page.getPageSize();
RechargeAudit rechargeAudit = page.getRechargeAudit();
return auditService.selectRechargeBy(pageNum, pageSize, rechargeAudit);
} //多条件查询退款审核订单列表
@PostMapping("selectRefund")
public PageInfo<RefundAudit> searchRefundAudit(
@RequestBody Page page) {
Integer pageNum = page.getPageNum();
Integer pageSize = page.getPageSize();
RefundAudit refundAudit = page.getRefundAudit();
return auditService.selectRefundBy(pageNum, pageSize, refundAudit);
}
//充值审核合计数
@PostMapping("sumRechargeGold")
public Gold sumRechargeGold(@RequestBody Page page) {
Integer pageNum = page.getPageNum();
Integer pageSize = page.getPageSize();
RechargeAudit rechargeAudit = page.getRechargeAudit();
return auditService.sumRechargeGold(pageNum, pageSize, rechargeAudit);
}
//退款审核合计数
@PostMapping("sumRefundGold")
public Gold sumRefundGold(@RequestBody Page page) {
Integer pageNum = page.getPageNum();
Integer pageSize = page.getPageSize();
RefundAudit refundAudit = page.getRefundAudit();
return auditService.sumRefundGold(pageNum, pageSize, refundAudit);
}
}

103
src/main/java/com/example/demo/controller/ConsumeController.java

@ -0,0 +1,103 @@
package com.example.demo.controller;
import com.example.demo.domain.entity.UserGoldRecord;
import com.example.demo.domain.vo.ConsumeUser;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.Page;
import com.example.demo.domain.vo.Result;
import com.example.demo.service.ConsumeService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
/**
* @program: gold-java
* @ClassName ConsumeController
* @description:消费模块
* @author: Double
* @create: 202506-23 13:06
* @Version 1.0
**/
@RestController
@RequestMapping("/consume")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin
public class ConsumeController {
@Autowired
private ConsumeService consumeService;
//消耗明细
@PostMapping("/selectAll")
public Result selcetAll(@RequestBody Page page) {
try {
if (ObjectUtils.isEmpty(page.getPageNum())) {
return Result.error("页码数为空!");
}
if (ObjectUtils.isEmpty(page.getPageSize())) {
return Result.error("页大小为空!");
} else {
return Result.success(consumeService.selectAll(page.getPageNum(), page.getPageSize(),page.getConsumeUser()));
}
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
//消耗明细筛选
@PostMapping("/selectBy")
public Result selcetBy(@RequestBody Page page) {
try {
if (ObjectUtils.isEmpty(page.getPageNum())) {
return Result.error("页码数为空!");
}
if (ObjectUtils.isEmpty(page.getPageSize())) {
return Result.error("页大小为空!");
} else {
return Result.success(consumeService.selectBy(page.getPageNum(), page.getPageSize(), page.getConsumeUser()));
}
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
//消耗金币统计
@PostMapping("/statsGold")
public Result statsGold(@RequestBody ConsumeUser consumeUser) {
try {
Gold gold = consumeService.statsGold(consumeUser);
return Result.success(gold);
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
//消耗金币增加
@PostMapping("/add")
public Result add(@RequestBody ConsumeUser consumeUser) {
try {
return consumeService.add(consumeUser);
// if(consumeUser.getJwcode().equals(94226013))
// {
// return consumeService.add(consumeUser);
// }else {
// return Result.error("不是测试的精网号,无法添加消费");
// }
//
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
}

99
src/main/java/com/example/demo/controller/ExportController.java

@ -0,0 +1,99 @@
package com.example.demo.controller;
import com.example.demo.Util.BusinessException;
import com.example.demo.Util.RedisLockUtil;
import com.example.demo.domain.DTO.ConsumeDTO;
import com.example.demo.domain.DTO.RechargeDTO;
import com.example.demo.domain.DTO.RefundDTO;
import com.example.demo.domain.entity.Export;
import com.example.demo.domain.vo.Result;
import com.example.demo.service.ExportExcelService;
import com.example.demo.service.GoldDetailService;
import com.example.demo.Export.ExportService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.UUID;
/**
* @program: GOLD
* @ClassName ExportController
* @description:
* @author: huangqizhen
* @create: 202506-28 15:22
* @Version 1.0
**/
@RestController
@RequestMapping("/export")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin
public class ExportController {
@Autowired
private ExportExcelService exportExcelService;
@Autowired
private RedisLockUtil redisLockUtil;
@Autowired
private GoldDetailService goldDetailService;
@Autowired
private ExportService exportService;
@PostMapping("/export")
public Result export(@RequestBody Export Export){
return Result.success(exportExcelService.getExcel(Export));
}
@PostMapping("/exportRecharge")
public Result export(@Valid @RequestBody RechargeDTO dto) {
String lockKey = "export:lock:" + dto.getToken(); // 锁的 Key可按用户/业务区分
String requestId = UUID.randomUUID().toString(); // 请求 ID防止误删锁
long expireTime = 5000; // 锁过期时间5秒s
try {
// 尝试获取锁
if (!redisLockUtil.tryLock(lockKey, requestId, expireTime)) {
throw new BusinessException("操作太频繁,请稍后重试");
}
// 执行业务逻辑
return exportService.addExportRecharge(dto);
} finally {
// 释放锁
redisLockUtil.unlock(lockKey, requestId);
}
}
@PostMapping("/exportRefund")
public Result export(@Valid @RequestBody RefundDTO dto) {
String lockKey = "export:lock:" + dto.getToken(); // 锁的 Key可按用户/业务区分
String requestId = UUID.randomUUID().toString(); // 请求 ID防止误删锁
long expireTime = 5000; // 锁过期时间5秒s
try {
// 尝试获取锁
if (!redisLockUtil.tryLock(lockKey, requestId, expireTime)) {
throw new BusinessException("操作太频繁,请稍后重试");
}
// 执行业务逻辑
return exportService.addExportRefund(dto);
} finally {
// 释放锁
redisLockUtil.unlock(lockKey, requestId);
}
}
@PostMapping("/exportConsume")
public Result export(@Valid @RequestBody ConsumeDTO dto) {
String lockKey = "export:lock:" + dto.getToken(); // 锁的 Key可按用户/业务区分
String requestId = UUID.randomUUID().toString(); // 请求 ID防止误删锁
long expireTime = 5000; // 锁过期时间5秒s
try {
// 尝试获取锁
if (!redisLockUtil.tryLock(lockKey, requestId, expireTime)) {
throw new BusinessException("操作太频繁,请稍后重试");
}
// 执行业务逻辑
return exportService.addExportConsume(dto);
} finally {
// 释放锁
redisLockUtil.unlock(lockKey, requestId);
}
}
}

12
src/main/java/com/example/demo/controller/GeneralController.java

@ -41,4 +41,16 @@ public class GeneralController {
List<String> list = generalService.getPlatform();
return Result.success(list);
}
@PostMapping("/goods")
public Result getGoods()
{
List<String> list = generalService.getGoods();
return Result.success(list);
}
@PostMapping("/activity")
public Result getActivity()
{
List<String> list = generalService.getActivity();
return Result.success(list);
}
}

111
src/main/java/com/example/demo/controller/GoldDetailController.java

@ -0,0 +1,111 @@
package com.example.demo.controller;
import com.example.demo.Util.BusinessException;
import com.example.demo.Util.RedisLockUtil;
import com.example.demo.domain.DTO.GoldDetailDTO;
import com.example.demo.domain.DTO.GoldUserDTO;
import com.example.demo.domain.entity.User;
import com.example.demo.domain.vo.GoldDetail;
import com.example.demo.domain.vo.Page;
import com.example.demo.domain.vo.Result;
import com.example.demo.service.GoldDetailService;
import com.example.demo.serviceImpl.AiEmotionServiceImpl;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import java.util.UUID;
/**
* @program: GOLD
* @ClassName GoldDetailController
* @description:
* @author: huangqizhen
* @create: 202506-23 14:41
* @Version 1.0
**/
@RestController
@RequestMapping("/goldDetail")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin
public class GoldDetailController {
private final GoldDetailService goldDetailService;
@Autowired
private RedisLockUtil redisLockUtil;
@Autowired
private AiEmotionServiceImpl aiEmotionServiceImpl;
@PostMapping("/getGoldDetail")
public Result getGoldDetail(@RequestBody Page page){
if(ObjectUtils.isEmpty(page.getPageNum())){
return Result.error("页码数为空!");
}
if(ObjectUtils.isEmpty(page.getPageSize())){
return Result.error("页大小为空!");
}
else{
return Result.success(goldDetailService.getGoldDetail(page.getPageNum(), page.getPageSize(), page.getGoldDetail()));
}
}
@PostMapping("/getTotal")
public Result getTotal(@RequestBody GoldDetail goldDetail) {
return Result.success(goldDetailService.getTotal(goldDetail));
}
@PostMapping("/goldTotal")
public Result GoldTotal(@RequestBody User user) {
return Result.success(goldDetailService.GoldTotal(user));
}
@PostMapping("/getGold")
public Result getGold(@RequestBody Page page) {
System.out.println( page);
if(ObjectUtils.isEmpty(page.getPageNum())){
return Result.error("页码数为空!");
}
if(ObjectUtils.isEmpty(page.getPageSize())){
return Result.error("页大小为空!");
}
return Result.success(goldDetailService.getGold(page.getPageNum(), page.getPageSize(), page.getUser()));
}
@PostMapping("/export")
public Result export(@Valid @RequestBody GoldDetailDTO dto) {
String lockKey = "export:lock:" + dto.getToken(); // 锁的 Key可按用户/业务区分
String requestId = UUID.randomUUID().toString(); // 请求 ID防止误删锁
long expireTime = 5000; // 锁过期时间5秒s
try {
// 尝试获取锁
if (!redisLockUtil.tryLock(lockKey, requestId, expireTime)) {
throw new BusinessException("操作太频繁,请稍后重试");
}
// 执行业务逻辑
return goldDetailService.addExportRecord(dto);
} finally {
// 释放锁
redisLockUtil.unlock(lockKey, requestId);
}
}
@PostMapping("/exportGold")
public Result export(@Valid @RequestBody GoldUserDTO dto) {
String lockKey = "export:lock:" + dto.getToken(); // 锁的 Key可按用户/业务区分
String requestId = UUID.randomUUID().toString(); // 请求 ID防止误删锁
long expireTime = 5000; // 锁过期时间5秒s
try {
// 尝试获取锁
if (!redisLockUtil.tryLock(lockKey, requestId, expireTime)) {
throw new BusinessException("操作太频繁,请稍后重试");
}
// 执行业务逻辑
return goldDetailService.addExportRecordGold(dto);
} finally {
// 释放锁
redisLockUtil.unlock(lockKey, requestId);
}
}
}

70
src/main/java/com/example/demo/controller/PermissionController.java

@ -0,0 +1,70 @@
package com.example.demo.controller;
import com.example.demo.domain.entity.Admin;
import com.example.demo.domain.entity.AdminRole;
import com.example.demo.domain.vo.Page;
import com.example.demo.domain.vo.Permission;
import com.example.demo.domain.vo.Result;
import com.example.demo.service.PermissionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
/**
* @program: GOLD
* @ClassName PermissionController
* @description:
* @author: huangqizhen
* @create: 202506-26 13:22
* @Version 1.0
**/
@RestController
@RequestMapping("/permission")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin
public class PermissionController {
private final PermissionService permissionService;
@PostMapping("/getposition")
public Result getposition(@RequestBody String token){
return Result.success(permissionService.getposition(token));
}
@PostMapping("/getmarket")
public Result getmarket(@RequestBody String token){
return Result.success(permissionService.getmarket(token));
}
@PostMapping("/getPermission")
public Result getPermission(@RequestBody Page page){
return Result.success(permissionService.getpermission(page.getPageNum(), page.getPageSize(), page.getPermission()));
}
@PostMapping("/addPermission")
public Result addPermission(@RequestBody Admin admin) throws Exception {
System.out.println( admin);
try {
return Result.success(permissionService.addpermission(admin));
}
catch (Exception e) {
log.error(Arrays.toString(e.getStackTrace()));
return Result.error(e.getMessage());
}
}
@PostMapping("/getRole")
public Result getRole(@RequestBody String token){
return Result.success(permissionService.getRole(token));
}
@PostMapping("/deleteAdmin")
public Result deleteAdmin(@RequestBody Admin admin){
return Result.success(permissionService.deleteAdmin(admin.getId()));
}
@PostMapping("/updateAdminRole")
public Result updateAdminRole(@RequestBody AdminRole adminrole){
return Result.success(permissionService.updateAdminRole(adminrole));
}
@PostMapping("/upadatePermission")
public Result upadatePermission(@RequestBody Admin admin) throws Exception {
return Result.success(permissionService.upadatePermission(admin));
}
}

69
src/main/java/com/example/demo/controller/RateController.java

@ -0,0 +1,69 @@
package com.example.demo.controller;
import com.example.demo.domain.entity.Rate;
import com.example.demo.domain.vo.Page;
import com.example.demo.domain.vo.Result;
import com.example.demo.mapper.RateMapper;
import com.example.demo.service.RateService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/rate")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin
public class RateController {
@Autowired
private RateService rateService;
//货币汇率列表
@PostMapping("/selectAll")
public Result selectAll(@RequestBody Page page){
if (ObjectUtils.isEmpty(page.getPageNum())) {
return Result.error("页码数为空!");
}
if (ObjectUtils.isEmpty(page.getPageSize())) {
return Result.error("页大小为空!");
} else {
return Result.success(rateService.selectAll(page.getPageNum(), page.getPageSize()));
}
}
//查询货币
@PostMapping("/selectById")
public Result selectById(@RequestBody Map<String, Object> requestBody) {
Integer id = (Integer) requestBody.get("id");
if (ObjectUtils.isEmpty(id)) {
return Result.error("id 为空!");
}
Rate rate = rateService.selectById(id);
return Result.success(rate);
}
// 编辑
@PostMapping("/update")
public Result update(@RequestBody Rate rate) {
if (ObjectUtils.isEmpty(rate.getId())) {
return Result.error("id不能为空");
}
if (ObjectUtils.isEmpty(rate.getRateName())) {
return Result.error("汇率名称不能为空");
}
if (rate.getNum() == null) {
return Result.error("汇率数值不能为空");
}
rateService.update(rate);
return Result.success("编辑成功");
}
}

93
src/main/java/com/example/demo/controller/RechargeController.java

@ -0,0 +1,93 @@
package com.example.demo.controller;
import com.example.demo.domain.vo.*;
import com.example.demo.service.ConsumeService;
import com.example.demo.service.RechargeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
/**
* @program: gold-java
* @ClassName RechargeController
* @description:
* @author: Double
* @create: 202506-29 13:01
* @Version 1.0
**/
@RestController
@RequestMapping("/recharge")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin
public class RechargeController {
@Autowired
private RechargeService rechargeService;
//消耗明细
@PostMapping("/selectAll")
public Result selcetAll(@RequestBody Page page) {
try {
if (ObjectUtils.isEmpty(page.getPageNum())) {
return Result.error("页码数为空!");
}
if (ObjectUtils.isEmpty(page.getPageSize())) {
return Result.error("页大小为空!");
} else {
return Result.success(rechargeService.selectAll(page.getPageNum(), page.getPageSize(),page.getRechargeUser()));
}
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
//消耗明细筛选
@PostMapping("/selectBy")
public Result selcetBy(@RequestBody Page page) {
try {
if (ObjectUtils.isEmpty(page.getPageNum())) {
return Result.error("页码数为空!");
}
if (ObjectUtils.isEmpty(page.getPageSize())) {
return Result.error("页大小为空!");
} else {
return Result.success(rechargeService.selectBy(page.getPageNum(), page.getPageSize(), page.getRechargeUser()));
}
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
//消耗金币统计
@PostMapping("/statsGold")
public Result statsGold(@RequestBody RechargeUser rechargeUser) {
try {
Gold gold = rechargeService.statsGold(rechargeUser);
return Result.success(gold);
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
//充值金币增加
@PostMapping("/add")
public Result add(@RequestBody RechargeUser rechargeUser) {
try {
return rechargeService.add(rechargeUser);
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
}

101
src/main/java/com/example/demo/controller/RefundController.java

@ -0,0 +1,101 @@
package com.example.demo.controller;
import com.example.demo.domain.vo.*;
import com.example.demo.service.ConsumeService;
import com.example.demo.service.RefundService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @program: gold-java
* @ClassName RefundMapper.xml
* @description:
* @author: Double
* @create: 202506-26 11:28
* @Version 1.0
**/
@RestController
@RequestMapping("/refund")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin
public class RefundController {
@Autowired
private RefundService refundService;
//退款明细
@PostMapping("/selectAll")
public Result selcetAll(@RequestBody Page page) {
try {
if (ObjectUtils.isEmpty(page.getPageNum())) {
return Result.error("页码数为空!");
}
if (ObjectUtils.isEmpty(page.getPageSize())) {
return Result.error("页大小为空!");
} else {
return Result.success(refundService.selectAll(page.getPageNum(), page.getPageSize(), page.getRefundUser()));
}
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
@PostMapping("/selectBy")
public Result selcetBy(@RequestBody Page page) {
try {
if (ObjectUtils.isEmpty(page.getPageNum())) {
return Result.error("页码数为空!");
}
if (ObjectUtils.isEmpty(page.getPageSize())) {
return Result.error("页大小为空!");
} else {
return Result.success(refundService.selectBy(page.getPageNum(), page.getPageSize(), page.getRefundUser()));
}
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
@PostMapping("/statsGold")
public Result statsGold(@RequestBody RefundUser refundUser) {
try {
Gold gold = refundService.statsGold(refundUser);
return Result.success(gold);
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
@PostMapping("/refundType")
public Result getRefundType()
{
List<String> list = refundService.getRefundType();
return Result.success(list);
}
@PostMapping("/selectGoods")
public Result getSelectGoods(@RequestBody RefundUser refundUser)
{
List<RefundUser> list = refundService.selectGoods(refundUser.getJwcode());
return Result.success(list);
}
//消耗金币增加
@PostMapping("/add")
public Result add(@RequestBody RefundUser refundUser) {
try {
return refundService.add(refundUser);
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
}

28
src/main/java/com/example/demo/controller/StatisticsController.java

@ -1,13 +1,20 @@
package com.example.demo.controller;
import com.example.demo.domain.entity.Statistics;
import com.example.demo.domain.vo.Result;
import com.example.demo.service.GeneralService;
import com.example.demo.service.StatisticsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.List;
/**
* @program: gold-java
* @ClassName StatisticsController
@ -25,4 +32,25 @@ import org.springframework.web.bind.annotation.RestController;
public class StatisticsController {
@Autowired
private StatisticsService statisticsService;
@Autowired
private GeneralService generalService;
//测试定时任务part1
@PostMapping("/Hourly1")
public void HourlyTask1() {
statisticsService.runHourlyTaskPart1();
}
//测试定时任务part2
@PostMapping("/Hourly2")
public void HourlyTask2() {
statisticsService.runHourlyTaskPart2();
}
//测试一周内定时任务part2
@PostMapping("/Daily2")
public void DailyTask2() {
statisticsService.runDailyTaskPart2();
}
}

41
src/main/java/com/example/demo/controller/UserController.java

@ -0,0 +1,41 @@
package com.example.demo.controller;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.GoldUser;
import com.example.demo.domain.vo.Result;
import com.example.demo.service.ConsumeService;
import com.example.demo.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @program: gold-java
* @ClassName UserController
* @description:
* @author: Double
* @create: 202506-25 10:25
* @Version 1.0
**/
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/selectUser")
public Result selectUser(@RequestBody GoldUser user) {
try {
user = userService.selectUser(user.getJwcode().toString());
return Result.success(user);
} catch (Exception e) {
return Result.error("接口调用失败");
}
}
}

49
src/main/java/com/example/demo/controller/WorkbenchController.java

@ -1,12 +1,20 @@
package com.example.demo.controller;
import com.example.demo.domain.entity.Statistics;
import com.example.demo.domain.vo.TestRequest;
import com.example.demo.domain.vo.WorkbenchCard;
import com.example.demo.mapper.StatisticsMapper;
import com.example.demo.service.StatisticsService;
import com.example.demo.service.WorkbenchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.Map;
/**
* @program: gold-java
* @ClassName WorkbenchController
@ -24,27 +32,40 @@ import org.springframework.web.bind.annotation.*;
public class WorkbenchController {
@Autowired
private WorkbenchService WorkbenchService;
private WorkbenchService workbenchService;
@Autowired
private StatisticsService statisticsService;
@Autowired
private StatisticsMapper statisticsMapper;
/*
获取工作台卡片一的数据
获取各地区工作台卡片的数据
*/
@PostMapping("card1")
public WorkbenchCard card1(@RequestBody WorkbenchCard workbench){
return WorkbenchService.getCard1(workbench.getToken(),workbench.getMarket());
@PostMapping("getCard")
public ResponseEntity<WorkbenchCard> card1(@RequestBody WorkbenchCard workbench){
WorkbenchCard result =workbenchService.getCard(workbench.getToken());
return ResponseEntity.ok(result);
}
/*
获取工作台卡片二的数据
获取各地区工作台图表的数据
*/
@PostMapping("card2")
public WorkbenchCard card2(@RequestBody WorkbenchCard workbench){
return WorkbenchService.getCard2(workbench.getToken(),workbench.getMarket());
@PostMapping("getGraph")
public ResponseEntity<WorkbenchCard> graph1(@RequestBody WorkbenchCard workbench){
WorkbenchCard result =workbenchService.getGraph(workbench.getToken(),workbench.getStartDate(),workbench.getEndDate(),workbench.getMarkets());
return ResponseEntity.ok(result);
}
/*
获取工作台卡片三的数据
测试一段时间内的统计数据
*/
@PostMapping("card3")
public WorkbenchCard card3(@RequestBody WorkbenchCard workbench){
return WorkbenchService.getCard3(workbench.getToken(),workbench.getMarket());
}
/* @PostMapping("testSum")
public Statistics testSum( @RequestBody TestRequest request){
String market = request.getMarket();
Date date = request.getDate();
//获取传入日期所在周的周一
Date thisWeekStart = workbenchService.getStartOfWeek(date);
return statisticsMapper.selectSumByMarketAndDate(market, thisWeekStart, date);
}*/
}

42
src/main/java/com/example/demo/domain/DTO/ConsumeDTO.java

@ -0,0 +1,42 @@
package com.example.demo.domain.DTO;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: GOLD
* @ClassName ConsumeDTO
* @description:
* @author: huangqizhen
* @create: 202507-01 16:17
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class ConsumeDTO {
private String token;
private String url = "";
private String fileName = "";
private Integer sort = 0;
private String field = "";
private Integer account;
private Integer type = 4; //类型
private Integer state = 0; //状态
private String text = ""; //关键词搜索
private Integer dataNum = 0;
private String deptid = "";
@NotNull(message = "page不能为空")
private Integer page = 1;
@NotNull(message = "pageSize不能为空")
private Integer pageSize = 20;
@Override
public String toString() {
return String.format(
"AiEmotionExport(account=%d, type=%d, state=%d, dataNum=%d)",
account, type, state, dataNum
);
}
}

44
src/main/java/com/example/demo/domain/DTO/GoldDetailDTO.java

@ -0,0 +1,44 @@
package com.example.demo.domain.DTO;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: GOLD
* @ClassName AiEmotionExportDTO
* @description:
* @author: huangqizhen
* @create: 202506-30 15:06
* @Version 1.0
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GoldDetailDTO {
private String token;
private String url = "";
private String fileName = "";
private Integer sort = 0;
private String field = "";
private Integer account;
private Integer type = 0; //类型
private Integer state = 0; //状态
private String text = ""; //关键词搜索
private Integer dataNum = 0;
private String deptid = "";
@NotNull(message = "page不能为空")
private Integer page = 1;
@NotNull(message = "pageSize不能为空")
private Integer pageSize = 20;
@Override
public String toString() {
return String.format(
"AiEmotionExport(account=%d, type=%d, state=%d, dataNum=%d)",
account, type, state, dataNum
);
}
}

42
src/main/java/com/example/demo/domain/DTO/GoldUserDTO.java

@ -0,0 +1,42 @@
package com.example.demo.domain.DTO;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: GOLD
* @ClassName GoldDTO
* @description:
* @author: huangqizhen
* @create: 202506-30 23:40
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class GoldUserDTO {
private String token;
private String url = "";
private String fileName = "";
private Integer sort = 0;
private String field = "";
private Integer account;
private Integer type = 1; //类型
private Integer state = 0; //状态
private String text = ""; //关键词搜索
private Integer dataNum = 0;
private String deptid = "";
@NotNull(message = "page不能为空")
private Integer page = 1;
@NotNull(message = "pageSize不能为空")
private Integer pageSize = 20;
@Override
public String toString() {
return String.format(
"AiEmotionExport(account=%d, type=%d, state=%d, dataNum=%d)",
account, type, state, dataNum
);
}
}

43
src/main/java/com/example/demo/domain/DTO/RechargeDTO.java

@ -0,0 +1,43 @@
package com.example.demo.domain.DTO;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: GOLD
* @ClassName RechargeDTO
* @description:
* @author: huangqizhen
* @create: 202507-01 16:15
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class RechargeDTO {
private String token;
private String url = "";
private String fileName = "";
private Integer sort = 0;
private String field = "";
private Integer account;
private Integer type = 2; //类型
private Integer state = 0; //状态
private String text = ""; //关键词搜索
private Integer dataNum = 0;
private String deptid = "";
@NotNull(message = "page不能为空")
private Integer page = 1;
@NotNull(message = "pageSize不能为空")
private Integer pageSize = 20;
@Override
public String toString() {
return String.format(
"AiEmotionExport(account=%d, type=%d, state=%d, dataNum=%d)",
account, type, state, dataNum
);
}
}

42
src/main/java/com/example/demo/domain/DTO/RefundDTO.java

@ -0,0 +1,42 @@
package com.example.demo.domain.DTO;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: GOLD
* @ClassName RefundDTO
* @description:
* @author: huangqizhen
* @create: 202507-01 16:16
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class RefundDTO {
private String token;
private String url = "";
private String fileName = "";
private Integer sort = 0;
private String field = "";
private Integer account;
private Integer type = 3; //类型
private Integer state = 0; //状态
private String text = ""; //关键词搜索
private Integer dataNum = 0;
private String deptid = "";
@NotNull(message = "page不能为空")
private Integer page = 1;
@NotNull(message = "pageSize不能为空")
private Integer pageSize = 20;
@Override
public String toString() {
return String.format(
"AiEmotionExport(account=%d, type=%d, state=%d, dataNum=%d)",
account, type, state, dataNum
);
}
}

67
src/main/java/com/example/demo/domain/entity/Admin.java

@ -1,17 +1,19 @@
package com.example.demo.domain.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.io.Serializable;
import java.util.Date;
import java.util.*;
@Data
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Admin implements Serializable {
public class Admin implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
private Integer id; // 主键ID
@ -29,4 +31,61 @@ public class Admin implements Serializable {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date updateTime; // 更新时间
private Integer roleId;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> authorities = new HashSet<>();
Optional.ofNullable(postiton)
.map(Integer::valueOf)
.ifPresent(permValue -> {
switch (permValue) {
case 1:
authorities.add(new SimpleGrantedAuthority("ROLE_SUPER_ADMIN"));
break;
case 2:
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
break;
case 3:
authorities.add(new SimpleGrantedAuthority("ROLE_AUDITORS"));
break;
case 5:
authorities.add(new SimpleGrantedAuthority("Branch_Manager"));
break;
default:
// 可以添加默认角色或处理未知权限
break;
}
});
return authorities;
}
@Override
public String getUsername() {
return account;
}
@Override
@JsonIgnore
public boolean isAccountNonExpired() {
return true; // 默认账户未过期
}
@Override
@JsonIgnore
public boolean isAccountNonLocked() {
return true; // 默认账户未锁定
}
@Override
@JsonIgnore
public boolean isCredentialsNonExpired() {
return true; // 默认凭证未过期
}
@Override
@JsonIgnore
public boolean isEnabled() {
return adminStatus != null && adminStatus == 1;
}
}

33
src/main/java/com/example/demo/domain/entity/Export.java

@ -0,0 +1,33 @@
package com.example.demo.domain.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @program: GOLD
* @ClassName Export
* @description:
* @author: huangqizhen
* @create: 202506-24 16:17
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class Export {
private String token;
private Integer account; // 账号
private String url; // 文件路径
private String fileName; // 文件名
private Byte type; // 类型
private Byte state; // 状态
private Integer dataNum; // 数据量
private String reason; // 失败原因
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date createTime; // 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date updateTime; // 更新时间
}

8
src/main/java/com/example/demo/domain/entity/Statistics.java

@ -2,10 +2,13 @@ package com.example.demo.domain.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.Date;
/**
@ -45,8 +48,9 @@ public class Statistics implements Serializable {
private Integer rechargeNum; // 当日充值人数
private Integer firstRecharge; // 当日首充人数
// 数据日期
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
private Date currentDatetime;
@JsonFormat(pattern = "yyyy-MM-dd")
@JsonDeserialize(using = LocalDateDeserializer.class)
private LocalDate currentDatetime;
// 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date createTime;

3
src/main/java/com/example/demo/domain/entity/User.java

@ -27,6 +27,7 @@ public class User implements Serializable {
private Integer currentFreeDecember; // 当前十二月免费金币
private Integer currentTaskGold; // 当前任务金币
private Integer rechargeNum; // 充值次数
private Integer sumConsume; // 历史消费
private Integer consumeNum; // 消费次数
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
@ -37,4 +38,6 @@ public class User implements Serializable {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date updateTime; // 更新时间
private String sortField; //排序字段
private String sortOrder; //排序顺序
}

28
src/main/java/com/example/demo/domain/export/Goldmingxi.java

@ -0,0 +1,28 @@
package com.example.demo.domain.export;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: GOLD
* @ClassName goldmingxi
* @description:
* @author: huangqizhen
* @create: 202506-29 17:37
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class Goldmingxi {
private String name; // 名称
private Integer jwcode; // 精网号
private String market; // 所属地区
private String payPlatform; // 支付平台
private Integer type; // 类型
private Integer sumGold; // 总金币
private Integer permentGold; //永久金币
private Integer freeJune; // 免费金币六月到期
private Integer freeDecember; // 免费金币七月到期
private Integer taskGold; // 任务金币
private String adminName; //提交人
}

28
src/main/java/com/example/demo/domain/vo/AiEmotionExportRecordVO.java

@ -0,0 +1,28 @@
package com.example.demo.domain.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @program: GOLD
* @ClassName AiEmotionExportRecordVO
* @description:
* @author: huangqizhen
* @create: 202506-29 14:59
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class AiEmotionExportRecordVO {
private static final long serialVersionUID = 1L;
private String token;
private Long id;
private Long jwcode;
private String fileName;
private String url;
private Integer state;
private Date createTime;
private Date updateTime;
}

18
src/main/java/com/example/demo/domain/vo/AuditRequest.java

@ -0,0 +1,18 @@
package com.example.demo.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AuditRequest {
private String token;
private String orderCode; //订单号
private Integer auditId; //审核人id
private Integer action; //操作
private String rejectReason; //驳回理由
}

50
src/main/java/com/example/demo/domain/vo/ConsumeUser.java

@ -0,0 +1,50 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.PositiveOrZero;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
* @program: gold-java
* @ClassName Consume
* @description: 消费明细
* @author: Double
* @create: 202506-23 11:53
* @Version 1.0
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ConsumeUser implements Serializable {
private static final long serialVersionUID = 1L;
private String name; // 客户姓名
private Integer jwcode; // 精网号
private String market; // 所属地区
private String goodsName; // 商品名称
private String payPlatform; // 消费平台
private Integer sumGold; // 金币总数
private Integer permanentGold; // 永久金币
private Integer freeGold; // 免费金币
private Integer taskGold; // 任务金币
private String remark; // 备注
private Integer adminId; //提交人Id
private String adminName; //提交人姓名
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date createTime; // 消费时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date startTime; // 开始时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date endTime; // 结束时间
private String sortField; //排序字段
private String sortOrder; //排序顺序
}

25
src/main/java/com/example/demo/domain/vo/ExecutionContext.java

@ -0,0 +1,25 @@
package com.example.demo.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Date;
@Data
@AllArgsConstructor
public class ExecutionContext {
// getters setters
private String executionType; // "API" "SCRIPT"
private String apiUrl;
private String requestParams;
private String token;
private String scriptFile;
private Date executionTime;
private String method;
// 构造方法
public ExecutionContext() {
this.executionTime = new Date();
}
}

26
src/main/java/com/example/demo/domain/vo/ExportVo.java

@ -0,0 +1,26 @@
package com.example.demo.domain.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @program: GOLD
* @ClassName ExportVo
* @description:
* @author: huangqizhen
* @create: 202506-29 17:24
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class ExportVo {
private String token;
private Long id;
private String fileName;
private String url;
private Integer state;
}

27
src/main/java/com/example/demo/domain/vo/Gold.java

@ -0,0 +1,27 @@
package com.example.demo.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @program: gold-java
* @ClassName Gold
* @description: 金币信息
* @author: Double
* @create: 202506-23 15:53
* @Version 1.0
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Gold implements Serializable {
private static final long serialVersionUID = 1L;
private Integer totalNum; //总条数
private Integer permanentGolds; // 永久金币总数
private Integer freeGolds; // 免费金币总数
private Integer taskGolds; // 任务金币总数
}

42
src/main/java/com/example/demo/domain/vo/GoldDetail.java

@ -0,0 +1,42 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @program: GOLD
* @ClassName GoldDetail
* @description:
* @author: huangqizhen
* @create: 202506-23 13:03
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class GoldDetail {
private static final long serialVersionUID = 1L;
private String token;
private String name; // 名称
private Integer jwcode; // 精网号
private String market; // 所属地区
private String payPlatform; // 支付平台
private Integer type; // 类型
private Integer sumGold; // 总金币
private Integer permentGold; //永久金币
private Integer freeJune; // 免费金币六月到期
private Integer freeDecember; // 免费金币七月到期
private Integer taskGold; // 任务金币
private String adminName; //提交人
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date startTime; // 开始时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date endTime; // 结束时间
private String sortField; //排序字段
private String sortOrder; //排序顺序
}

41
src/main/java/com/example/demo/domain/vo/GoldUser.java

@ -0,0 +1,41 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @program: gold-java
* @ClassName ConsumeUser
* @description:
* @author: Double
* @create: 202506-24 18:30
* @Version 1.0
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GoldUser {
private String name; // 客户姓名
private Integer jwcode; // 精网号
private String market; // 所属地区
private Integer NowSumGold; // 当前金币总数
private Integer NowPermanentGold; // 当前永久金币
private Integer NowFreeGold; // 当前免费金币
private Integer NowFreeJune; // 免费金币6月
private Integer NowFreeDecember; // 免费金币12月
private Integer NowTaskGold; // 当前任务金币
private Integer historySumGold; // 历史金币总数
private Integer historyPermanentGold; // 历史永久金币
private Integer historyFreeGold; // 历史免费金币
private Integer historyTaskGold; // 历史任务金币
private Integer rechargeNum; // 充值次数
private Integer consumeNum; // 消费次数
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Asia/Shanghai")
private Date firstRecharge; // 首充日期
}

30
src/main/java/com/example/demo/domain/vo/Page.java

@ -0,0 +1,30 @@
package com.example.demo.domain.vo;
import com.example.demo.domain.entity.User;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: GOLD
* @ClassName Page
* @description:
* @author: huangqizhen
* @create: 202506-23 16:23
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class Page {
private static final long serialVersionUID = 1L;
private Integer pageNum;
private Integer pageSize;
private GoldDetail goldDetail;
private ConsumeUser consumeUser;
private User user;
private RefundUser refundUser;
private Permission permission;
private RechargeAudit rechargeAudit;
private RefundAudit refundAudit;
private RechargeUser rechargeUser;
}

27
src/main/java/com/example/demo/domain/vo/Permission.java

@ -0,0 +1,27 @@
package com.example.demo.domain.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: GOLD
* @ClassName Permission
* @description:
* @author: huangqizhen
* @create: 202506-26 10:54
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class Permission {
private String token;
private String id;
private String name; //姓名
private String account; //账号
private String market; //地区
private String postiton; //职位
private String roleName; //角色
private String remark; //备注
private Integer adminStatus; //状态
private Integer roleId; //角色id
}

30
src/main/java/com/example/demo/domain/vo/RateDetail.java

@ -0,0 +1,30 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
@Data
@NoArgsConstructor
public class RateDetail {
private static final long serialVersionUID = 1L;
private Integer id;
private String rateName;
private BigDecimal num = BigDecimal.ZERO;
private Integer adminId;//提交人
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date createTime; // 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date updateTime; // 更新时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date lastTime; // 最晚时间
}

57
src/main/java/com/example/demo/domain/vo/RechargeAudit.java

@ -0,0 +1,57 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @program: gold-java
* @ClassName RechargeAudit
* @description: 充值审核
* @author: Ethan
* @create: 202506-30 10:29
* @Version 1.0
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RechargeAudit {
private static final long serialVersionUID = 1L;
private String name; // 客户姓名
private Integer jwcode; // 精网号
private String orderCode; // 订单号
private String activity; // 活动名称
private String market; // 所属地区
private Byte refundType; // 退款类型
private Integer sumGold; //充值金额
private Integer permanentGold; // 永久金币
private Integer freeGold; // 免费金币
private Integer freeJune; // 6月免费金币
private Integer freeDecember; // 12月免费金币
private String remark; // 备注
private String payModel; //支付方式
private String voucher; //支付凭证
private Integer adminId; //提交人Id
private String adminName; //提交人姓名
private String auditStatus; //审核状态
private Integer auditId; //审核人Id
private String auditName; //审核人姓名
private Byte type; //类型
private String rejectReason; //驳回理由
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private String payTime; //支付时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date createTime; // 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date startTime; // 开始时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date endTime; // 结束时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date auditTime; // 审核时间
}

51
src/main/java/com/example/demo/domain/vo/RechargeUser.java

@ -0,0 +1,51 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @program: gold-java
* @ClassName Recharge
* @description:
* @author: Double
* @create: 202506-29 13:18
* @Version 1.0
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RechargeUser {
private static final long serialVersionUID = 1L;
private String name; // 客户姓名
private Integer jwcode; // 精网号
private String market; // 所属地区
private String activity; // 活动名称
private Integer rateId; // 汇率ID
private String rateName; // 汇率名称
private Integer money; // 金额[]
private Integer permanentGold; // 永久金币
private Integer freeGold; // 免费金币
private String payModel; // 支付方式
private String payPlatform; // 支付平台
private String voucher; // 支付凭证
private String remark; // 备注
private Integer adminId; //提交人Id
private String adminName; //提交人姓名
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date payTime; // 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date startTime; // 开始时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date endTime; // 结束时间
private String sortField; //排序字段
private String sortOrder; //排序顺序
}

54
src/main/java/com/example/demo/domain/vo/RefundAudit.java

@ -0,0 +1,54 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @program: gold-java
* @ClassName RechargeAudit
* @description: 退款审核
* @author: Ethan
* @create: 202506-30 13:29
* @Version 1.0
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RefundAudit {
private static final long serialVersionUID = 1L;
private String name; // 客户姓名
private Integer jwcode; // 精网号
private String orderCode; // 订单号
private String market; // 所属地区
private Integer refundModel; // 退款方式-全额 部分
private String goodsName; // 商品名称
private Integer sumGold; // 退款金额
private Integer permanentGold; // 永久金币
private Integer freeGold; // 免费金币
private Integer freeJune; // 6月免费金币
private Integer freeDecember; // 12月免费金币
private Integer taskGold; // 任务金币
private String remark; // 备注
private Integer adminId; //提交人Id
private String adminName; //提交人姓名
private String auditStatus; //审核状态
private Integer auditId; //审核人Id
private String auditName; //审核人姓名
private String rejectReason; //驳回理由
private Byte type; //类型
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date createTime; // 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date startTime; // 开始时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date endTime; // 结束时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date auditTime; // 审核时间
}

50
src/main/java/com/example/demo/domain/vo/RefundUser.java

@ -0,0 +1,50 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* @program: gold-java
* @ClassName RefundUser
* @description:
* @author: Double
* @create: 202506-26 11:29
* @Version 1.0
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RefundUser {
private static final long serialVersionUID = 1L;
private String orderCode; // 订单号
private String name; // 客户姓名
private Integer jwcode; // 精网号
private String market; // 所属地区
private String goodsName; // 商品名称
private String refundType; // 退款类型
private Byte refundModel; // 退款方式0全部/1部分退款
private Integer sumGold; // 金币总数
private Integer permanentGold; // 永久金币
private Integer freeGold; // 免费金币
private Integer taskGold; // 任务金币
private String remark; // 退款原因
private Integer adminId; //提交人Id
private String adminName; //提交人姓名
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date createTime; // 创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date startTime; // 开始时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date endTime; // 结束时间
private String sortField; //排序字段
private String sortOrder; //排序顺序
}

64
src/main/java/com/example/demo/domain/vo/Result.java

@ -1,5 +1,6 @@
package com.example.demo.domain.vo;
import com.example.demo.Util.BusinessException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
@ -8,40 +9,67 @@ import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.HashMap;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result implements Serializable {
private static final long serialVersionUID = 1L;
private Integer code;
private String msg;
private Object data;
private Integer code; // 响应码200 代表成功401 代表未授权
private String msg; // 响应消息
private Object data; // 返回的数据
public static Result success(Integer code, String msg, Object data) {
return new Result(code, msg, data);
// 成功响应不需要给前端返回数据
public static Result success() {
return new Result(200, "success", new HashMap<>());
}
public static Result success(Integer code, Object data) {
return success(code, "操作成功", data);
// 查询成功响应把查询结果作为返回数据响应给前端
public static Result success(Object data) {
return new Result(200, "success", data);
}
public static Result success(String msg, Object data) {return success(200, msg, data);}
public static Result success(Object data){
return success(200, data);
// 失败响应
public static Result error(String msg) {
return new Result(0, msg, new HashMap<>());
}
public static Result success(){
return success(null);
// 失败响应可以自定义错误码
public static Result error(int code, String msg) {
return new Result(code, msg, new HashMap<>());
}
public static Result error(Integer code, String msg, Object data){
return new Result(code, msg, data);
// 成功响应可以自定义消息和数据
public static Result success(String msg, HashMap<String, Object> resultData) {
return new Result(200, msg, resultData); // 返回成功响应状态码为 200
}
public static Result error(Integer code, String msg){
return error(code, msg, null);
// 未授权响应可以自定义错误码
public static Result unauthorized(int code, String msg) {
return new Result(code, msg, new HashMap<>());
}
public static Result error(String msg){
return error(0, msg);
// 错误响应状态码为200code为401
public static Result unauthorized(String msg) {
return new Result(401, msg, new HashMap<>());
}
//失败响应 自定义状态码 默认为500
public static Result error(BusinessException e) {
Result response = new Result();
// 定义默认错误码映射
final int defaultErrorCode = 400;
// 检查 getCode() 是否为 null如果是 Integer
Integer code = e.getCode();
if (code == null || code == 0) {
response.setCode(defaultErrorCode); // 默认错误码
} else {
response.setCode(code);
}
response.setMsg(e.getMessage());
return response;
}
public String toJson() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(this);

17
src/main/java/com/example/demo/domain/vo/TestRequest.java

@ -0,0 +1,17 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
public class TestRequest {
private String market;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date date;
}

25
src/main/java/com/example/demo/domain/vo/Total.java

@ -0,0 +1,25 @@
package com.example.demo.domain.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @program: GOLD
* @ClassName Total
* @description:
* @author: huangqizhen
* @create: 202506-23 16:53
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class Total {
private static final long serialVersionUID = 1L;
private String token;
private Integer Goldtotal;
private Integer permanentGold;
private Integer freeGold;
private Integer taskGold;
}

45
src/main/java/com/example/demo/domain/vo/WorkbenchCard.java

@ -1,16 +1,18 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @program: gold-java
* @ClassName Workbench
* @description: 工作台请求参数
* @description: 工作台顶层容器
* @author: Ethan
* @create: 202506-17 17:43
* @Version 1.0
@ -21,41 +23,12 @@ import java.util.List;
@AllArgsConstructor
public class WorkbenchCard implements Serializable {
private String token; //用户token
private List<String> market; // 地区
// 卡片一当前金币相关
private Integer currentGold; // 当前金币余量
private Integer dailyChange; // 余量较前一天的变化
private Integer currentPermanent; // 永久金币余量
private Integer currentFreeJune; // 六月到期免费金币余量
private Integer currentFreeDecember; // 十二月到期免费金币余量
private Integer currentTask; // 任务金币余量
private Integer currentFree; // 免费金币余量currentFreeJune + currentFreeDecember
private List<WorkbenchMarketCard> marketCards; // 地区卡片数据
private List<String> markets; // 地区列表
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date startDate; // 起始时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date endDate; // 结束时间
// 卡片二充值相关
private Integer recharge; // 当日充值金币数
private Integer money; // 当日金额永久金币
private Integer yearlyRecharge; // 全年累计充值金币数
private Integer yearlyMoney; // 全年累计金额
// 卡片三当日消费/退款/消耗相关
private Integer consumePermanent; // 当日新增消费永久
private Integer consumeFreeJune; // 当日新增消费六月免费
private Integer consumeFreeDecember; // 当日新增消费十二月免费
private Integer consumeTask; // 当日新增消费任务
private Integer refundPermanent; // 当日新增退款永久
private Integer refundFreeJune; // 当日新增退款六月免费
private Integer refundFreeDecember; // 当日新增退款十二月免费
private Integer refundTask; // 当日新增退款任务
private Integer dailyConsume; // 当日总消耗 = consumePermanent + consumeFreeJune + consumeFreeDecember + consumeTask - (refundPermanent + refundFreeJune + refundFreeDecember + refundTask)
private Integer yearlyConsume; // 全年累计消费
private Integer yearlyRefund; // 全年累计退款金币数
private Integer yearlyReduce; // 全年累计消耗金币数 = yearlyConsume - yearlyRefund
// 卡片四人头数相关
private Integer rechargeNum; // 当日充值人数
private Integer firstRecharge; // 当日首充人数
private Integer wow; // 周同比%
private Integer daily; // 日环比%
private Integer yearlyRechargeNum; // 全年累计充值人头数
}

65
src/main/java/com/example/demo/domain/vo/WorkbenchMarketCard.java

@ -0,0 +1,65 @@
package com.example.demo.domain.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @program: gold-java
* @ClassName WorkbenchMarketCard
* @description:
* @author: Ethan
* @create: 202506-25 16:20
* @Version 1.0
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WorkbenchMarketCard implements Serializable {
private String market;//地区
// 卡片一当前金币相关
private Integer currentGold; // 当前金币余量
private Integer dailyChange; // 余量较前一天的变化
private Integer currentPermanent; // 永久金币余量
private Integer currentFreeJune; // 六月到期免费金币余量
private Integer currentFreeDecember; // 十二月到期免费金币余量
private Integer currentTask; // 任务金币余量
private Integer currentFree; // 免费金币余量currentFreeJune + currentFreeDecember
// 卡片二充值相关
private Integer recharge; // 当日充值金币数
private Integer money; // 当日金额永久金币
private Integer yearlyRecharge; // 全年累计充值金币数
private Integer yearlyMoney; // 全年累计金额
// 卡片三当日消费/退款/消耗相关
private Integer consumePermanent; // 当日新增消费永久
private Integer consumeFreeJune; // 当日新增消费六月免费
private Integer consumeFreeDecember; // 当日新增消费十二月免费
private Integer consumeTask; // 当日新增消费任务
private Integer refundPermanent; // 当日新增退款永久
private Integer refundFreeJune; // 当日新增退款六月免费
private Integer refundFreeDecember; // 当日新增退款十二月免费
private Integer refundTask; // 当日新增退款任务
private Integer dailyReduce; // 当日总消耗 = consumePermanent + consumeFreeJune + consumeFreeDecember + consumeTask - (refundPermanent + refundFreeJune + refundFreeDecember + refundTask)
private Integer yearlyConsume; // 全年累计消费
private Integer yearlyRefund; // 全年累计退款金币数
private Integer yearlyReduce; // 全年累计消耗金币数 = yearlyConsume - yearlyRefund
// 卡片四人头数相关
private Integer rechargeNum; // 当日充值人数
private Integer firstRecharge; // 当日首充人数
private Integer wow; // 周同比%
private Integer daily; // 日环比%
private Integer yearlyRechargeNum; // 全年累计充值人头数
//图表
private Integer SumRechargePermanent; //合计充值永久金币
private Integer SumRechargeFree; //合计充值免费金币
private Integer SumConsumePermanent; //合计消费永久金币
private Integer SumConsumeFree; //合计消费免费金币
private Integer SumConsumeTask; //合计消费任务金币
}

13
src/main/java/com/example/demo/exception/SystemException.java

@ -0,0 +1,13 @@
package com.example.demo.exception;
public class SystemException extends RuntimeException {
public SystemException(String message) {
super(message);
}
public SystemException(String message, Throwable cause) {
super(message, cause);
}
}

17
src/main/java/com/example/demo/mapper/AdminMapper.java

@ -0,0 +1,17 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.Admin;
import org.apache.ibatis.annotations.Mapper;
/**
* @program: GOLD
* @ClassName AdminMapper
* @description:
* @author: huangqizhen
* @create: 202506-27 17:21
* @Version 1.0
**/
@Mapper
public interface AdminMapper {
Admin getAdmin(String account);
}

25
src/main/java/com/example/demo/mapper/AiEmotionMapper.java

@ -0,0 +1,25 @@
package com.example.demo.mapper;
import com.example.demo.domain.vo.AiEmotionExportRecordVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @program: GOLD
* @ClassName AiEmotionMapper
* @description:
* @author: huangqizhen
* @create: 202506-29 16:48
* @Version 1.0
**/
@Mapper
public interface AiEmotionMapper {
void updateStatus(
@Param("recordId") Long recordId,
@Param("state") Integer state,
@Param("url") String url,
@Param("reason") String reason,
@Param("dataNum") Integer dataNum
);
AiEmotionExportRecordVO getRecordById(Long recordId);
}

25
src/main/java/com/example/demo/mapper/AuditMapper.java

@ -1,6 +1,14 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.User;
import com.example.demo.domain.entity.UserGoldRecord;
import com.example.demo.domain.vo.RechargeAudit;
import com.example.demo.domain.vo.RefundAudit;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @program: gold-java
@ -13,6 +21,21 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface AuditMapper {
//根据订单号查订单
UserGoldRecord selectOrderByOrderCode(String orderCode);
//修改订单审核人与审核状态
int updateOrder (UserGoldRecord userGoldRecord);
//修改用户余额
int updateUserGold(User user);
//修改消费订单为以退款
int updateOrderRefund(String orderCode ,Byte isRefund);
//多条件查询充值审核订单
List<RechargeAudit> selectRechargeBy(@Param("pageNum") Integer pageNum,
@Param("pageSize") Integer pageSize,
@Param("rechargeAudit") RechargeAudit rechargeAudit);
//多条件查询消费审核订单
List<RefundAudit> selectRefundBy(@Param("pageNum") Integer pageNum,
@Param("pageSize") Integer pageSize,
@Param("refundAudit") RefundAudit refundAudit);
}

28
src/main/java/com/example/demo/mapper/ConsumeMapper.java

@ -0,0 +1,28 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.UserGoldRecord;
import com.example.demo.domain.vo.ConsumeUser;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @program: gold-java
* @ClassName ConsumeMapper
* @description:
* @author: Double
* @create: 202506-23 13:45
* @Version 1.0
**/
@Mapper
public interface ConsumeMapper {
List<ConsumeUser> selectAll(ConsumeUser consumeUser);
List<ConsumeUser> selectBy(ConsumeUser consumeUser);
void add(UserGoldRecord userGoldRecord);
void updateIsRefund(String orderCode);
}

23
src/main/java/com/example/demo/mapper/ExportMapper.java

@ -0,0 +1,23 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.Export;
import com.example.demo.domain.vo.ExportVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @program: GOLD
* @ClassName ExportMapper
* @description:
* @author: huangqizhen
* @create: 202506-29 17:28
* @Version 1.0
**/
@Mapper
public interface ExportMapper {
ExportVo getExportData(Integer id);
int updateExportData(Long recordId, Integer state, String url, String reason, Integer dataNum);
List<Export> getExportRecord(Integer account);
}

2
src/main/java/com/example/demo/mapper/GeneralMapper.java

@ -16,4 +16,6 @@ import java.util.List;
public interface GeneralMapper {
List<String> getMarket();
List<String> getPlatform();
List<String> getGoods();
List<String> getActivity();
}

39
src/main/java/com/example/demo/mapper/GoldDetailMapper.java

@ -0,0 +1,39 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.User;
import com.example.demo.domain.vo.GoldDetail;
import com.example.demo.domain.vo.Total;
import lombok.Data;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @program: GOLD
* @ClassName GoldDetailMapper
* @description:
* @author: huangqizhen
* @create: 202506-23 13:47
* @Version 1.0
**/
@Mapper
public interface GoldDetailMapper {
List<GoldDetail> getGoldDetail(GoldDetail goldDetail);
Total getTotal(GoldDetail goldDetail);
List<User> getGold(User user);
Total GoldTotal(User user);
@Data
public static class ExportRecordIdHolder{
private Long id;
}
void insertExportRecord(
@Param("recordId") ExportRecordIdHolder recordId, // 用于接收主键
@Param("account") Integer account,
@Param("type") Integer type,
@Param("state") Integer state,
@Param("url") String url,
@Param("fileName") String fileName,
@Param("dataNum") Integer dataNum
);
}

31
src/main/java/com/example/demo/mapper/PermissionMapper.java

@ -0,0 +1,31 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.Admin;
import com.example.demo.domain.entity.AdminRole;
import com.example.demo.domain.entity.Role;
import com.example.demo.domain.vo.Permission;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @program: GOLD
* @ClassName PermissionMapper
* @description:
* @author: huangqizhen
* @create: 202506-26 11:25
* @Version 1.0
**/
@Mapper
public interface PermissionMapper {
List<String> getposition(String token);
List<String> getmarket(String token);
List<Permission> getPermission(Permission permission);
Integer updatePermission(Admin admin);
Integer addPermission(Admin admin);
List<Role> getRole(String token);
Integer addadminRole(AdminRole adminRole);
Integer deleteAdmin(Integer id);
Integer deleteAdminRole(Integer id);
Integer updateAdminRole(AdminRole adminRole);
}

18
src/main/java/com/example/demo/mapper/RateMapper.java

@ -0,0 +1,18 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.Rate;
import com.example.demo.domain.vo.RateDetail;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface RateMapper {
List<Rate> selectAll();
Rate selectById(Integer id);
void update(Rate rate);
void add(Rate rate);
}

27
src/main/java/com/example/demo/mapper/RechargeMapper.java

@ -0,0 +1,27 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.UserGoldRecord;
import com.example.demo.domain.vo.RechargeUser;
import com.example.demo.domain.vo.RefundUser;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @program: gold-java
* @ClassName RechargeMapper
* @description:
* @author: Double
* @create: 202506-29 13:41
* @Version 1.0
**/
@Mapper
public interface RechargeMapper {
List<RechargeUser> selectAll(RechargeUser rechargeUser);
List<RechargeUser> selectBy(RechargeUser rechargeUser);
void add(UserGoldRecord userGoldRecord);
}

32
src/main/java/com/example/demo/mapper/RefundMapper.java

@ -0,0 +1,32 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.UserGoldRecord;
import com.example.demo.domain.vo.ConsumeUser;
import com.example.demo.domain.vo.RefundUser;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @program: gold-java
* @ClassName RefundMapper
* @description:
* @author: Double
* @create: 202506-27 11:31
* @Version 1.0
**/
@Mapper
public interface RefundMapper {
List<RefundUser> selectAll(RefundUser refundUser);
List<RefundUser> selectBy(RefundUser refundUser);
void add(UserGoldRecord userGoldRecord);
List<String> getRefundType();
List<RefundUser> selectGoods(Integer jwcode);
}

62
src/main/java/com/example/demo/mapper/StatisticsMapper.java

@ -0,0 +1,62 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.Statistics;
import com.example.demo.domain.entity.UserGoldRecord;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
/**
* @program: gold-java
* @ClassName StatisticsMapper
* @description:
* @author: Ethan
* @create: 202506-23 14:08
* @Version 1.0
**/
@Mapper
public interface StatisticsMapper {
//根据地区审核状态起止时间查询订单表数据
List<UserGoldRecord> findByMarketAndAuditStatus(@Param("market") String market,
@Param("auditStatusList") List<Integer> auditStatusList,
@Param("startTime") Date startTime,
@Param("endTime") Date endTime);
//获取某地区当前永久金币余量
Integer sumCurrentPermanentGold(@Param("market") String market);
//获取某地区当前六月免费金币余量
Integer sumCurrentFreeJune(@Param("market") String market);
//获取某地区当前永久金币余量
Integer sumCurrentFreeDecember(@Param("market") String market);
//获取某地区当前永久金币余量
Integer sumCurrentTaskGold(@Param("market") String market);
//计算该天充值人数
Integer countRechargeNum(
@Param("market") String market,
@Param("startTime") Date startTime,
@Param("endTime") Date endTime);
//计算该天首充人数
Integer countFirstRecharge(
@Param("market") String market,
@Param("startTime") Date startTime,
@Param("endTime") Date endTime);
//新增part1统计数据
void insertPart1(Statistics statistics);
//更新part1统计数据
void updatePart1(Statistics statistics);
//新增part2统计数据
void insertPart2(Statistics statistics);
//更新part2统计数据
void updatePart2(Statistics statistics);
//获取某地区某时间所在日期的数据仅一条
Statistics selectByMarketAndDate(@Param("market") String market,
@Param("startDate") Date startDate,
@Param("endDate") Date endDate);
//获取某地区某时间段的统计数据仅一条
Statistics selectSumByMarketAndDate(@Param("market") String market,
@Param("startDate") Date startDate,
@Param("endDate") Date endDate);
}

25
src/main/java/com/example/demo/mapper/UserMapper.java

@ -0,0 +1,25 @@
package com.example.demo.mapper;
import com.example.demo.domain.entity.User;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.GoldUser;
import org.apache.ibatis.annotations.Mapper;
/**
* @program: gold-java
* @ClassName UserMapper
* @description:
* @author: Double
* @create: 202506-25 10:40
* @Version 1.0
**/
@Mapper
public interface UserMapper {
GoldUser selectUser(String jwcode);
GoldUser selectGold(String jwcode);
void updateGold(User user);
}

23
src/main/java/com/example/demo/mapper/WorkBenchMapper.java

@ -3,6 +3,7 @@ package com.example.demo.mapper;
import com.example.demo.domain.vo.WorkbenchCard;
import org.apache.ibatis.annotations.Mapper;
import java.util.Date;
import java.util.List;
/**
@ -16,10 +17,20 @@ import java.util.List;
@Mapper
public interface WorkBenchMapper {
//工作台卡片一
public WorkbenchCard getCard1(List<String> areas);
//工作台卡片二
public WorkbenchCard getCard2(List<String> areas);
//工作台卡片三
public WorkbenchCard getCard3(List<String> areas);
//给定时间范围内的该地区充值金币数永久+免费
Integer sumRecharge(String market, Date startDate, Date endDate);
//给定时间范围内的该地区充值金额永久金币数
Integer sumMoney(String market, Date startDate, Date endDate);
//给定时间范围内的该地区消费金币数永久+免费+任务
Integer sumConsume(String market, Date startDate, Date endDate);
//给定时间范围内的该地区消费永久金币数
Integer sumCPermanent(String market, Date startDate, Date endDate);
//给定时间范围内的该地区消费免费金币数
Integer sumCFree(String market, Date startDate, Date endDate);
//给定时间范围内的该地区消费任务金币数
Integer sumCTask(String market, Date startDate, Date endDate);
//给定时间范围内的该地区退款金币数永久+免费+任务
Integer sumRefund(String market,Date startDate, Date endDate);
//给定时间范围内的该地区充值人头数根据精网号去重老数据有多人共用一个精网号的问题
Integer countRechargeNum(String market, Date startDate, Date endDate);
}

8
src/main/java/com/example/demo/security/SecurityConfig.java

@ -36,8 +36,8 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
public class SecurityConfig {
@Autowired
TokenFilter tokenFilter;
// @Autowired
// TokenFilter tokenFilter;
// 核心配置 配置一个过滤器链
@ -60,7 +60,7 @@ public class SecurityConfig {
request
.requestMatchers( HttpMethod.POST,
// 用户不登录就可以访问的路径
"/admin/login","/upload/**","/detailY/ERP","/home/java/haiwaiyanfa/gold1/**","/home/java/haiwaiyanfa/**","/**").permitAll()
"/admin/login","/upload/**","/detailY/ERP","/home/java/haiwaiyanfa/gold1/**","/home/java/haiwaiyanfa/**").permitAll()
.requestMatchers(
"/error","alipay/**","/upload/**","/home/java/haiwaiyanfa/gold1/**","/home/java/haiwaiyanfa/**"
).permitAll()
@ -70,7 +70,7 @@ public class SecurityConfig {
http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class); // 然后是TokenFilter
// http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class); // 然后是TokenFilter
return http.build();
}

256
src/main/java/com/example/demo/security/TokenFilter.java

@ -1,205 +1,8 @@
//package com.example.demo.security;
//
//
//import com.example.demo.Util.JWTUtil;
//import com.example.demo.Util.RequestWrapper;
//import com.example.demo.domain.entity.Admin;
//import jakarta.servlet.FilterChain;
//import jakarta.servlet.ServletException;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import org.springframework.core.annotation.Order;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.context.SecurityContextHolder;
//import org.springframework.security.core.userdetails.UserDetails;
//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
//import org.springframework.stereotype.Component;
//import org.springframework.util.ObjectUtils;
//import org.springframework.util.StringUtils;
//import org.springframework.web.filter.OncePerRequestFilter;
//import java.io.IOException;
//
//
//@Component
//public class TokenFilter extends OncePerRequestFilter {
// @Override
// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// // 取Token 生成登录信息
// String token = request.getHeader("token");
//
//
// System.out.println(token+"123132132");
//
// // token不为空
// if (StringUtils.hasText(token)){
// try {
// UserDetails userDetails = JWTUtil.getUserDetailsList(token, Admin.class);
// if ( ! ObjectUtils.isEmpty(userDetails)) {
// // 将这个用户注册到Security中
// UsernamePasswordAuthenticationToken authenticationToken
// = new UsernamePasswordAuthenticationToken(
// userDetails, null,
// userDetails.getAuthorities());
// authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// SecurityContextHolder.getContext().setAuthentication(authenticationToken);
// }
// } catch (Exception e) {
// e.printStackTrace();
// // Token无效
// }
// }
// // 过滤器放行
// filterChain.doFilter(request, response);
// }
//}
//package com.example.demo.security;
//
//import com.example.demo.Util.JWTUtil;
//import com.example.demo.Util.RequestWrapper;
//import com.example.demo.Util.TokenPayload;
//import com.example.demo.domain.entity.Admin;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import jakarta.servlet.FilterChain;
//import jakarta.servlet.ServletException;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import org.springframework.core.annotation.Order;
//import org.springframework.security.access.prepost.PreFilter;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.context.SecurityContextHolder;
//import org.springframework.security.core.userdetails.UserDetails;
//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
//import org.springframework.stereotype.Component;
//import org.springframework.util.ObjectUtils;
//import org.springframework.util.StringUtils;
//import org.springframework.web.filter.OncePerRequestFilter;
//import java.io.IOException;
//import java.io.InputStream;
//
//
//@Component
//public class TokenFilter extends OncePerRequestFilter {
//
// @Override
// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
// throws ServletException, IOException {
// // 使用RequestWrapper包装原始的HttpServletRequest使其输入流可以被重复读取
// RequestWrapper requestWrapper = new RequestWrapper(request);
// // 确保请求体只被读取一次
// boolean hasRequestBody = "POST".equals(requestWrapper.getMethod());
// System.out.println("/*-/*-/*"+requestWrapper.getBodyString());
// if (hasRequestBody) {
// // 获取输入流
// InputStream inputStream = requestWrapper.getInputStream();
// // 使用Jackson ObjectMapper解析JSON
// ObjectMapper objectMapper = new ObjectMapper();
// TokenPayload tokenPayload = objectMapper.readValue(inputStream, TokenPayload.class);
//
// // 检查tokenPayload中是否存在token属性并且这个属性不为空
// String token = tokenPayload.getToken();
// if (StringUtils.hasText(token)) {
// try {
// UserDetails userDetails = JWTUtil.getUserDetailsList(token, Admin.class);
// if (!ObjectUtils.isEmpty(userDetails)) {
// // 将这个用户注册到Security中
// UsernamePasswordAuthenticationToken authenticationToken
// = new UsernamePasswordAuthenticationToken(
// userDetails, null,
// userDetails.getAuthorities());
// authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(requestWrapper));
// SecurityContextHolder.getContext().setAuthentication(authenticationToken);
// }
// } catch (Exception e) {
// e.printStackTrace();
// // Token无效可以在这里添加相应的处理逻辑例如返回401状态码等
// }
// }
// }
// filterChain.doFilter(requestWrapper, response); // 注意这里使用requestWrapper
// }
//}
//package com.example.demo.security;
//
//import com.example.demo.Util.JWTUtil;
//import com.example.demo.Util.RequestWrapper;
//import com.example.demo.Util.TokenPayload;
//import com.example.demo.domain.entity.Admin;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import jakarta.servlet.FilterChain;
//import jakarta.servlet.ServletException;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import org.springframework.core.annotation.Order;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.context.SecurityContextHolder;
//import org.springframework.security.core.userdetails.UserDetails;
//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
//import org.springframework.stereotype.Component;
//import org.springframework.util.ObjectUtils;
//import org.springframework.util.StringUtils;
//import org.springframework.web.filter.OncePerRequestFilter;
//import java.io.IOException;
//import java.io.InputStream;
//
//@Component
//public class TokenFilter extends OncePerRequestFilter {
//
// @Override
// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
// throws ServletException, IOException {
// // 检查是否是上传请求
// boolean isUploadRequest = request.getRequestURI().startsWith("/upload");
// System.out.println(request.getRequestURI());
// System.out.println(isUploadRequest);
// if (isUploadRequest) {
// // 如果是上传请求直接将请求传递给下一个过滤器或目标资源
// filterChain.doFilter(request, response);
// return;
// } else {
// // 使用RequestWrapper包装原始的HttpServletRequest使其输入流可以被重复读取
// RequestWrapper requestWrapper = new RequestWrapper(request);
// System.out.println(request);
// // 确保请求体只被读取一次
// boolean hasRequestBody = "POST".equals(requestWrapper.getMethod());
// if (hasRequestBody) {
// // 获取输入流
// InputStream inputStream = requestWrapper.getInputStream();
// // 使用Jackson ObjectMapper解析JSON
// ObjectMapper objectMapper = new ObjectMapper();
// TokenPayload tokenPayload = objectMapper.readValue(inputStream, TokenPayload.class);
//
// // 检查tokenPayload中是否存在token属性并且这个属性不为空
// String token = tokenPayload.getToken();
// if (StringUtils.hasText(token)) {
// try {
// UserDetails userDetails = JWTUtil.getUserDetailsList(token, Admin.class);
// if (!ObjectUtils.isEmpty(userDetails)) {
// // 将这个用户注册到Security中
// UsernamePasswordAuthenticationToken authenticationToken
// = new UsernamePasswordAuthenticationToken(
// userDetails, null,
// userDetails.getAuthorities());
// authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(requestWrapper));
// SecurityContextHolder.getContext().setAuthentication(authenticationToken);
// }
// } catch (Exception e) {
// e.printStackTrace();
// // Token无效可以在这里添加相应的处理逻辑例如返回401状态码等
// }
// }
// }
// // 非上传请求继续执行过滤器链
// filterChain.doFilter(requestWrapper, response);
// }
// }
//}
package com.example.demo.security;
import com.example.demo.Util.JWTUtil;
import com.example.demo.Util.RequestWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.example.demo.domain.entity.Admin;
import com.example.demo.domain.entity.User;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
@ -214,65 +17,23 @@ import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
@Component
public class TokenFilter extends OncePerRequestFilter {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 检查是否是上传请求
boolean isErpRequest = request.getRequestURI().startsWith("/ERP") || request.getRequestURI().contains("ERP");
boolean isUploadRequest = request.getRequestURI().startsWith("/upload");
System.out.println(request.getRequestURI());
System.out.println(isUploadRequest);
if (isUploadRequest ) {
// 如果是上传请求直接将请求传递给下一个过滤器或目标资源
// 忽略登录接口的token处理防止无限递归
if (request.getRequestURI().startsWith("/admin/login")) {
filterChain.doFilter(request, response);
return;
} else {
// 使用RequestWrapper包装原始的HttpServletRequest使其输入流可以被重复读取
RequestWrapper requestWrapper = new RequestWrapper(request);
System.out.println(request);
// 确保请求体只被读取一次
boolean hasRequestBody = "POST".equals(requestWrapper.getMethod());
if (hasRequestBody) {
// 获取输入流
InputStream inputStream = requestWrapper.getInputStream();
try {
// 尝试将输入流转换为Map<String, Object>
Map<String, Object> jsonMap = objectMapper.readValue(inputStream, new TypeReference<Map<String, Object>>() {});
// 提取并处理token字段
String token = (String) jsonMap.get("token");
/* if (StringUtils.hasText(token)) {
processToken(token, requestWrapper);
}*/
// 处理其他字段如recharge列表
// 这里可以根据需要进一步解析其他字段
} catch (JsonProcessingException e) {
e.printStackTrace();
// JSON解析失败可以在这里添加相应的处理逻辑例如返回400状态码等
}
}
// 非上传请求继续执行过滤器链
filterChain.doFilter(requestWrapper, response);
}
}
/* private void processToken(String token, HttpServletRequest request) {
String token = request.getHeader("token");
if (StringUtils.hasText(token)) {
try {
UserDetails userDetails = JWTUtil.getUserDetailsList(token, Admin.class);
if (!ObjectUtils.isEmpty(userDetails)) {
// 将这个用户注册到Security中
UsernamePasswordAuthenticationToken authenticationToken
= new UsernamePasswordAuthenticationToken(
userDetails, null,
@ -282,11 +43,8 @@ public class TokenFilter extends OncePerRequestFilter {
}
} catch (Exception e) {
e.printStackTrace();
// Token无效可以在这里添加相应的处理逻辑例如返回401状态码等
}
}
}*/
filterChain.doFilter(request, response);
}
}

43
src/main/java/com/example/demo/security/UploadFilter.java

@ -1,43 +0,0 @@
package com.example.demo.security;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.multipart.MultipartResolver;
import java.io.IOException;
@Component
public class UploadFilter extends OncePerRequestFilter {
private final MultipartResolver multipartResolver;
public UploadFilter(MultipartResolver multipartResolver) {
this.multipartResolver = multipartResolver;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 检查请求是否为上传请求这里假设上传请求的路径以 "/upload" 开头
boolean isUploadRequest = request.getRequestURI().startsWith("/upload");
System.out.println(isUploadRequest);
System.out.println("MultipartResolver: " + multipartResolver);
if (isUploadRequest ) {
System.out.println("执行upload-------------------------------");
// 如果是上传请求且Content-Type为multipart/form-data直接将请求传递给下一个过滤器或目标资源
filterChain.doFilter(request, response);
} else {
// 如果不是上传请求执行一些自定义逻辑
// 例如可以在这里添加令牌验证或其他安全检查
// 继续执行过滤器链
filterChain.doFilter(request, response);
}
}
}

15
src/main/java/com/example/demo/service/AdminService.java

@ -0,0 +1,15 @@
package com.example.demo.service;
import com.example.demo.domain.entity.Admin;
/**
* @program: GOLD
* @ClassName adminService
* @description:
* @author: huangqizhen
* @create: 202507-01 10:40
* @Version 1.0
**/
public interface AdminService {
Admin login(Admin admin)throws Exception;
}

19
src/main/java/com/example/demo/service/AiEmotionService.java

@ -0,0 +1,19 @@
package com.example.demo.service;
import com.example.demo.domain.vo.AiEmotionExportRecordVO;
import com.example.demo.domain.vo.ExportVo;
/**
* @program: GOLD
* @ClassName AiEmotionService
* @description:
* @author: huangqizhen
* @create: 202506-29 14:27
* @Version 1.0
**/
public interface AiEmotionService {
int updateStatus(Long recordId, int i, String s, String s1, int i1);
AiEmotionExportRecordVO getRecordById(Long id) throws Exception;
}

15
src/main/java/com/example/demo/service/AuditService.java

@ -1,5 +1,10 @@
package com.example.demo.service;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.RechargeAudit;
import com.example.demo.domain.vo.RefundAudit;
import com.github.pagehelper.PageInfo;
/**
* @program: gold-java
* @ClassName AuditService
@ -11,4 +16,14 @@ package com.example.demo.service;
public interface AuditService {
//审核订单并修改用户余额等
boolean auditOrder(String token, String orderCode, Integer auditId,Integer action,String rejectReason);
//多条件查询充值审核订单
PageInfo<RechargeAudit> selectRechargeBy(Integer pageNum, Integer pageSize, RechargeAudit rechargeAudit);
//多条件查询退款审核订单
PageInfo<RefundAudit> selectRefundBy(Integer pageNum, Integer pageSize, RefundAudit refundAudit);
//充值审核金币合计数
Gold sumRechargeGold(Integer pageNum, Integer pageSize, RechargeAudit rechargeAudit);
//退款审核金币合计数
Gold sumRefundGold(Integer pageNum, Integer pageSize,RefundAudit refundAudit);
}

28
src/main/java/com/example/demo/service/ConsumeService.java

@ -0,0 +1,28 @@
package com.example.demo.service;
import com.example.demo.domain.entity.UserGoldRecord;
import com.example.demo.domain.vo.ConsumeUser;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.Result;
import com.github.pagehelper.PageInfo;
/**
* @program: gold-java
* @ClassName ConsumeService
* @description: 消费模块
* @author: Double
* @create: 202506-23 13:58
* @Version 1.0
**/
public interface ConsumeService {
PageInfo<ConsumeUser> selectAll(Integer pageNum, Integer pageSize, ConsumeUser consumeUser);
Gold statsGold(ConsumeUser consumeUser);
PageInfo<ConsumeUser> selectBy(Integer pageNum, Integer pageSize, ConsumeUser consumeUser);
Result add(ConsumeUser consumeUser);
}

22
src/main/java/com/example/demo/service/ExportExcelService.java

@ -0,0 +1,22 @@
package com.example.demo.service;
import com.example.demo.domain.entity.Export;
import java.util.List;
/**
* @program: GOLD
* @ClassName exportService
* @description:
* @author: huangqizhen
* @create: 202506-28 15:39
* @Version 1.0
**/
public interface ExportExcelService {
Exception handleExcelExportData(String message) throws Exception;
Exception handleExcel(String message) throws Exception;
Exception rechargeExcel(String message) throws Exception;
Exception consumeExcel(String message) throws Exception;
Exception refundExcel(String message) throws Exception;
List<Export> getExcel(Export export);
}

19
src/main/java/com/example/demo/service/GeneralService.java

@ -1,5 +1,9 @@
package com.example.demo.service;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
/**
@ -12,6 +16,21 @@ import java.util.List;
**/
public interface GeneralService {
//获取所有市场地区
List<String> getMarket();
//获取平台
List<String> getPlatform();
//获取商品
List<String> getGoods();
//获取活动
List<String> getActivity();
//获取昨天的日期
Date getYesterday();
//获取某天的开始时间(00:00:00)
Date getStartOfDay(Date date);
//转换日期格式为yyyy-MM-dd
String formatDate(Date date) ;
//获取时间段内的所有日期包含起始和结束日
List<Date> getAllDatesBetween(Date start, Date end);
}

31
src/main/java/com/example/demo/service/GoldDetailService.java

@ -0,0 +1,31 @@
package com.example.demo.service;
import com.example.demo.domain.DTO.GoldDetailDTO;
import com.example.demo.domain.DTO.GoldUserDTO;
import com.example.demo.domain.entity.User;
import com.example.demo.domain.vo.GoldDetail;
import com.example.demo.domain.vo.Result;
import com.example.demo.domain.vo.Total;
import com.github.pagehelper.PageInfo;
/**
* @program: GOLD
* @ClassName GoldDetailService
* @description:
* @author: huangqizhen
* @create: 202506-23 11:59
* @Version 1.0
**/
public interface GoldDetailService {
PageInfo<GoldDetail> getGoldDetail(Integer pageNum, Integer pageSize, GoldDetail goldDetail);
Total getTotal(GoldDetail goldDetail);
PageInfo<User> getGold(Integer pageNum, Integer pageSize, User user);
Total GoldTotal(User user);
//异步导出客户明细
Result addExportRecord(GoldDetailDTO dto);
//异步导出金币余额
Result addExportRecordGold(GoldUserDTO dto);
}

30
src/main/java/com/example/demo/service/PermissionService.java

@ -0,0 +1,30 @@
package com.example.demo.service;
import com.example.demo.domain.entity.Admin;
import com.example.demo.domain.entity.AdminRole;
import com.example.demo.domain.entity.Role;
import com.example.demo.domain.vo.Page;
import com.example.demo.domain.vo.Permission;
import com.github.pagehelper.PageInfo;
import javax.swing.*;
import java.util.List;
/**
* @program: GOLD
* @ClassName PermissionService
* @description:
* @author: huangqizhen
* @create: 202506-26 13:18
* @Version 1.0
**/
public interface PermissionService {
List<String> getposition(String token);
List<String> getmarket(String token);
PageInfo<Permission> getpermission(Integer pageNum, Integer pageSize, Permission permission);
Integer addpermission(Admin admin) throws Exception;
List<Role> getRole(String token);
Integer deleteAdmin(Integer id);
Integer updateAdminRole(AdminRole adminRole);
Integer upadatePermission(Admin admin) throws Exception;
}

16
src/main/java/com/example/demo/service/RateService.java

@ -0,0 +1,16 @@
package com.example.demo.service;
import com.example.demo.domain.entity.Rate;
import com.example.demo.domain.vo.RateDetail;
import com.github.pagehelper.PageInfo;
public interface RateService {
PageInfo<Rate> selectAll(Integer pageNum, Integer pageSize);
Rate selectById(Integer id);
void add(Rate rate);
void update(Rate rate);
}

26
src/main/java/com/example/demo/service/RechargeService.java

@ -0,0 +1,26 @@
package com.example.demo.service;
import com.example.demo.domain.vo.ConsumeUser;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.RechargeUser;
import com.example.demo.domain.vo.Result;
import com.github.pagehelper.PageInfo;
/**
* @program: gold-java
* @ClassName RechargeService
* @description:
* @author: Double
* @create: 202506-29 13:39
* @Version 1.0
**/
public interface RechargeService {
PageInfo<RechargeUser> selectAll(Integer pageNum, Integer pageSize, RechargeUser rechargeUser);
Gold statsGold(RechargeUser rechargeUser);
PageInfo<RechargeUser> selectBy(Integer pageNum, Integer pageSize, RechargeUser rechargeUser);
Result add(RechargeUser rechargeUser);
}

35
src/main/java/com/example/demo/service/RefundService.java

@ -0,0 +1,35 @@
package com.example.demo.service;
import com.example.demo.domain.vo.ConsumeUser;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.RefundUser;
import com.example.demo.domain.vo.Result;
import com.github.pagehelper.PageInfo;
import java.util.List;
/**
* @program: gold-java
* @ClassName RefundService
* @description:
* @author: Double
* @create: 202506-27 11:50
* @Version 1.0
**/
public interface RefundService {
PageInfo<RefundUser> selectAll(Integer pageNum, Integer pageSize, RefundUser refundUser);
Gold statsGold(RefundUser refundUser);
PageInfo<RefundUser> selectBy(Integer pageNum, Integer pageSize, RefundUser refundUser);
Result add(RefundUser refundUser);
//获取退款类型
List<String> getRefundType();
List<RefundUser> selectGoods(Integer jwcode);
}

22
src/main/java/com/example/demo/service/StatisticsService.java

@ -1,5 +1,9 @@
package com.example.demo.service;
import com.example.demo.domain.entity.Statistics;
import java.util.Date;
/**
* @program: gold-java
* @ClassName StatisticsService
@ -11,4 +15,22 @@ package com.example.demo.service;
public interface StatisticsService {
//1点12点18点,23点30分执行定时任务更新当天part1数据
public void runHourlyTaskPart1();
//12点18点执行定时任务更新当天part2数据
public void runHourlyTaskPart2();
//0点执行定时任务更新近一周part2数据
public void runDailyTaskPart2();
//查询某地区某天是否已存在统计数据
public Statistics getExistStatistics(String market,Date date);
//新增或更新或不修改某地区某天part1统计数据
public void saveStatisticsPart1(String market, Date date);
//新增或更新或不修改某地区某天part2统计数据
public void saveStatisticsPart2(String market, Date date);
//根据地区与日期获取part1(余量属性)统计数据
public Statistics getStatisticsPart1(String market, Date date);
//根据地区与日期获取part2(余量外属性)统计数据
public Statistics getStatisticsPart2(String market, Date date);
}

19
src/main/java/com/example/demo/service/UserService.java

@ -0,0 +1,19 @@
package com.example.demo.service;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.GoldUser;
/**
* @program: gold-java
* @ClassName UserService
* @description:
* @author: Double
* @create: 202506-25 10:30
* @Version 1.0
**/
public interface UserService {
GoldUser selectUser(String jwcode);
GoldUser selectgold(String jwcode);
}

22
src/main/java/com/example/demo/service/WorkbenchService.java

@ -1,7 +1,10 @@
package com.example.demo.service;
import com.example.demo.domain.entity.Statistics;
import com.example.demo.domain.vo.WorkbenchCard;
import com.example.demo.domain.vo.WorkbenchMarketCard;
import java.util.Date;
import java.util.List;
/**
@ -15,7 +18,20 @@ import java.util.List;
public interface WorkbenchService {
WorkbenchCard getCard1(String token, List<String>areas);
WorkbenchCard getCard2(String token, List<String>areas);
WorkbenchCard getCard3(String token, List<String>areas);
//获取不同地区的工作台统计卡片
WorkbenchCard getCard(String token);
//获取卡片数据
WorkbenchMarketCard createWorkbenchMarketCard(String market, Statistics statistics, Date yearlyStartDate, Date currentDate);
//获取不同地区的工作台柱状图数据根据类型起止时间地区查询
WorkbenchCard getGraph(String token, Date startDate, Date endDate, List<String> markets);
//根据类型获取年初至今的统计数据
Integer calculateSum(String market, String type, Date startDate,Date endDate);
//获取该日期该市场的日同比
Integer calculateDayOverDay(String market,Date date);
//获取该日期该市场的周环比
Integer calculateWeekOverWeek(String market, Date date);
//获取与传入的日期相差XX天的日期
Date addDays(Date date, int days);
//获取传入时间所在周的第一天周一
Date getStartOfWeek(Date date);
}

84
src/main/java/com/example/demo/service/listen/AiEmotionExportListener.java

@ -0,0 +1,84 @@
package com.example.demo.service.listen;
import cn.hutool.core.util.StrUtil;
import com.example.demo.Util.ExecutionContextUtil;
import com.example.demo.Util.FeiShuAlertUtil;
import com.example.demo.Util.RedisUtil;
import com.example.demo.domain.vo.ExecutionContext;
import com.example.demo.service.ExportExcelService;
import com.example.demo.service.queue.AbstractMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import static java.lang.Thread.sleep;
@Component
public class AiEmotionExportListener extends AbstractMessageListener<String> {
//注入ExportExcelService
@Autowired
private ExportExcelService exportExcelService;
@Autowired
public AiEmotionExportListener(
RedisUtil redisQueueUtil
) {
super(redisQueueUtil, "hwgold:queue:export_queue");
System.out.println("监听器已启动,队列: ");
}
@Override
protected void handleMessage(String message) {
if (StrUtil.isBlank(message)) {
System.err.println("redis消息队列数据为空" + message);
}
try {
Thread.sleep(5000);
exportExcelService.handleExcelExportData(message);
} catch (Exception e) {
logError(e, message);
throw new RuntimeException("Failed to process HWGOLD export: " + e.getMessage(), e);
}
}
private void logError(Exception e, String message) {
System.err.println("Export data listener exception: " + e.getMessage());
e.printStackTrace();
try {
ExecutionContext context = ExecutionContextUtil.getExecutionContext();
String cause = "";
if (e.getCause() != null) {
cause = e.getCause().getMessage();
}
FeiShuAlertUtil.sendAlertMessage(
context,
e.getStackTrace()[0].getFileName(),
e.getStackTrace()[0].getLineNumber(),
"HWGOLD Export Error: " + e.getMessage() + " 底层错误: " + cause ,
"Failed message: " + message
);
} catch (Exception alertEx) {
System.err.println("Failed to send Feishu alert: " + alertEx.getMessage());
}
}
@Override
protected void handleError(Exception e, String message) {
System.err.println("处理消息失败: " + message);
e.printStackTrace();
}
}

81
src/main/java/com/example/demo/service/listen/ConsumeListener.java

@ -0,0 +1,81 @@
package com.example.demo.service.listen;
import cn.hutool.core.util.StrUtil;
import com.example.demo.Export.ExportService;
import com.example.demo.Util.ExecutionContextUtil;
import com.example.demo.Util.FeiShuAlertUtil;
import com.example.demo.Util.RedisUtil;
import com.example.demo.domain.vo.ExecutionContext;
import com.example.demo.service.ExportExcelService;
import com.example.demo.service.queue.AbstractMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @program: GOLD
* @ClassName RechargeListener
* @description:
* @author: huangqizhen
* @create: 202507-01 15:46
* @Version 1.0
**/
@Component
public class ConsumeListener extends AbstractMessageListener<String> {
//注入ExportExcelService
@Autowired
private ExportExcelService exportService;
@Autowired
public ConsumeListener(
RedisUtil redisQueueUtil
) {
super(redisQueueUtil, "consume:queue:export_queue");
System.out.println("监听器已启动,队列: ");
}
@Override
protected void handleMessage(String message) {
if (StrUtil.isBlank(message)) {
System.err.println("redis消息队列数据为空" + message);
}
try {
Thread.sleep(5000);
exportService.consumeExcel(message);
} catch (Exception e) {
logError(e, message);
throw new RuntimeException("Failed to process HWGOLD export: " + e.getMessage(), e);
}
}
private void logError(Exception e, String message) {
System.err.println("Export data listener exception: " + e.getMessage());
e.printStackTrace();
try {
ExecutionContext context = ExecutionContextUtil.getExecutionContext();
String cause = "";
if (e.getCause() != null) {
cause = e.getCause().getMessage();
}
FeiShuAlertUtil.sendAlertMessage(
context,
e.getStackTrace()[0].getFileName(),
e.getStackTrace()[0].getLineNumber(),
"HWGOLD Export Error: " + e.getMessage() + " 底层错误: " + cause ,
"Failed message: " + message
);
} catch (Exception alertEx) {
System.err.println("Failed to send Feishu alert: " + alertEx.getMessage());
}
}
@Override
protected void handleError(Exception e, String message) {
System.err.println("处理消息失败: " + message);
e.printStackTrace();
}
}

82
src/main/java/com/example/demo/service/listen/GoldListener.java

@ -0,0 +1,82 @@
package com.example.demo.service.listen;
import cn.hutool.core.util.StrUtil;
import com.example.demo.Util.ExecutionContextUtil;
import com.example.demo.Util.FeiShuAlertUtil;
import com.example.demo.Util.RedisUtil;
import com.example.demo.domain.vo.ExecutionContext;
import com.example.demo.service.ExportExcelService;
import com.example.demo.service.GoldDetailService;
import com.example.demo.service.queue.AbstractMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @program: GOLD
* @ClassName GoldListener
* @description:
* @author: huangqizhen
* @create: 202507-01 15:43
* @Version 1.0
**/
@Component
public class GoldListener extends AbstractMessageListener<String> {
//注入ExportExcelService
@Autowired
private ExportExcelService exportExcelService;
@Autowired
public GoldListener(
RedisUtil redisQueueUtil
) {
super(redisQueueUtil, "gold:queue:export_queue");
System.out.println("监听器已启动,队列: ");
}
@Override
protected void handleMessage(String message) {
if (StrUtil.isBlank(message)) {
System.err.println("redis消息队列数据为空" + message);
}
try {
Thread.sleep(5000);
exportExcelService.handleExcel(message);
} catch (Exception e) {
logError(e, message);
throw new RuntimeException("Failed to process HWGOLD export: " + e.getMessage(), e);
}
}
private void logError(Exception e, String message) {
System.err.println("Export data listener exception: " + e.getMessage());
e.printStackTrace();
try {
ExecutionContext context = ExecutionContextUtil.getExecutionContext();
String cause = "";
if (e.getCause() != null) {
cause = e.getCause().getMessage();
}
FeiShuAlertUtil.sendAlertMessage(
context,
e.getStackTrace()[0].getFileName(),
e.getStackTrace()[0].getLineNumber(),
"HWGOLD Export Error: " + e.getMessage() + " 底层错误: " + cause ,
"Failed message: " + message
);
} catch (Exception alertEx) {
System.err.println("Failed to send Feishu alert: " + alertEx.getMessage());
}
}
@Override
protected void handleError(Exception e, String message) {
System.err.println("处理消息失败: " + message);
e.printStackTrace();
}
}

81
src/main/java/com/example/demo/service/listen/RechargeListener.java

@ -0,0 +1,81 @@
package com.example.demo.service.listen;
import cn.hutool.core.util.StrUtil;
import com.example.demo.Export.ExportService;
import com.example.demo.Util.ExecutionContextUtil;
import com.example.demo.Util.FeiShuAlertUtil;
import com.example.demo.Util.RedisUtil;
import com.example.demo.domain.vo.ExecutionContext;
import com.example.demo.service.ExportExcelService;
import com.example.demo.service.queue.AbstractMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @program: GOLD
* @ClassName RechargeListener
* @description:
* @author: huangqizhen
* @create: 202507-01 15:46
* @Version 1.0
**/
@Component
public class RechargeListener extends AbstractMessageListener<String> {
//注入ExportExcelService
@Autowired
private ExportExcelService exportService;
@Autowired
public RechargeListener(
RedisUtil redisQueueUtil
) {
super(redisQueueUtil, "recharge:queue:export_queue");
System.out.println("监听器已启动,队列: ");
}
@Override
protected void handleMessage(String message) {
if (StrUtil.isBlank(message)) {
System.err.println("redis消息队列数据为空" + message);
}
try {
Thread.sleep(5000);
exportService.rechargeExcel(message);
} catch (Exception e) {
logError(e, message);
throw new RuntimeException("Failed to process HWGOLD export: " + e.getMessage(), e);
}
}
private void logError(Exception e, String message) {
System.err.println("Export data listener exception: " + e.getMessage());
e.printStackTrace();
try {
ExecutionContext context = ExecutionContextUtil.getExecutionContext();
String cause = "";
if (e.getCause() != null) {
cause = e.getCause().getMessage();
}
FeiShuAlertUtil.sendAlertMessage(
context,
e.getStackTrace()[0].getFileName(),
e.getStackTrace()[0].getLineNumber(),
"HWGOLD Export Error: " + e.getMessage() + " 底层错误: " + cause ,
"Failed message: " + message
);
} catch (Exception alertEx) {
System.err.println("Failed to send Feishu alert: " + alertEx.getMessage());
}
}
@Override
protected void handleError(Exception e, String message) {
System.err.println("处理消息失败: " + message);
e.printStackTrace();
}
}

81
src/main/java/com/example/demo/service/listen/RefundListener.java

@ -0,0 +1,81 @@
package com.example.demo.service.listen;
import cn.hutool.core.util.StrUtil;
import com.example.demo.Export.ExportService;
import com.example.demo.Util.ExecutionContextUtil;
import com.example.demo.Util.FeiShuAlertUtil;
import com.example.demo.Util.RedisUtil;
import com.example.demo.domain.vo.ExecutionContext;
import com.example.demo.service.ExportExcelService;
import com.example.demo.service.queue.AbstractMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @program: GOLD
* @ClassName RechargeListener
* @description:
* @author: huangqizhen
* @create: 202507-01 15:46
* @Version 1.0
**/
@Component
public class RefundListener extends AbstractMessageListener<String> {
//注入ExportExcelService
@Autowired
private ExportExcelService exportExcelService;
@Autowired
public RefundListener(
RedisUtil redisQueueUtil
) {
super(redisQueueUtil, "refund:queue:export_queue");
System.out.println("监听器已启动,队列: ");
}
@Override
protected void handleMessage(String message) {
if (StrUtil.isBlank(message)) {
System.err.println("redis消息队列数据为空" + message);
}
try {
Thread.sleep(5000);
exportExcelService.refundExcel(message);
} catch (Exception e) {
logError(e, message);
throw new RuntimeException("Failed to process HWGOLD export: " + e.getMessage(), e);
}
}
private void logError(Exception e, String message) {
System.err.println("Export data listener exception: " + e.getMessage());
e.printStackTrace();
try {
ExecutionContext context = ExecutionContextUtil.getExecutionContext();
String cause = "";
if (e.getCause() != null) {
cause = e.getCause().getMessage();
}
FeiShuAlertUtil.sendAlertMessage(
context,
e.getStackTrace()[0].getFileName(),
e.getStackTrace()[0].getLineNumber(),
"HWGOLD Export Error: " + e.getMessage() + " 底层错误: " + cause ,
"Failed message: " + message
);
} catch (Exception alertEx) {
System.err.println("Failed to send Feishu alert: " + alertEx.getMessage());
}
}
@Override
protected void handleError(Exception e, String message) {
System.err.println("处理消息失败: " + message);
e.printStackTrace();
}
}

69
src/main/java/com/example/demo/service/queue/AbstractMessageListener.java

@ -0,0 +1,69 @@
package com.example.demo.service.queue;
import com.example.demo.Util.RedisUtil;
import jakarta.annotation.PostConstruct;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 抽象消息监听器
*/
public abstract class AbstractMessageListener<T> {
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
protected final RedisUtil redisQueueUtil;
protected final String queueName;
public AbstractMessageListener(RedisUtil redisQueueUtil, String queueName) {
this.redisQueueUtil = redisQueueUtil;
this.queueName = queueName;
}
@PostConstruct
public void init() {
executorService.submit(this::listen);
}
private void listen() {
System.out.println("消费者消费数据" + queueName + "<UNK>");
while (!Thread.currentThread().isInterrupted()) {
try {
Object message = redisQueueUtil.blockingGetMessage(queueName, 1);
if (message != null) {
try {
handleMessage((T) message);
} catch (Exception e) {
handleError(e, (T) message);
}
}
} catch (Exception e) {
System.err.println("监听队列异常: " + e.getMessage());
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}
/**
* 处理消息
* @param message 消息内容
*/
protected abstract void handleMessage(T message);
/**
* 处理错误
* @param e 异常
* @param message 消息内容
*/
protected void handleError(Exception e, T message) {
System.err.println("处理消息异常: " + e.getMessage());
}
}

74
src/main/java/com/example/demo/serviceImpl/AdminServiceImpl.java

@ -0,0 +1,74 @@
package com.example.demo.serviceImpl;
import com.example.demo.domain.entity.Admin;
import com.example.demo.mapper.AdminMapper;
import com.example.demo.service.AdminService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
public class AdminServiceImpl implements AdminService {
private static final Logger log = LoggerFactory.getLogger(AdminServiceImpl.class);
private final AuthenticationManager authenticationManager;
private final AdminMapper adminMapper;
@Override
public Admin login(Admin admin) throws Exception {
String account = admin.getAccount();
String inputMachineId = admin.getMachineId();
if (StringUtils.isBlank(account)) {
throw new IllegalArgumentException("账号不能为空");
}
// Admin adminInDB = adminMapper.getAdmin(account);
// System.out.println("adminInDB:" + adminInDB);
// if (adminInDB == null) {
// throw new RuntimeException("无此精网号");
// }
// 校验机器权限
// if (!hasPermissionToMachine(adminInDB, inputMachineId)) {
// throw new RuntimeException("你没有使用该机器的权限!");
// }
// try {
System.out.println("admin:" + account);
System.out.println("admin:" + admin.getPassword());
UsernamePasswordAuthenticationToken token =
new UsernamePasswordAuthenticationToken(account,admin.getPassword());
Authentication authentication = authenticationManager.authenticate(token);
return (Admin) authentication.getPrincipal();
// } catch (Exception e) {
// System.out.println("密码错误"+e.getMessage());
// log.error("登录过程中发生异常", e);
// throw new RuntimeException("登录失败,请稍后再试", e);
// }
}
private boolean hasPermissionToMachine(Admin admin, String targetMachineId) {
if (targetMachineId == null || admin.getMachineId() == null) {
return false;
}
String[] machineIds = admin.getMachineId().split(",");
for (String id : machineIds) {
if (targetMachineId.equals(id)) {
return true;
}
}
return false;
}
}

35
src/main/java/com/example/demo/serviceImpl/AiEmotionServiceImpl.java

@ -0,0 +1,35 @@
package com.example.demo.serviceImpl;
import com.example.demo.domain.vo.AiEmotionExportRecordVO;
import com.example.demo.domain.vo.ExportVo;
import com.example.demo.mapper.AiEmotionMapper;
import com.example.demo.mapper.ExportMapper;
import com.example.demo.service.AiEmotionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @program: GOLD
* @ClassName AiEmotionServiceImpl
* @description:
* @author: huangqizhen
* @create: 202506-29 14:46
* @Version 1.0
**/
@Service
public class AiEmotionServiceImpl implements AiEmotionService {
@Autowired
private ExportMapper exportMapper;
@Autowired
private AiEmotionMapper aiEmotionMapper;
@Override
public int updateStatus(Long recordId, int i, String s, String s1, int i1) {
return exportMapper.updateExportData(recordId, i, s, s1, i1);
}
@Override
public AiEmotionExportRecordVO getRecordById(Long id) throws Exception {
return aiEmotionMapper.getRecordById(id);
}
}

173
src/main/java/com/example/demo/serviceImpl/AuditServiceImpl.java

@ -1,6 +1,19 @@
package com.example.demo.serviceImpl;
import com.example.demo.domain.entity.User;
import com.example.demo.domain.entity.UserGoldRecord;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.RechargeAudit;
import com.example.demo.domain.vo.RefundAudit;
import com.example.demo.mapper.AuditMapper;
import com.example.demo.service.AuditService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
/**
* @program: gold-java
@ -11,6 +24,164 @@ import com.example.demo.service.AuditService;
* @Version 1.0
**/
@Service
public class AuditServiceImpl implements AuditService {
@Autowired
private AuditMapper auditMapper;
/*
审核订单并修改用户余额等
*/
@Override
public boolean auditOrder(String token, String orderCode, Integer auditId, Integer action,String rejectReason) {
UserGoldRecord order=auditMapper.selectOrderByOrderCode(orderCode);
if (order == null || order.getAuditStatus() != 0) {
throw new IllegalArgumentException("订单不存在或已被审核");
}
//更新订单的审核状态和审核人
UserGoldRecord updateOrder = new UserGoldRecord();
updateOrder.setOrderCode(orderCode);
updateOrder.setAuditId(auditId);
//判断是通过还是驳回
if (action==2){ //驳回
updateOrder.setAuditStatus(2);
updateOrder.setRejectReason(rejectReason);
updateOrder.setAuditTime(new Date());
auditMapper.updateOrder(updateOrder);
if (order.getType()==2) { //退款
//2.获取对应的消费订单退款订单号去掉开头"TK"即为对应消费订单
String consumeOrderCode = order.getOrderCode().replaceFirst("TK", "");
//3.更新消费订单是否已退款状态为0
UserGoldRecord consumeOrder = auditMapper.selectOrderByOrderCode(consumeOrderCode);
if (consumeOrderCode != null&&consumeOrder.getType()==1){ //确保是消费订单
auditMapper.updateOrderRefund(consumeOrderCode,(byte)0);
}else {
throw new IllegalArgumentException("找不到对应的订单或不是有效订单");
}
}
}else if (action==1) { //通过
updateOrder.setAuditStatus(1);
updateOrder.setAuditTime(new Date());
}
// 执行审核更新
auditMapper.updateOrder(updateOrder);
//判断是充值还是退款
if (order.getType()==0){ //充值
//更新用户余额
User update = new User();
update.setJwcode(order.getJwcode()); //精网号
update.setSumPermanentGold(order.getPermanentGold()); //历史永久金币
update.setSumFreeJune(order.getFreeJune()); //历史六月免费金币
update.setSumFreeDecember(order.getFreeDecember()); //历史十二月免费金币
update.setSumTaskGold(order.getTaskGold()); //历史任务金币
update.setCurrentPermanentGold(order.getPermanentGold()); //当前永久金币
update.setCurrentFreeJune(order.getFreeJune()); //当前六月免费金币
update.setCurrentFreeDecember(order.getFreeDecember()); //当前十二月免费金币
update.setCurrentTaskGold(order.getTaskGold()); //当前任务金币
auditMapper.updateUserGold(update);
}else if (order.getType()==2) { //退款
//更新用户余额
User update = new User();
update.setJwcode(order.getJwcode());
update.setCurrentPermanentGold(order.getPermanentGold()); //当前永久金币
update.setCurrentFreeJune(order.getFreeJune()); //当前六月免费金币
update.setCurrentFreeDecember(order.getFreeDecember()); //当前十二月免费金币
update.setCurrentTaskGold(order.getTaskGold()); //当前任务金币
auditMapper.updateUserGold(update);
}
return true;
}
/*
* 多条件查询充值订单列表
*/
@Override
public PageInfo<RechargeAudit> selectRechargeBy(Integer pageNum, Integer pageSize, RechargeAudit rechargeAudit) {
PageHelper.startPage(pageNum, pageSize);
List<RechargeAudit> rechargeAudits = auditMapper.selectRechargeBy(pageNum, pageSize, rechargeAudit);
// rechargeAudit.setFreeGold(rechargeAudit.getFreeJune()+rechargeAudit.getFreeDecember());
return new PageInfo<>(rechargeAudits);
}
/*
多条件查询退款订单
*/
@Override
public PageInfo<RefundAudit> selectRefundBy(Integer pageNum, Integer pageSize, RefundAudit refundAudit) {
PageHelper.startPage(pageNum, pageSize);
List<RefundAudit> refundAudits = auditMapper.selectRefundBy(pageNum, pageSize, refundAudit);
//refundAudit.setFreeGold(refundAudit.getFreeJune()+refundAudit.getFreeDecember());
return new PageInfo<>(refundAudits);
}
/*
充值审核金币合计数
*/
@Override
public Gold sumRechargeGold(Integer pageNum, Integer pageSize, RechargeAudit rechargeAudit) {
Gold gold = new Gold();
//获取充值审核订单列表
List<RechargeAudit> rechargeAudits = auditMapper.selectRechargeBy(1, 500000, rechargeAudit);
// 初始化累加器
int totalNum=0;
int permanentGoldSum = 0;
int freeGoldSum = 0;
// 遍历消费记录并累加金币
for (RechargeAudit recharge : rechargeAudits) {
// 累加永久金币
if (recharge.getPermanentGold() != null) {
permanentGoldSum += recharge.getPermanentGold();
}
// 累加免费金币
if (recharge.getFreeJune() != null||recharge.getFreeDecember() != null) {
freeGoldSum = freeGoldSum+recharge.getFreeJune()+recharge.getFreeDecember();
}
// 每遍历一条记录总条数加1
totalNum++;
}
// 将累加结果设置到Gold对象
gold.setPermanentGolds(permanentGoldSum);
gold.setFreeGolds(freeGoldSum);
gold.setTotalNum(totalNum);
return gold;
}
/*
退款审核合计数
*/
@Override
public Gold sumRefundGold(Integer pageNum, Integer pageSize, RefundAudit refundAudit) {
Gold gold = new Gold();
//获取充值审核订单列表
List<RefundAudit> refundAudits = auditMapper.selectRefundBy(1, 500000, refundAudit);
// 初始化累加器
int totalNum=0;
int permanentGoldSum = 0;
int freeGoldSum = 0;
int taskGoldSum = 0;
// 遍历消费记录并累加金币
for (RefundAudit refund : refundAudits) {
// 累加永久金币
if (refund.getPermanentGold() != null) {
permanentGoldSum += refund.getPermanentGold();
}
// 累加免费金币
if (refund.getFreeJune() != null||refund.getFreeDecember()!=null) {
freeGoldSum += refund.getFreeJune()+refund.getFreeDecember();
}
//累加任务金币
if(refund.getTaskGold()!=null)
taskGoldSum+=refund.getTaskGold();
// 每遍历一条记录总条数加1
totalNum++;
}
// 将累加结果设置到Gold对象
gold.setPermanentGolds(permanentGoldSum);
gold.setFreeGolds(freeGoldSum);
gold.setTotalNum(totalNum);
gold.setTaskGolds(taskGoldSum);
return gold;
}
}

169
src/main/java/com/example/demo/serviceImpl/ConsumeServiceImpl.java

@ -0,0 +1,169 @@
package com.example.demo.serviceImpl;
import com.example.demo.Util.GoldTistV2;
import com.example.demo.domain.entity.User;
import com.example.demo.domain.entity.UserGoldRecord;
import com.example.demo.domain.vo.ConsumeUser;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.GoldUser;
import com.example.demo.domain.vo.Result;
import com.example.demo.mapper.ConsumeMapper;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.ConsumeService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @program: gold-java
* @ClassName ConsumeServiceImpl
* @description: 消费模块
* @author: Double
* @create: 202506-23 13:58
* @Version 1.0
**/
@Service
public class ConsumeServiceImpl implements ConsumeService {
@Autowired
private ConsumeMapper consumeMapper;
@Autowired
private UserMapper userMapper;
//消耗明细
@Override
public PageInfo<ConsumeUser> selectAll(Integer pageNum, Integer pageSize, ConsumeUser consumeUser) {
PageHelper.startPage(pageNum, pageSize);
List<ConsumeUser> consumeUsers = consumeMapper.selectAll(consumeUser);
return new PageInfo<>(consumeUsers);
}
//消耗金币统计
@Override
public Gold statsGold(ConsumeUser consumeUser) {
Gold gold = new Gold();
List<ConsumeUser> consumeUsers = consumeMapper.selectBy(consumeUser);
// 初始化累加器
int permanentGoldSum = 0;
int freeGoldSum = 0;
int taskGoldSum = 0;
// 遍历消费记录并累加金币
for (ConsumeUser user : consumeUsers) {
// 累加永久金币
if (user.getPermanentGold() != null) {
permanentGoldSum += user.getPermanentGold();
}
// 累加免费金币
if (user.getFreeGold() != null) {
freeGoldSum += user.getFreeGold();
}
// 累加任务金币
if (user.getTaskGold() != null) {
taskGoldSum += user.getTaskGold();
}
}
// 将累加结果设置到Gold对象
gold.setPermanentGolds(permanentGoldSum);
gold.setFreeGolds(freeGoldSum);
gold.setTaskGolds(taskGoldSum);
return gold;
}
//消耗明细筛选
@Override
public PageInfo<ConsumeUser> selectBy(Integer pageNum, Integer pageSize, ConsumeUser consumeUser) {
PageHelper.startPage(pageNum, pageSize);
List<ConsumeUser> consumeUsers = consumeMapper.selectBy(consumeUser);
return new PageInfo<>(consumeUsers);
}
//新增消耗
@Override
public Result add(ConsumeUser consumeUser) {
UserGoldRecord userGoldRecord = new UserGoldRecord();
// 获取当前时间戳部分
String timestampPart = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
// 获取自增计数器部分三位数不足补零
AtomicInteger atomicInteger = new AtomicInteger(0);
int count = atomicInteger.getAndUpdate(c -> (c >= 999) ? 0 : c + 1);
String counterPart = String.format("%03d", count);
//订单号生成
userGoldRecord.setOrderCode("XF" + timestampPart + counterPart);
userGoldRecord.setJwcode(consumeUser.getJwcode());
userGoldRecord.setGoodsName(consumeUser.getGoodsName());
userGoldRecord.setSumGold(consumeUser.getSumGold());
userGoldRecord.setPermanentGold(consumeUser.getPermanentGold());
// 获取当前月份1-12
int currentMonth = LocalDate.now().getMonthValue();
GoldUser gold = userMapper.selectGold(consumeUser.getJwcode().toString());
if (consumeUser.getFreeGold() > (gold.getNowFreeDecember() + gold.getNowFreeJune()) || consumeUser.getPermanentGold() > gold.getNowPermanentGold()
|| consumeUser.getTaskGold() > gold.getNowTaskGold()) {
return Result.error("金币数量不足");
}
// 根据当前月份设置对应字段
if (currentMonth >= 1 && currentMonth <= 6) {
// 1-6月设置6月额度12月保持默认值
if (consumeUser.getFreeGold() > gold.getNowFreeJune()) {
userGoldRecord.setFreeJune(gold.getNowFreeJune());
userGoldRecord.setFreeDecember(consumeUser.getFreeGold() - gold.getNowFreeJune());
} else {
userGoldRecord.setFreeJune(consumeUser.getFreeGold());
userGoldRecord.setFreeDecember(0);
}
} else {
// 7-12月设置12月额度6月保持默认值
if (consumeUser.getFreeGold() > gold.getNowFreeDecember()) {
userGoldRecord.setFreeDecember(gold.getNowFreeDecember());
userGoldRecord.setFreeJune(consumeUser.getFreeGold() - gold.getNowFreeDecember());
} else {
userGoldRecord.setFreeDecember(consumeUser.getFreeGold());
userGoldRecord.setFreeJune(0);
}
}
userGoldRecord.setTaskGold(consumeUser.getTaskGold());
userGoldRecord.setRemark(consumeUser.getRemark());
userGoldRecord.setType((byte) 1);
userGoldRecord.setIsRefund((byte) 0);
userGoldRecord.setPayPlatform("金币系统");
userGoldRecord.setAdminId(consumeUser.getAdminId());
userGoldRecord.setAuditStatus(1);
userGoldRecord.setCreateTime(new Date());
userGoldRecord.setPayTime(new Date());
consumeMapper.add(userGoldRecord);
User user = new User();
user.setJwcode(userGoldRecord.getJwcode());
user.setCurrentPermanentGold(gold.getNowPermanentGold() - consumeUser.getPermanentGold());
user.setCurrentFreeJune(gold.getNowFreeJune() - userGoldRecord.getFreeJune());
user.setCurrentFreeDecember(gold.getNowFreeDecember() - userGoldRecord.getFreeDecember());
user.setCurrentTaskGold(gold.getNowTaskGold() - consumeUser.getTaskGold());
user.setConsumeNum(gold.getConsumeNum() + 1);
user.setSumConsume(consumeUser.getPermanentGold() + consumeUser.getFreeGold() + consumeUser.getTaskGold());
userMapper.updateGold(user);
//对接接口
// GoldTistV2.addCoinNew(userGoldRecord.getJwcode().toString(), 65,
// (double) (userGoldRecord.getPermanentGold() + userGoldRecord.getFreeDecember() + userGoldRecord.getFreeJune() + userGoldRecord.getTaskGold()) /100,
// userGoldRecord.getRemark(),((double) userGoldRecord.getPermanentGold() /100), userGoldRecord.getPayPlatform(), userGoldRecord.getGoodsName());
return Result.success();
}
}

1102
src/main/java/com/example/demo/serviceImpl/ExportExcelServiceImpl.java
File diff suppressed because it is too large
View File

71
src/main/java/com/example/demo/serviceImpl/GeneralServiceImpl.java

@ -5,6 +5,12 @@ import com.example.demo.service.GeneralService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
@ -32,4 +38,69 @@ public class GeneralServiceImpl implements GeneralService {
List<String> list = generalMapper.getPlatform();
return list;
}
@Override
public List<String> getGoods() {
List<String> list = generalMapper.getGoods();
return list;
}
@Override
public List<String> getActivity() {
List<String> list = generalMapper.getActivity();
return list;
}
/*
获取昨天的日期
*/
@Override
public Date getYesterday() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, -1); //当前天数-1
return getStartOfDay(cal.getTime()); //昨天的00:00:00
}
/*
获取某天的开始时间(00:00:00)
*/
@Override
public Date getStartOfDay(Date date) {
LocalDateTime localDate = date.toInstant()
.atZone(ZoneId.systemDefault()) // 转换为本地时区
.toLocalDateTime()
.with(LocalTime.MIN); // 设置时间为当天 00:00:00
return Date.from(localDate.atZone(ZoneId.systemDefault()).toInstant());
}
/*
转换日期格式为yyyy-MM-dd
*/
@Override
public String formatDate(Date date) {
return date.toInstant()
.atZone(ZoneId.systemDefault())
.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE); // 输出格式如 "2025-10-01"
}
/*
获取时间段内的所有日期包含起始和结束日
*/
@Override
public List<Date> getAllDatesBetween(Date start, Date end) {
List<Date> dates = new ArrayList<>();
//初始化日历对象
Calendar tempStart = Calendar.getInstance();
tempStart.setTime(start);
Calendar tempEnd = Calendar.getInstance();
tempEnd.setTime(end);
while (!tempStart.after(tempEnd)) {
dates.add(tempStart.getTime()); // 将当前日期添加到列表中
tempStart.add(Calendar.DAY_OF_YEAR, 1); // 每次增加一天
}
return dates;
}
}

168
src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java

@ -0,0 +1,168 @@
package com.example.demo.serviceImpl;
import com.example.demo.Util.RedisUtil;
import com.example.demo.domain.DTO.GoldDetailDTO;
import com.example.demo.domain.DTO.GoldUserDTO;
import com.example.demo.domain.entity.User;
import com.example.demo.domain.vo.GoldDetail;
import com.example.demo.domain.vo.Result;
import com.example.demo.domain.vo.Total;
import com.example.demo.exception.SystemException;
import com.example.demo.mapper.GoldDetailMapper;
import com.example.demo.service.GoldDetailService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @program: GOLD
* @ClassName GoldDetailServiceImpl
* @description:
* @author: huangqizhen
* @create: 202506-23 13:44
* @Version 1.0
**/
@Service
public class GoldDetailServiceImpl implements GoldDetailService {
@Autowired
private GoldDetailMapper goldDetailMapper;
@Autowired
private RedisUtil redisUtil;
@Override
public PageInfo<GoldDetail> getGoldDetail(Integer pageNum, Integer pageSize, GoldDetail goldDetail) {
PageHelper.startPage(pageNum, pageSize);
List<GoldDetail> list = goldDetailMapper.getGoldDetail(goldDetail);
return new PageInfo<>(list);
}
@Override
public Total getTotal(GoldDetail goldDetail) {
return goldDetailMapper.getTotal(goldDetail);
}
@Override
public PageInfo<User> getGold(Integer pageNum, Integer pageSize, User user) {
PageHelper.startPage(pageNum, pageSize);
List<User> list = goldDetailMapper.getGold(user);
return new PageInfo<>(list);
}
@Override
public Total GoldTotal(User user) {
return goldDetailMapper.GoldTotal(user);
}
@Override
public Result addExportRecord(GoldDetailDTO dto) {
// 获取操作者 jwcode
// 生成文件名
String fileName = String.format("%s_%s_%s.xlsx",
"客户金币明细",
"操作人",
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
System.out.println(fileName);
dto.setAccount(123456);
dto.setUrl("");
dto.setFileName(fileName);
dto.setDataNum(0);
try{
// 调用方式
GoldDetailMapper.ExportRecordIdHolder idHolder = new GoldDetailMapper.ExportRecordIdHolder();
goldDetailMapper.insertExportRecord(
idHolder, // 用于接收主键
dto.getAccount(),
dto.getType(),
dto.getState(),
dto.getUrl(),
dto.getFileName(),
dto.getDataNum()
);
// 获取主键
Long recordId = idHolder.getId();
// 2. 构造完整的 JSON 数据包含所有请求参数
Map<String, Object> exportData = new HashMap<>();
exportData.put("recordId", recordId);
// 手动构造请求数据避免 toString() 只返回部分字段
Map<String, Object> requestData = new HashMap<>();
requestData.put("text", dto.getText());
requestData.put("sort", dto.getSort());
requestData.put("field", dto.getField());
requestData.put("deptId", dto.getDeptid());
exportData.put("requestData", requestData);
// 3. 发送到 Redis 消息队列
String jsonData = new ObjectMapper().writeValueAsString(exportData);
redisUtil.sendMessage("hwgold:queue:export_queue", jsonData);
}catch (Exception e){
e.printStackTrace();
throw new SystemException("导出数据异常,请稍后重试", e);
}
return Result.success();
}
@Override
public Result addExportRecordGold(GoldUserDTO dto) {
// 生成文件名
String fileName = String.format("%s_%s_%s.xlsx",
"金币余额明细",
"操作人",
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
System.out.println(fileName);
dto.setAccount(123456);
dto.setUrl("");
dto.setFileName(fileName);
dto.setDataNum(0);
try{
// 调用方式
GoldDetailMapper.ExportRecordIdHolder idHolder = new GoldDetailMapper.ExportRecordIdHolder();
goldDetailMapper.insertExportRecord(
idHolder, // 用于接收主键
dto.getAccount(),
dto.getType(),
dto.getState(),
dto.getUrl(),
dto.getFileName(),
dto.getDataNum()
);
// 获取主键
Long recordId = idHolder.getId();
// 2. 构造完整的 JSON 数据包含所有请求参数
Map<String, Object> exportData = new HashMap<>();
exportData.put("recordId", recordId);
// 手动构造请求数据避免 toString() 只返回部分字段
Map<String, Object> requestData = new HashMap<>();
requestData.put("text", dto.getText());
requestData.put("sort", dto.getSort());
requestData.put("field", dto.getField());
requestData.put("deptId", dto.getDeptid());
exportData.put("requestData", requestData);
// 3. 发送到 Redis 消息队列
String jsonData = new ObjectMapper().writeValueAsString(exportData);
redisUtil.sendMessage("gold:queue:export_queue", jsonData);
}catch (Exception e){
e.printStackTrace();
throw new SystemException("导出数据异常,请稍后重试", e);
}
return Result.success();
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save