Browse Source

可跑(不合并)

huangqizheng/feature-20250701172715-异步导出
huangqizhen 8 hours ago
parent
commit
dc95d625e6
  1. 25
      src/main/java/com/example/demo/Export/ExportService.java
  2. 177
      src/main/java/com/example/demo/Export/ExportServiceImpl.java
  3. 43
      src/main/java/com/example/demo/controller/AdminController.java
  4. 75
      src/main/java/com/example/demo/controller/ExportController.java
  5. 19
      src/main/java/com/example/demo/controller/GoldDetailController.java
  6. 42
      src/main/java/com/example/demo/domain/DTO/ConsumeDTO.java
  7. 6
      src/main/java/com/example/demo/domain/DTO/GoldDetailDTO.java
  8. 42
      src/main/java/com/example/demo/domain/DTO/GoldUserDTO.java
  9. 43
      src/main/java/com/example/demo/domain/DTO/RechargeDTO.java
  10. 42
      src/main/java/com/example/demo/domain/DTO/RefundDTO.java
  11. 66
      src/main/java/com/example/demo/domain/entity/Admin.java
  12. 6
      src/main/java/com/example/demo/mapper/ExportMapper.java
  13. 2
      src/main/java/com/example/demo/mapper/GoldDetailMapper.java
  14. 268
      src/main/java/com/example/demo/security/TokenFilter.java
  15. 43
      src/main/java/com/example/demo/security/UploadFilter.java
  16. 15
      src/main/java/com/example/demo/service/AdminService.java
  17. 2
      src/main/java/com/example/demo/service/AiEmotionService.java
  18. 10
      src/main/java/com/example/demo/service/ExportExcelService.java
  19. 6
      src/main/java/com/example/demo/service/GoldDetailService.java
  20. 4
      src/main/java/com/example/demo/service/listen/AiEmotionExportListener.java
  21. 81
      src/main/java/com/example/demo/service/listen/ConsumeListener.java
  22. 82
      src/main/java/com/example/demo/service/listen/GoldListener.java
  23. 81
      src/main/java/com/example/demo/service/listen/RechargeListener.java
  24. 81
      src/main/java/com/example/demo/service/listen/RefundListener.java
  25. 64
      src/main/java/com/example/demo/serviceImpl/AdminServiceImpl.java
  26. 2
      src/main/java/com/example/demo/serviceImpl/AiEmotionServiceImpl.java
  27. 877
      src/main/java/com/example/demo/serviceImpl/ExportExcelServiceImpl.java
  28. 52
      src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java
  29. 4
      src/main/resources/mapper/AiEmotionMapper.xml
  30. 10
      src/main/resources/mapper/ExportMapper.xml
  31. 4
      src/main/resources/mapper/GoldDetailMapper.xml
  32. 6
      src/main/resources/mapper/PermissionMapper.xml

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();
}
}

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());
}
}
}

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

@ -1,12 +1,24 @@
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
@ -21,8 +33,67 @@ import org.springframework.web.bind.annotation.*;
@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 null;
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);
}
}
}

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

@ -3,6 +3,7 @@ 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;
@ -89,4 +90,22 @@ public class GoldDetailController {
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);
}
}
}

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
);
}
}

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

@ -22,7 +22,7 @@ public class GoldDetailDTO {
private String fileName = "";
private Integer sort = 0;
private String field = "";
private Integer jwcode;
private Integer account;
private Integer type = 0; //类型
private Integer state = 0; //状态
private String text = ""; //关键词搜索
@ -37,8 +37,8 @@ public class GoldDetailDTO {
@Override
public String toString() {
return String.format(
"AiEmotionExport(jwcode=%d, type=%d, state=%d, dataNum=%d)",
jwcode, type, state, dataNum
"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
);
}
}

66
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
@ -30,4 +32,60 @@ 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;
}
}

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

@ -1,8 +1,11 @@
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
@ -14,6 +17,7 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ExportMapper {
ExportVo getExportData(Integer id);
ExportVo updateExportData(Long recordId, Integer state, String url, String reason, Integer dataNum);
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/GoldDetailMapper.java

@ -29,7 +29,7 @@ public interface GoldDetailMapper {
}
void insertExportRecord(
@Param("recordId") ExportRecordIdHolder recordId, // 用于接收主键
@Param("jwcode") Integer jwcode,
@Param("account") Integer account,
@Param("type") Integer type,
@Param("state") Integer state,
@Param("url") String url,

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

@ -1,209 +1,14 @@
//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 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;
@ -212,66 +17,24 @@ 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;
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 ) {
// 如果是上传请求直接将请求传递给下一个过滤器或目标资源
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();
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 取Token 生成登录信息
String token = request.getHeader("token");
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);
}*/
System.out.println(token+"123132132");
// 处理其他字段如recharge列表
// 这里可以根据需要进一步解析其他字段
} catch (JsonProcessingException e) {
e.printStackTrace();
// JSON解析失败可以在这里添加相应的处理逻辑例如返回400状态码等
}
}
// 非上传请求继续执行过滤器链
filterChain.doFilter(requestWrapper, response);
}
}
/* private void processToken(String token, HttpServletRequest request) {
if (StringUtils.hasText(token)) {
// token不为空
if (StringUtils.hasText(token)){
try {
UserDetails userDetails = JWTUtil.getUserDetailsList(token, Admin.class);
if (!ObjectUtils.isEmpty(userDetails)) {
if ( ! ObjectUtils.isEmpty(userDetails)) {
// 将这个用户注册到Security中
UsernamePasswordAuthenticationToken authenticationToken
= new UsernamePasswordAuthenticationToken(
@ -282,11 +45,10 @@ public class TokenFilter extends OncePerRequestFilter {
}
} catch (Exception e) {
e.printStackTrace();
// Token无效可以在这里添加相应的处理逻辑例如返回401状态码等
// Token无效
}
}
}*/
// 过滤器放行
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;
}

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

@ -13,7 +13,7 @@ import com.example.demo.domain.vo.ExportVo;
**/
public interface AiEmotionService {
ExportVo updateStatus(Long recordId, int i, String s, String s1, int i1);
int updateStatus(Long recordId, int i, String s, String s1, int i1);
AiEmotionExportRecordVO getRecordById(Long id) throws Exception;
}

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

@ -1,6 +1,8 @@
package com.example.demo.service;
import com.example.demo.domain.vo.AiEmotionExportRecordVO;
import com.example.demo.domain.entity.Export;
import java.util.List;
/**
* @program: GOLD
@ -12,5 +14,9 @@ import com.example.demo.domain.vo.AiEmotionExportRecordVO;
**/
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);
}

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

@ -1,14 +1,14 @@
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;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @program: GOLD
@ -26,4 +26,6 @@ public interface GoldDetailService {
Total GoldTotal(User user);
//异步导出客户明细
Result addExportRecord(GoldDetailDTO dto);
//异步导出金币余额
Result addExportRecordGold(GoldUserDTO dto);
}

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

@ -48,7 +48,7 @@ public class AiEmotionExportListener extends AbstractMessageListener<String> {
exportExcelService.handleExcelExportData(message);
} catch (Exception e) {
logError(e, message);
throw new RuntimeException("Failed to process AI emotion export: " + e.getMessage(), e);
throw new RuntimeException("Failed to process HWGOLD export: " + e.getMessage(), e);
}
@ -67,7 +67,7 @@ public class AiEmotionExportListener extends AbstractMessageListener<String> {
context,
e.getStackTrace()[0].getFileName(),
e.getStackTrace()[0].getLineNumber(),
"AI Emotion Export Error: " + e.getMessage() + " 底层错误: " + cause ,
"HWGOLD Export Error: " + e.getMessage() + " 底层错误: " + cause ,
"Failed message: " + message
);
} catch (Exception alertEx) {

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();
}
}

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

@ -0,0 +1,64 @@
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;
@Transactional
@Service
@RequiredArgsConstructor
public class AdminServiceImpl implements AdminService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private AdminMapper adminMapper;
@Override
public Admin login(Admin admin) throws Exception {
try {
Admin admin1 = adminMapper.getAdmin(admin.getAccount());
String[] machineIds = admin1.getMachineId().split(",");
boolean flag = false;
for (String machineId : machineIds) {
if (admin.getMachineId() != null && admin.getMachineId().equals(machineId))
flag = true;
}
if (!flag) {
throw new RuntimeException("你没有使用该机器的权限!");
}
System.out.println(admin.getAccount());
System.out.println(admin.getPassword()+"---------------------------");
UsernamePasswordAuthenticationToken token =
new UsernamePasswordAuthenticationToken(admin.getAccount(),admin.getPassword());
System.out.println( token+"---------------------------");
// Authentication authentication = authenticationManager.authenticate(token);
// Admin loginAdmin = (Admin) authentication.getPrincipal();
Admin loginAdmin = (Admin) authenticationManager.authenticate(token).getPrincipal();
return loginAdmin;
}catch (NullPointerException e){
throw new RuntimeException("无此精网号");
}catch(BadCredentialsException exception){
throw new BadCredentialsException("密码错误");
}catch (Exception e){
throw new RuntimeException("你没有使用该机器的权限!");
}
}
}

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

@ -24,7 +24,7 @@ public class AiEmotionServiceImpl implements AiEmotionService {
private AiEmotionMapper aiEmotionMapper;
@Override
public ExportVo updateStatus(Long recordId, int i, String s, String s1, int i1) {
public int updateStatus(Long recordId, int i, String s, String s1, int i1) {
return exportMapper.updateExportData(recordId, i, s, s1, i1);
}

877
src/main/java/com/example/demo/serviceImpl/ExportExcelServiceImpl.java

@ -5,10 +5,15 @@ import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.example.demo.Util.ExcelUploadUtil;
import com.example.demo.controller.ConsumeController;
import com.example.demo.controller.GoldDetailController;
import com.example.demo.controller.RechargeController;
import com.example.demo.controller.RefundController;
import com.example.demo.domain.entity.Export;
import com.example.demo.domain.export.Goldmingxi;
import com.example.demo.domain.vo.*;
import com.example.demo.mapper.ExportMapper;
import com.example.demo.service.ExportExcelService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -17,6 +22,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.example.demo.service.AiEmotionService;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -25,7 +31,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.io.*;
import java.util.List;
import java.util.Map;
@Service
@ -40,9 +45,17 @@ public class ExportExcelServiceImpl implements ExportExcelService {
//注入GoldDetailController
@Autowired
private GoldDetailController goldDetailController;
@Autowired
private RechargeController rechargeController;
@Autowired
private RefundController refundController;
@Autowired
private ConsumeController consumeController;
// 每页查询的数据量
private static final int PAGE_SIZE = 1000;
@Autowired
private ExportMapper exportMapper;
@Transactional
@ -92,20 +105,31 @@ public class ExportExcelServiceImpl implements ExportExcelService {
Result pageResult = goldDetailController.getGoldDetail(page);
Integer code = pageResult.getCode();
Object data = pageResult.getData();
if (code == 200) {
Map<String, Object> rawData = (Map<String, Object>) data;
Long total = (Long) rawData.get("total");
List<Map<String, Object>> list = (List<Map<String, Object>>) rawData.get("list");
// 检查是否还有数据
// 判断 data 是否是 PageInfo 类型
if (!(data instanceof PageInfo<?>)) {
log.error("返回数据类型错误,期望 PageInfo,实际为:{}", data.getClass());
hasMore = false;
continue;
}
@SuppressWarnings("unchecked")
PageInfo<GoldDetail> pageInfo = (PageInfo<GoldDetail>) data;
Long total = (long) pageInfo.getTotal(); // 转换为 long
List<GoldDetail> list = pageInfo.getList();
if (list == null || list.isEmpty()) {
hasMore = false;
} else {
// 写入数据注意finish()应在所有数据写入后调用
// 写入 Excel 数据
excelWriter.write(list, writeSheet);
page.setPageNum(page.getPageNum() + 1);
totalCount += list.size();
log.info("导出进度 recordId: {}, 已处理: {}条", recordId, totalCount);
// 检查是否还有更多数据
hasMore = totalCount < total;
}
} else {
@ -136,16 +160,35 @@ public class ExportExcelServiceImpl implements ExportExcelService {
// 3. 执行上传
String result = uploadUtil.uploadExcel(excelFile, "export/excel/");
// 1. 解析JSON任务
// JsonNode uploadResult = objectMapper.readTree(result);
// System.out.println(uploadResult+"11111111111111111111111");
// long code = uploadResult.path("code").asLong();
// String url = String.valueOf(uploadResult.path("data"));
// url = url.replace("\"", "");
// if (code == 1) {
// // 3. 验证导出记录decodecode
// aiEmotionService.updateStatus(recordId, 2, url, "", totalCount);
// } else {
// //更新失败
// aiEmotionService.updateStatus(recordId, 3, "", url, 0);
// }
JsonNode uploadResult = objectMapper.readTree(result);
long code = uploadResult.path("code").asLong();
String url = String.valueOf(uploadResult.path("data"));
url = url.replace("\"", "");
if (code == 1) {
// 3. 验证导出记录decodecode
aiEmotionService.updateStatus(recordId, 2, url, "", totalCount);
String fileUrl = "";
JsonNode dataNode = uploadResult.path("data");
if (dataNode.isObject()) {
fileUrl = dataNode.path("url").asText();
} else if (dataNode.isTextual()) {
fileUrl = dataNode.asText(); // 如果 data 是直接字符串 URL
}
log.info("解析到的URL: {}", fileUrl);
if (code == 200 && !fileUrl.isEmpty()) {
aiEmotionService.updateStatus(recordId, 2, fileUrl, "", totalCount);
} else {
//更新失败
aiEmotionService.updateStatus(recordId, 3, "", url, 0);
aiEmotionService.updateStatus(recordId, 3, "", "上传成功但URL为空或解析失败", 0);
}
} catch (Exception e) {
//更新失败
@ -215,6 +258,812 @@ public class ExportExcelServiceImpl implements ExportExcelService {
}
@Transactional
@Override
public Exception handleExcel(String message) throws Exception {
System.out.println("明细导出excel数据开始执行:" + message);
long startTime = System.currentTimeMillis();
Long recordId = null;
String fileName = null;
File tempFile = null;
OutputStream outputStream = null;
ExcelWriter excelWriter = null;
try {
// 1. 解析JSON任务
JsonNode rootNode = objectMapper.readTree(message);
// 2. 获取基本参数
recordId = rootNode.path("recordId").asLong();
JsonNode requestDataNode = rootNode.path("requestData");
// 3. 验证导出记录
AiEmotionExportRecordVO record = validateExportRecord(recordId);
if (record == null) return null;
//4. 更新状态为处理中
aiEmotionService.updateStatus(recordId, 1, "", "", 0);
// 5. 准备Excel文件
fileName = record.getFileName();
// 初始化临时文件保存到本地临时目录
tempFile = File.createTempFile("export_", ".xlsx");
outputStream = new FileOutputStream(tempFile); // 使用文件输出流
// 从JSON中提取单个值
String text = requestDataNode.has("text") ? requestDataNode.get("text").asText() : null;
Integer sort = requestDataNode.has("sort") ? requestDataNode.get("sort").asInt() : null;
String field = requestDataNode.has("field") ? requestDataNode.get("field").asText() : null;
String deptId = requestDataNode.has("deptId") ? requestDataNode.get("deptId").asText() : null;
try {
// 6. 初始化Excel写入器指向本地文件流
excelWriter = initExcelWriter(outputStream, "user");
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
// 7. 分页查询并写入数据
Page page = new Page();
page.setPageNum(1);
page.setPageSize(1000);
Integer totalCount = 0;
boolean hasMore = true;
while (hasMore) {
Result pageResult = goldDetailController.getGold(page);
Integer code = pageResult.getCode();
Object data = pageResult.getData();
if (code == 200) {
// 判断 data 是否是 PageInfo 类型
if (!(data instanceof PageInfo<?>)) {
log.error("返回数据类型错误,期望 PageInfo,实际为:{}", data.getClass());
hasMore = false;
continue;
}
@SuppressWarnings("unchecked")
PageInfo<GoldDetail> pageInfo = (PageInfo<GoldDetail>) data;
Long total = (long) pageInfo.getTotal(); // 转换为 long
List<GoldDetail> list = pageInfo.getList();
if (list == null || list.isEmpty()) {
hasMore = false;
} else {
// 写入 Excel 数据
excelWriter.write(list, writeSheet);
page.setPageNum(page.getPageNum() + 1);
totalCount += list.size();
log.info("导出进度 recordId: {}, 已处理: {}条", recordId, totalCount);
hasMore = totalCount < total;
}
} else {
hasMore = false;
log.error("获取数据失败,状态码: {}", code);
}
}
// 7. 完成Excel写入所有数据写入后关闭写入器
if (excelWriter != null) {
excelWriter.finish();
}
if (outputStream != null) {
outputStream.flush(); // 确保所有数据写入
outputStream.close(); // 关闭文件流
}
// 检查文件是否存在且不为空
if (tempFile != null && tempFile.exists() && tempFile.length() > 0) {
// 8. 上传到OSS读取本地临时文件
// 获取接口的基础 URL
String uploadUrl = "http://39.101.133.168:8828/hljw/api/aws/upload";
try {
// 1. 创建上传工具实例
ExcelUploadUtil uploadUtil = new ExcelUploadUtil(uploadUrl);
// 2. 准备要上传的文件
File excelFile = new File(tempFile.toURI());
try {
// 3. 执行上传
String result = uploadUtil.uploadExcel(excelFile, "export/excel/");
// 1. 解析JSON任务
// JsonNode uploadResult = objectMapper.readTree(result);
// System.out.println(uploadResult+"11111111111111111111111");
// long code = uploadResult.path("code").asLong();
// String url = String.valueOf(uploadResult.path("data"));
// url = url.replace("\"", "");
// if (code == 1) {
// // 3. 验证导出记录decodecode
// aiEmotionService.updateStatus(recordId, 2, url, "", totalCount);
// } else {
// //更新失败
// aiEmotionService.updateStatus(recordId, 3, "", url, 0);
// }
JsonNode uploadResult = objectMapper.readTree(result);
long code = uploadResult.path("code").asLong();
String fileUrl = "";
JsonNode dataNode = uploadResult.path("data");
if (dataNode.isObject()) {
fileUrl = dataNode.path("url").asText();
} else if (dataNode.isTextual()) {
fileUrl = dataNode.asText(); // 如果 data 是直接字符串 URL
}
log.info("解析到的URL: {}", fileUrl);
if (code == 200 && !fileUrl.isEmpty()) {
aiEmotionService.updateStatus(recordId, 2, fileUrl, "", totalCount);
} else {
aiEmotionService.updateStatus(recordId, 3, "", "上传成功但URL为空或解析失败", 0);
}
} catch (Exception e) {
//更新失败
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
throw new Exception("文件上传云端失败1", e);
}
} catch (Exception e) {
log.error("上传文件失败 recordId: {}, 文件名: {}", recordId, fileName, e);
//更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
throw new Exception("文件上传云端失败2", e);
}
} else {
throw new Exception("导出的Excel文件不存在或为空");
}
} catch (Exception e) {
System.out.println("导出异常" + e.getMessage());
log.error("导出任务处理失败 recordId: {}", recordId, e);
// 更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
throw new Exception("导出异常", e);
} finally {
// 确保资源被关闭
try {
if (excelWriter != null) {
excelWriter.finish();
}
if (outputStream != null) {
outputStream.close();
}
} catch (Exception e) {
log.error("关闭资源失败", e);
throw new Exception("excel文件关闭资源失败", e);
}
}
} catch (Exception e) {
log.error("导出任务处理失败 recordId: {}", recordId, e);
// 更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
System.out.println("<导出失败>" + e.getMessage());
throw new Exception("导出任务处理失败", e);
} finally {
// 清理临时文件
if (tempFile != null && tempFile.exists()) {
try {
if (tempFile.delete()) {
log.info("临时文件已删除: {}", tempFile.getAbsolutePath());
} else {
log.warn("无法删除临时文件: {}", tempFile.getAbsolutePath());
}
} catch (Exception e) {
log.error("删除临时文件失败", e.getMessage());
throw new Exception("删除临时文件失败", e);
}
}
long endTime = System.currentTimeMillis();
log.info("导出任务完成,耗时: {}毫秒", (endTime - startTime));
}
return null;
}
@Transactional
@Override
public Exception rechargeExcel(String message) throws Exception {
System.out.println("明细导出excel数据开始执行:" + message);
long startTime = System.currentTimeMillis();
Long recordId = null;
String fileName = null;
File tempFile = null;
OutputStream outputStream = null;
ExcelWriter excelWriter = null;
try {
// 1. 解析JSON任务
JsonNode rootNode = objectMapper.readTree(message);
// 2. 获取基本参数
recordId = rootNode.path("recordId").asLong();
JsonNode requestDataNode = rootNode.path("requestData");
// 3. 验证导出记录
AiEmotionExportRecordVO record = validateExportRecord(recordId);
if (record == null) return null;
//4. 更新状态为处理中
aiEmotionService.updateStatus(recordId, 1, "", "", 0);
// 5. 准备Excel文件
fileName = record.getFileName();
// 初始化临时文件保存到本地临时目录
tempFile = File.createTempFile("export_", ".xlsx");
outputStream = new FileOutputStream(tempFile); // 使用文件输出流
// 从JSON中提取单个值
String text = requestDataNode.has("text") ? requestDataNode.get("text").asText() : null;
Integer sort = requestDataNode.has("sort") ? requestDataNode.get("sort").asInt() : null;
String field = requestDataNode.has("field") ? requestDataNode.get("field").asText() : null;
String deptId = requestDataNode.has("deptId") ? requestDataNode.get("deptId").asText() : null;
try {
// 6. 初始化Excel写入器指向本地文件流
excelWriter = initExcelWriter(outputStream, "user");
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
// 7. 分页查询并写入数据
Page page = new Page();
page.setPageNum(1);
page.setPageSize(1000);
Integer totalCount = 0;
boolean hasMore = true;
while (hasMore) {
Result pageResult = rechargeController.selcetBy( page);
Integer code = pageResult.getCode();
Object data = pageResult.getData();
if (code == 200) {
// 判断 data 是否是 PageInfo 类型
if (!(data instanceof PageInfo<?>)) {
log.error("返回数据类型错误,期望 PageInfo,实际为:{}", data.getClass());
hasMore = false;
continue;
}
@SuppressWarnings("unchecked")
PageInfo<GoldDetail> pageInfo = (PageInfo<GoldDetail>) data;
Long total = (long) pageInfo.getTotal(); // 转换为 long
List<GoldDetail> list = pageInfo.getList();
if (list == null || list.isEmpty()) {
hasMore = false;
} else {
// 写入 Excel 数据
excelWriter.write(list, writeSheet);
page.setPageNum(page.getPageNum() + 1);
totalCount += list.size();
log.info("导出进度 recordId: {}, 已处理: {}条", recordId, totalCount);
hasMore = totalCount < total;
}
} else {
hasMore = false;
log.error("获取数据失败,状态码: {}", code);
}
}
// 7. 完成Excel写入所有数据写入后关闭写入器
if (excelWriter != null) {
excelWriter.finish();
}
if (outputStream != null) {
outputStream.flush(); // 确保所有数据写入
outputStream.close(); // 关闭文件流
}
// 检查文件是否存在且不为空
if (tempFile != null && tempFile.exists() && tempFile.length() > 0) {
// 8. 上传到OSS读取本地临时文件
// 获取接口的基础 URL
String uploadUrl = "http://39.101.133.168:8828/hljw/api/aws/upload";
try {
// 1. 创建上传工具实例
ExcelUploadUtil uploadUtil = new ExcelUploadUtil(uploadUrl);
// 2. 准备要上传的文件
File excelFile = new File(tempFile.toURI());
try {
// 3. 执行上传
String result = uploadUtil.uploadExcel(excelFile, "export/excel/");
// 1. 解析JSON任务
// JsonNode uploadResult = objectMapper.readTree(result);
// System.out.println(uploadResult+"11111111111111111111111");
// long code = uploadResult.path("code").asLong();
// String url = String.valueOf(uploadResult.path("data"));
// url = url.replace("\"", "");
// if (code == 1) {
// // 3. 验证导出记录decodecode
// aiEmotionService.updateStatus(recordId, 2, url, "", totalCount);
// } else {
// //更新失败
// aiEmotionService.updateStatus(recordId, 3, "", url, 0);
// }
JsonNode uploadResult = objectMapper.readTree(result);
long code = uploadResult.path("code").asLong();
String fileUrl = "";
JsonNode dataNode = uploadResult.path("data");
if (dataNode.isObject()) {
fileUrl = dataNode.path("url").asText();
} else if (dataNode.isTextual()) {
fileUrl = dataNode.asText(); // 如果 data 是直接字符串 URL
}
log.info("解析到的URL: {}", fileUrl);
if (code == 200 && !fileUrl.isEmpty()) {
aiEmotionService.updateStatus(recordId, 2, fileUrl, "", totalCount);
} else {
aiEmotionService.updateStatus(recordId, 3, "", "上传成功但URL为空或解析失败", 0);
}
} catch (Exception e) {
//更新失败
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
throw new Exception("文件上传云端失败1", e);
}
} catch (Exception e) {
log.error("上传文件失败 recordId: {}, 文件名: {}", recordId, fileName, e);
//更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
throw new Exception("文件上传云端失败2", e);
}
} else {
throw new Exception("导出的Excel文件不存在或为空");
}
} catch (Exception e) {
System.out.println("导出异常" + e.getMessage());
log.error("导出任务处理失败 recordId: {}", recordId, e);
// 更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
throw new Exception("导出异常", e);
} finally {
// 确保资源被关闭
try {
if (excelWriter != null) {
excelWriter.finish();
}
if (outputStream != null) {
outputStream.close();
}
} catch (Exception e) {
log.error("关闭资源失败", e);
throw new Exception("excel文件关闭资源失败", e);
}
}
} catch (Exception e) {
log.error("导出任务处理失败 recordId: {}", recordId, e);
// 更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
System.out.println("<导出失败>" + e.getMessage());
throw new Exception("导出任务处理失败", e);
} finally {
// 清理临时文件
if (tempFile != null && tempFile.exists()) {
try {
if (tempFile.delete()) {
log.info("临时文件已删除: {}", tempFile.getAbsolutePath());
} else {
log.warn("无法删除临时文件: {}", tempFile.getAbsolutePath());
}
} catch (Exception e) {
log.error("删除临时文件失败", e.getMessage());
throw new Exception("删除临时文件失败", e);
}
}
long endTime = System.currentTimeMillis();
log.info("导出任务完成,耗时: {}毫秒", (endTime - startTime));
}
return null;
}
@Transactional
@Override
public Exception consumeExcel(String message) throws Exception {
System.out.println("明细导出excel数据开始执行:" + message);
long startTime = System.currentTimeMillis();
Long recordId = null;
String fileName = null;
File tempFile = null;
OutputStream outputStream = null;
ExcelWriter excelWriter = null;
try {
// 1. 解析JSON任务
JsonNode rootNode = objectMapper.readTree(message);
// 2. 获取基本参数
recordId = rootNode.path("recordId").asLong();
JsonNode requestDataNode = rootNode.path("requestData");
// 3. 验证导出记录
AiEmotionExportRecordVO record = validateExportRecord(recordId);
if (record == null) return null;
//4. 更新状态为处理中
aiEmotionService.updateStatus(recordId, 1, "", "", 0);
// 5. 准备Excel文件
fileName = record.getFileName();
// 初始化临时文件保存到本地临时目录
tempFile = File.createTempFile("export_", ".xlsx");
outputStream = new FileOutputStream(tempFile); // 使用文件输出流
// 从JSON中提取单个值
String text = requestDataNode.has("text") ? requestDataNode.get("text").asText() : null;
Integer sort = requestDataNode.has("sort") ? requestDataNode.get("sort").asInt() : null;
String field = requestDataNode.has("field") ? requestDataNode.get("field").asText() : null;
String deptId = requestDataNode.has("deptId") ? requestDataNode.get("deptId").asText() : null;
try {
// 6. 初始化Excel写入器指向本地文件流
excelWriter = initExcelWriter(outputStream, "user");
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
// 7. 分页查询并写入数据
Page page = new Page();
page.setPageNum(1);
page.setPageSize(1000);
Integer totalCount = 0;
boolean hasMore = true;
while (hasMore) {
Result pageResult = refundController.selcetBy(page);
Integer code = pageResult.getCode();
Object data = pageResult.getData();
if (code == 200) {
// 判断 data 是否是 PageInfo 类型
if (!(data instanceof PageInfo<?>)) {
log.error("返回数据类型错误,期望 PageInfo,实际为:{}", data.getClass());
hasMore = false;
continue;
}
@SuppressWarnings("unchecked")
PageInfo<GoldDetail> pageInfo = (PageInfo<GoldDetail>) data;
Long total = (long) pageInfo.getTotal(); // 转换为 long
List<GoldDetail> list = pageInfo.getList();
if (list == null || list.isEmpty()) {
hasMore = false;
} else {
// 写入 Excel 数据
excelWriter.write(list, writeSheet);
page.setPageNum(page.getPageNum() + 1);
totalCount += list.size();
log.info("导出进度 recordId: {}, 已处理: {}条", recordId, totalCount);
hasMore = totalCount < total;
}
} else {
hasMore = false;
log.error("获取数据失败,状态码: {}", code);
}
}
// 7. 完成Excel写入所有数据写入后关闭写入器
if (excelWriter != null) {
excelWriter.finish();
}
if (outputStream != null) {
outputStream.flush(); // 确保所有数据写入
outputStream.close(); // 关闭文件流
}
// 检查文件是否存在且不为空
if (tempFile != null && tempFile.exists() && tempFile.length() > 0) {
// 8. 上传到OSS读取本地临时文件
// 获取接口的基础 URL
String uploadUrl = "http://39.101.133.168:8828/hljw/api/aws/upload";
try {
// 1. 创建上传工具实例
ExcelUploadUtil uploadUtil = new ExcelUploadUtil(uploadUrl);
// 2. 准备要上传的文件
File excelFile = new File(tempFile.toURI());
try {
// 3. 执行上传
String result = uploadUtil.uploadExcel(excelFile, "export/excel/");
// 1. 解析JSON任务
// JsonNode uploadResult = objectMapper.readTree(result);
// System.out.println(uploadResult+"11111111111111111111111");
// long code = uploadResult.path("code").asLong();
// String url = String.valueOf(uploadResult.path("data"));
// url = url.replace("\"", "");
// if (code == 1) {
// // 3. 验证导出记录decodecode
// aiEmotionService.updateStatus(recordId, 2, url, "", totalCount);
// } else {
// //更新失败
// aiEmotionService.updateStatus(recordId, 3, "", url, 0);
// }
JsonNode uploadResult = objectMapper.readTree(result);
long code = uploadResult.path("code").asLong();
String fileUrl = "";
JsonNode dataNode = uploadResult.path("data");
if (dataNode.isObject()) {
fileUrl = dataNode.path("url").asText();
} else if (dataNode.isTextual()) {
fileUrl = dataNode.asText(); // 如果 data 是直接字符串 URL
}
log.info("解析到的URL: {}", fileUrl);
if (code == 200 && !fileUrl.isEmpty()) {
aiEmotionService.updateStatus(recordId, 2, fileUrl, "", totalCount);
} else {
aiEmotionService.updateStatus(recordId, 3, "", "上传成功但URL为空或解析失败", 0);
}
} catch (Exception e) {
//更新失败
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
throw new Exception("文件上传云端失败1", e);
}
} catch (Exception e) {
log.error("上传文件失败 recordId: {}, 文件名: {}", recordId, fileName, e);
//更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
throw new Exception("文件上传云端失败2", e);
}
} else {
throw new Exception("导出的Excel文件不存在或为空");
}
} catch (Exception e) {
System.out.println("导出异常" + e.getMessage());
log.error("导出任务处理失败 recordId: {}", recordId, e);
// 更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
throw new Exception("导出异常", e);
} finally {
// 确保资源被关闭
try {
if (excelWriter != null) {
excelWriter.finish();
}
if (outputStream != null) {
outputStream.close();
}
} catch (Exception e) {
log.error("关闭资源失败", e);
throw new Exception("excel文件关闭资源失败", e);
}
}
} catch (Exception e) {
log.error("导出任务处理失败 recordId: {}", recordId, e);
// 更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
System.out.println("<导出失败>" + e.getMessage());
throw new Exception("导出任务处理失败", e);
} finally {
// 清理临时文件
if (tempFile != null && tempFile.exists()) {
try {
if (tempFile.delete()) {
log.info("临时文件已删除: {}", tempFile.getAbsolutePath());
} else {
log.warn("无法删除临时文件: {}", tempFile.getAbsolutePath());
}
} catch (Exception e) {
log.error("删除临时文件失败", e.getMessage());
throw new Exception("删除临时文件失败", e);
}
}
long endTime = System.currentTimeMillis();
log.info("导出任务完成,耗时: {}毫秒", (endTime - startTime));
}
return null;
}
@Transactional
@Override
public Exception refundExcel(String message) throws Exception {
System.out.println("明细导出excel数据开始执行:" + message);
long startTime = System.currentTimeMillis();
Long recordId = null;
String fileName = null;
File tempFile = null;
OutputStream outputStream = null;
ExcelWriter excelWriter = null;
try {
// 1. 解析JSON任务
JsonNode rootNode = objectMapper.readTree(message);
// 2. 获取基本参数
recordId = rootNode.path("recordId").asLong();
JsonNode requestDataNode = rootNode.path("requestData");
// 3. 验证导出记录
AiEmotionExportRecordVO record = validateExportRecord(recordId);
if (record == null) return null;
//4. 更新状态为处理中
aiEmotionService.updateStatus(recordId, 1, "", "", 0);
// 5. 准备Excel文件
fileName = record.getFileName();
// 初始化临时文件保存到本地临时目录
tempFile = File.createTempFile("export_", ".xlsx");
outputStream = new FileOutputStream(tempFile); // 使用文件输出流
// 从JSON中提取单个值
String text = requestDataNode.has("text") ? requestDataNode.get("text").asText() : null;
Integer sort = requestDataNode.has("sort") ? requestDataNode.get("sort").asInt() : null;
String field = requestDataNode.has("field") ? requestDataNode.get("field").asText() : null;
String deptId = requestDataNode.has("deptId") ? requestDataNode.get("deptId").asText() : null;
try {
// 6. 初始化Excel写入器指向本地文件流
excelWriter = initExcelWriter(outputStream, "user");
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
// 7. 分页查询并写入数据
Page page = new Page();
page.setPageNum(1);
page.setPageSize(1000);
Integer totalCount = 0;
boolean hasMore = true;
while (hasMore) {
Result pageResult = consumeController.selcetBy(page);
Integer code = pageResult.getCode();
Object data = pageResult.getData();
if (code == 200) {
// 判断 data 是否是 PageInfo 类型
if (!(data instanceof PageInfo<?>)) {
log.error("返回数据类型错误,期望 PageInfo,实际为:{}", data.getClass());
hasMore = false;
continue;
}
@SuppressWarnings("unchecked")
PageInfo<GoldDetail> pageInfo = (PageInfo<GoldDetail>) data;
Long total = (long) pageInfo.getTotal(); // 转换为 long
List<GoldDetail> list = pageInfo.getList();
if (list == null || list.isEmpty()) {
hasMore = false;
} else {
// 写入 Excel 数据
excelWriter.write(list, writeSheet);
page.setPageNum(page.getPageNum() + 1);
totalCount += list.size();
log.info("导出进度 recordId: {}, 已处理: {}条", recordId, totalCount);
hasMore = totalCount < total;
}
} else {
hasMore = false;
log.error("获取数据失败,状态码: {}", code);
}
}
// 7. 完成Excel写入所有数据写入后关闭写入器
if (excelWriter != null) {
excelWriter.finish();
}
if (outputStream != null) {
outputStream.flush(); // 确保所有数据写入
outputStream.close(); // 关闭文件流
}
// 检查文件是否存在且不为空
if (tempFile != null && tempFile.exists() && tempFile.length() > 0) {
// 8. 上传到OSS读取本地临时文件
// 获取接口的基础 URL
String uploadUrl = "http://39.101.133.168:8828/hljw/api/aws/upload";
try {
// 1. 创建上传工具实例
ExcelUploadUtil uploadUtil = new ExcelUploadUtil(uploadUrl);
// 2. 准备要上传的文件
File excelFile = new File(tempFile.toURI());
try {
// 3. 执行上传
String result = uploadUtil.uploadExcel(excelFile, "export/excel/");
// 1. 解析JSON任务
// JsonNode uploadResult = objectMapper.readTree(result);
// System.out.println(uploadResult+"11111111111111111111111");
// long code = uploadResult.path("code").asLong();
// String url = String.valueOf(uploadResult.path("data"));
// url = url.replace("\"", "");
// if (code == 1) {
// // 3. 验证导出记录decodecode
// aiEmotionService.updateStatus(recordId, 2, url, "", totalCount);
// } else {
// //更新失败
// aiEmotionService.updateStatus(recordId, 3, "", url, 0);
// }
JsonNode uploadResult = objectMapper.readTree(result);
long code = uploadResult.path("code").asLong();
String fileUrl = "";
JsonNode dataNode = uploadResult.path("data");
if (dataNode.isObject()) {
fileUrl = dataNode.path("url").asText();
} else if (dataNode.isTextual()) {
fileUrl = dataNode.asText(); // 如果 data 是直接字符串 URL
}
log.info("解析到的URL: {}", fileUrl);
if (code == 200 && !fileUrl.isEmpty()) {
aiEmotionService.updateStatus(recordId, 2, fileUrl, "", totalCount);
} else {
aiEmotionService.updateStatus(recordId, 3, "", "上传成功但URL为空或解析失败", 0);
}
} catch (Exception e) {
//更新失败
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
throw new Exception("文件上传云端失败1", e);
}
} catch (Exception e) {
log.error("上传文件失败 recordId: {}, 文件名: {}", recordId, fileName, e);
//更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
throw new Exception("文件上传云端失败2", e);
}
} else {
throw new Exception("导出的Excel文件不存在或为空");
}
} catch (Exception e) {
System.out.println("导出异常" + e.getMessage());
log.error("导出任务处理失败 recordId: {}", recordId, e);
// 更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
throw new Exception("导出异常", e);
} finally {
// 确保资源被关闭
try {
if (excelWriter != null) {
excelWriter.finish();
}
if (outputStream != null) {
outputStream.close();
}
} catch (Exception e) {
log.error("关闭资源失败", e);
throw new Exception("excel文件关闭资源失败", e);
}
}
} catch (Exception e) {
log.error("导出任务处理失败 recordId: {}", recordId, e);
// 更新状态为失败
if (recordId != null) {
aiEmotionService.updateStatus(recordId, 3, "", StringUtils.substring(e.getMessage(), 0, 500), 0);
}
System.out.println("<导出失败>" + e.getMessage());
throw new Exception("导出任务处理失败", e);
} finally {
// 清理临时文件
if (tempFile != null && tempFile.exists()) {
try {
if (tempFile.delete()) {
log.info("临时文件已删除: {}", tempFile.getAbsolutePath());
} else {
log.warn("无法删除临时文件: {}", tempFile.getAbsolutePath());
}
} catch (Exception e) {
log.error("删除临时文件失败", e.getMessage());
throw new Exception("删除临时文件失败", e);
}
}
long endTime = System.currentTimeMillis();
log.info("导出任务完成,耗时: {}毫秒", (endTime - startTime));
}
return null;
}
@Override
public List<Export> getExcel(Export export) {
List<Export> list = exportMapper.getExportRecord(export.getAccount());
System.out.println(list+"-------------------------------");
return list;
}
/**
* 验证导出记录
*/

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

@ -2,6 +2,7 @@ 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;
@ -74,7 +75,7 @@ public class GoldDetailServiceImpl implements GoldDetailService {
"操作人",
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
System.out.println(fileName);
dto.setJwcode(123456);
dto.setAccount(123456);
dto.setUrl("");
dto.setFileName(fileName);
dto.setDataNum(0);
@ -83,7 +84,7 @@ public class GoldDetailServiceImpl implements GoldDetailService {
GoldDetailMapper.ExportRecordIdHolder idHolder = new GoldDetailMapper.ExportRecordIdHolder();
goldDetailMapper.insertExportRecord(
idHolder, // 用于接收主键
dto.getJwcode(),
dto.getAccount(),
dto.getType(),
dto.getState(),
dto.getUrl(),
@ -114,6 +115,53 @@ public class GoldDetailServiceImpl implements GoldDetailService {
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();
}
}

4
src/main/resources/mapper/AiEmotionMapper.xml

@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.AiEmotionMapper">
<update id="updateStatus">
UPDATE admin_export_record
UPDATE export
<set>
<if test="state != null">state = #{state},</if>
<if test="url != null and url != ''">url = #{url},</if>
@ -12,6 +12,6 @@
WHERE id = #{recordId}
</update>
<select id="getRecordById" resultType="com.example.demo.domain.vo.AiEmotionExportRecordVO">
SELECT id, file_name, state, url FROM admin_export_record WHERE id = #{recordId}
SELECT id, file_name, state, url FROM export WHERE id = #{recordId}
</select>
</mapper>

10
src/main/resources/mapper/ExportMapper.xml

@ -15,4 +15,14 @@
<select id="getExportData" resultType="com.example.demo.domain.vo.ExportVo">
select id,file_name,url,state from export where id=#{recordId}
</select>
<select id="getExportRecord" resultType="com.example.demo.domain.entity.Export">
select * from export
<where>
<if test="account != null">
and account = #{account}
</if>
</where>
</select>
</mapper>

4
src/main/resources/mapper/GoldDetailMapper.xml

@ -2,8 +2,8 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.GoldDetailMapper">
<insert id="insertExportRecord" useGeneratedKeys="true" keyProperty="recordId.id">
insert into excprt (jwcode,type,state,url,file_name,data_num)
values(#{jwcode},#{type},#{state},#{url},#{fileName},#{dataNum})
insert into export (account,type,state,url,file_name,data_num)
values(#{account},#{type},#{state},#{url},#{fileName},#{dataNum})
</insert>
<select id="getGoldDetail" resultType="com.example.demo.domain.vo.GoldDetail">

6
src/main/resources/mapper/PermissionMapper.xml

@ -25,7 +25,7 @@
role_id= #{roleId},
</if>
</set>
where admin_id= #{adminId}
where admin_id= #{id}
</update>
<delete id="deleteAdmin">
delete from admin where id=#{id}
@ -40,7 +40,7 @@
select distinct market from admin
</select>
<select id="getPermission" resultType="com.example.demo.domain.vo.Permission">
select admin.id as id,admin.admin_name as name,admin.account,admin.market,admin.postiton,admin.remark,admin.admin_status,role.role_name,role.id as roleId
select admin.id as id,admin.admin_name as name,admin.account,admin.market,admin.postiton,admin.remark,admin.admin_status as adminStatus,role.role_name as roleName,role.id as roleId
from admin
left join admin_role on admin.id=admin_role.admin_id
left join role on admin_role.role_id=role.id
@ -61,4 +61,4 @@
select * from role
</select>
</mapper>
</mapper>
Loading…
Cancel
Save