4 Commits

  1. 35
      pom.xml
  2. 25
      src/main/java/com/example/demo/Export/ExportService.java
  3. 177
      src/main/java/com/example/demo/Export/ExportServiceImpl.java
  4. 200
      src/main/java/com/example/demo/Util/ExcelUploadUtil.java
  5. 227
      src/main/java/com/example/demo/Util/ExecutionContextUtil.java
  6. 173
      src/main/java/com/example/demo/Util/FeiShuAlertUtil.java
  7. 37
      src/main/java/com/example/demo/Util/RedisLockUtil.java
  8. 31
      src/main/java/com/example/demo/Util/RedisUtil.java
  9. 18
      src/main/java/com/example/demo/config/EnvConfig.java
  10. 4
      src/main/java/com/example/demo/config/RedisConfig.java
  11. 43
      src/main/java/com/example/demo/controller/AdminController.java
  12. 99
      src/main/java/com/example/demo/controller/ExportController.java
  13. 50
      src/main/java/com/example/demo/controller/GoldDetailController.java
  14. 4
      src/main/java/com/example/demo/controller/PermissionController.java
  15. 42
      src/main/java/com/example/demo/domain/DTO/ConsumeDTO.java
  16. 44
      src/main/java/com/example/demo/domain/DTO/GoldDetailDTO.java
  17. 42
      src/main/java/com/example/demo/domain/DTO/GoldUserDTO.java
  18. 43
      src/main/java/com/example/demo/domain/DTO/RechargeDTO.java
  19. 42
      src/main/java/com/example/demo/domain/DTO/RefundDTO.java
  20. 66
      src/main/java/com/example/demo/domain/entity/Admin.java
  21. 28
      src/main/java/com/example/demo/domain/export/Goldmingxi.java
  22. 28
      src/main/java/com/example/demo/domain/vo/AiEmotionExportRecordVO.java
  23. 25
      src/main/java/com/example/demo/domain/vo/ExecutionContext.java
  24. 26
      src/main/java/com/example/demo/domain/vo/ExportVo.java
  25. 13
      src/main/java/com/example/demo/exception/SystemException.java
  26. 25
      src/main/java/com/example/demo/mapper/AiEmotionMapper.java
  27. 23
      src/main/java/com/example/demo/mapper/ExportMapper.java
  28. 16
      src/main/java/com/example/demo/mapper/GoldDetailMapper.java
  29. 268
      src/main/java/com/example/demo/security/TokenFilter.java
  30. 43
      src/main/java/com/example/demo/security/UploadFilter.java
  31. 15
      src/main/java/com/example/demo/service/AdminService.java
  32. 19
      src/main/java/com/example/demo/service/AiEmotionService.java
  33. 22
      src/main/java/com/example/demo/service/ExportExcelService.java
  34. 9
      src/main/java/com/example/demo/service/GoldDetailService.java
  35. 1
      src/main/java/com/example/demo/service/PermissionService.java
  36. 84
      src/main/java/com/example/demo/service/listen/AiEmotionExportListener.java
  37. 81
      src/main/java/com/example/demo/service/listen/ConsumeListener.java
  38. 82
      src/main/java/com/example/demo/service/listen/GoldListener.java
  39. 81
      src/main/java/com/example/demo/service/listen/RechargeListener.java
  40. 81
      src/main/java/com/example/demo/service/listen/RefundListener.java
  41. 69
      src/main/java/com/example/demo/service/queue/AbstractMessageListener.java
  42. 64
      src/main/java/com/example/demo/serviceImpl/AdminServiceImpl.java
  43. 35
      src/main/java/com/example/demo/serviceImpl/AiEmotionServiceImpl.java
  44. 1102
      src/main/java/com/example/demo/serviceImpl/ExportExcelServiceImpl.java
  45. 119
      src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java
  46. 5
      src/main/java/com/example/demo/serviceImpl/PermissionServiceImpl.java
  47. 8
      src/main/resources/application.yml
  48. 17
      src/main/resources/mapper/AiEmotionMapper.xml
  49. 28
      src/main/resources/mapper/ExportMapper.xml
  50. 16
      src/main/resources/mapper/GoldDetailMapper.xml
  51. 19
      src/main/resources/mapper/PermissionMapper.xml
  52. 8
      src/main/resources/mapper/UrlMapper.xml

35
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>

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

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

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

@ -1,4 +1,3 @@
/*
package com.example.demo.Util;
import jakarta.annotation.PostConstruct;
@ -35,24 +34,24 @@ public class RedisUtil {
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) {
// 分段获取避免长时间阻塞
@ -66,35 +65,35 @@ public class RedisUtil {
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);
@ -116,10 +115,10 @@ public class RedisUtil {
});
}
*/
/**
* 启动延迟消息处理任务
*//*
*/
@Scheduled(fixedRate = DELAY_QUEUE_POLL_INTERVAL)
public void processDelayMessages() {
@ -134,10 +133,10 @@ public class RedisUtil {
}
}
*/
/**
* 处理单个延迟队列
*//*
*/
private void processSingleDelayQueue(String queueName) {
String delayQueueKey = getDelayQueueKey(queueName);
@ -187,4 +186,4 @@ public class RedisUtil {
}
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";
}

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

@ -1,4 +1,4 @@
/*
package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
@ -45,4 +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());
}
}
}

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

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

@ -1,15 +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.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
@ -26,6 +35,12 @@ import org.springframework.web.bind.annotation.*;
@CrossOrigin
public class GoldDetailController {
private final GoldDetailService goldDetailService;
@Autowired
private RedisLockUtil redisLockUtil;
@Autowired
private AiEmotionServiceImpl aiEmotionServiceImpl;
@PostMapping("/getGoldDetail")
public Result getGoldDetail(@RequestBody Page page){
@ -58,4 +73,39 @@ public class GoldDetailController {
}
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);
}
}
}

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

@ -62,5 +62,9 @@ public class PermissionController {
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));
}
}

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

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

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

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

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

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

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

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

@ -3,7 +3,9 @@ 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;
@ -19,7 +21,19 @@ import java.util.List;
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
);
}

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

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

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

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

@ -1,10 +1,15 @@
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
@ -19,4 +24,8 @@ public interface GoldDetailService {
PageInfo<User> getGold(Integer pageNum, Integer pageSize, User user);
Total GoldTotal(User user);
//异步导出客户明细
Result addExportRecord(GoldDetailDTO dto);
//异步导出金币余额
Result addExportRecordGold(GoldUserDTO dto);
}

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

@ -26,4 +26,5 @@ public interface PermissionService {
List<Role> getRole(String token);
Integer deleteAdmin(Integer id);
Integer updateAdminRole(AdminRole adminRole);
Integer upadatePermission(Admin admin) throws Exception;
}

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

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("你没有使用该机器的权限!");
}
}
}

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

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

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

@ -1,16 +1,27 @@
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
@ -25,10 +36,13 @@ 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);
List<GoldDetail> list = goldDetailMapper.getGoldDetail(goldDetail);
return new PageInfo<>(list);
}
@ -42,7 +56,7 @@ public class GoldDetailServiceImpl implements GoldDetailService {
public PageInfo<User> getGold(Integer pageNum, Integer pageSize, User user) {
PageHelper.startPage(pageNum, pageSize);
List<User> list= goldDetailMapper.getGold(user);
List<User> list = goldDetailMapper.getGold(user);
return new PageInfo<>(list);
}
@ -50,4 +64,105 @@ public class GoldDetailServiceImpl implements GoldDetailService {
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();
}
}

5
src/main/java/com/example/demo/serviceImpl/PermissionServiceImpl.java

@ -111,5 +111,10 @@ public class PermissionServiceImpl implements PermissionService {
return permissionMapper.updateAdminRole(adminRole);
}
@Override
public Integer upadatePermission(Admin admin) throws Exception {
return permissionMapper.updatePermission(admin);
}
}

8
src/main/resources/application.yml

@ -62,10 +62,10 @@ spring:
data:
redis:
database: 0
host: 192.168.8.94
port: 6379
password:
timeout: 1000
host: 18.143.76.3
port: 10703
password: Ngc0FYUTA6h3wC5J
lettuce:
pool:
max-active: 20

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

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-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.AiEmotionMapper">
<update id="updateStatus">
UPDATE export
<set>
<if test="state != null">state = #{state},</if>
<if test="url != null and url != ''">url = #{url},</if>
<if test="reason != null and reason != ''">reason = #{reason},</if>
<if test="dataNum != null and dataNum != ''">data_num = #{dataNum},</if>
</set>
WHERE id = #{recordId}
</update>
<select id="getRecordById" resultType="com.example.demo.domain.vo.AiEmotionExportRecordVO">
SELECT id, file_name, state, url FROM export WHERE id = #{recordId}
</select>
</mapper>

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

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-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.ExportMapper">
<update id="updateExportData">
UPDATE export
<set>
<if test="state != null">state = #{state},</if>
<if test="url != null and url != ''">url = #{url},</if>
<if test="reason != null and reason != ''">reason = #{reason},</if>
<if test="dataNum != null and dataNum != ''">data_num = #{dataNum},</if>
</set>
WHERE id = #{recordId}
</update>
<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>

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

@ -1,6 +1,10 @@
<?xml version="1.0" encoding="UTF-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 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">
select `user`.name, `user`.jwcode, `user`.market, `ugr`.pay_platform, `ugr`.type, `ugr`.sum_gold, `ugr`.permanent_gold, `ugr`.free_june, `ugr`.free_december, `ugr`.task_gold, `admin`.admin_name, `ugr`.audit_time
@ -8,13 +12,13 @@
left join `user` on `user`.jwcode = `ugr`.jwcode
left join `admin` on `admin`.id = `ugr`.admin_id
<where>
<if test="jwcode != null and jwcode.length > 0">
<if test="jwcode != null">
and `ugr`.jwcode = #{jwcode}
</if>
<if test="payPlatform != null and payPlatform.length > 0">
and `ugr`.pay_platform = #{payPlatform}
</if>
<if test="type != null and type.length > 0">
<if test="type != null">
and `ugr`.type = #{type}
</if>
<if test="market != null and market.length > 0">
@ -38,13 +42,13 @@
select sum(sum_gold) as Goldtotal, sum(permanent_gold) as permanentGold, sum(free_june+free_december) as freeGold, sum(task_gold) as taskGold
from user_gold_record
<where>
<if test="jwcode != null and jwcode.length > 0">
<if test="jwcode != null">
and `ugr`.jwcode = #{jwcode}
</if>
<if test="payPlatform != null and payPlatform.length > 0">
and `ugr`.pay_platform = #{payPlatform}
</if>
<if test="type != null and type.length > 0">
<if test="type != null">
and `ugr`.type = #{type}
</if>
<if test="market != null and market.length > 0">
@ -59,7 +63,7 @@
<select id="getGold" resultType="com.example.demo.domain.entity.User">
select * from user
<where>
<if test="jwcode != null and jwcode.length > 0">
<if test="jwcode != null">
and jwcode = #{jwcode}
</if>
<if test="market != null and market.length > 0">
@ -83,7 +87,7 @@
sum(current_permanent_gold) + sum(current_free_june + current_free_december) + sum(current_task_gold) as Goldtotal
from `user`
<where>
<if test="jwcode != null and jwcode.length > 0">
<if test="jwcode != null ">
and jwcode = #{jwcode}
</if>
<if test="market != null and market.length > 0">

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

@ -12,20 +12,11 @@
<update id="updatePermission">
update admin
<set>
<if test="name!=null">
admin_name=#{name},
</if>
<if test="market!=null">
market=#{market},
</if>
<if test="postiton!=null">
postiton=#{postiton},
</if>
<if test="role!=null">
roleId=#{role},
<if test="adminStatus!=null">
admin_status= #{adminStatus},
</if>
</set>
where id= #{id}
where id=#{id}
</update>
<update id="updateAdminRole">
update admin_role
@ -34,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}
@ -49,7 +40,7 @@
select distinct market from admin
</select>
<select id="getPermission" resultType="com.example.demo.domain.vo.Permission">
select admin.id,admin.admin_name,admin.account,admin.market,admin.postiton,admin.remark,admin.admin_status,role.role_name
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

8
src/main/resources/mapper/UrlMapper.xml

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-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.UrlMapper">
<select id="selectBaseUrl" resultType="java.lang.String">
select value from env where `key` = #{key}
</select>
</mapper>
Loading…
Cancel
Save