Browse Source

Merge remote-tracking branch 'origin/milestone-20250702-金币重构一期' into milestone-20250702-金币重构一期

# Conflicts:
#	src/main/java/com/example/demo/service/GeneralService.java
#	src/main/java/com/example/demo/serviceImpl/GeneralServiceImpl.java
feat0702/lhl
jianlin 2 weeks ago
parent
commit
67508049dc
  1. 175
      src/main/java/com/example/demo/Util/RedisUtil.java
  2. 33
      src/main/java/com/example/demo/controller/ConsumeController.java
  3. 6
      src/main/java/com/example/demo/controller/GeneralController.java
  4. 15
      src/main/java/com/example/demo/controller/GoldDetailController.java
  5. 33
      src/main/java/com/example/demo/domain/entity/Export.java
  6. 3
      src/main/java/com/example/demo/domain/entity/User.java
  7. 20
      src/main/java/com/example/demo/domain/vo/Consume.java
  8. 2
      src/main/java/com/example/demo/domain/vo/GoldDetail.java
  9. 1
      src/main/java/com/example/demo/domain/vo/Page.java
  10. 2
      src/main/java/com/example/demo/mapper/ConsumeMapper.java
  11. 1
      src/main/java/com/example/demo/mapper/GeneralMapper.java
  12. 4
      src/main/java/com/example/demo/mapper/GoldDetailMapper.java
  13. 6
      src/main/java/com/example/demo/service/ConsumeService.java
  14. 1
      src/main/java/com/example/demo/service/GeneralService.java
  15. 4
      src/main/java/com/example/demo/service/GoldDetailService.java
  16. 15
      src/main/java/com/example/demo/serviceImpl/ConsumeServiceImpl.java
  17. 6
      src/main/java/com/example/demo/serviceImpl/GeneralServiceImpl.java
  18. 13
      src/main/java/com/example/demo/serviceImpl/GoldDetailServiceImpl.java
  19. 43
      src/main/resources/mapper/ConsumeMapper.xml
  20. 3
      src/main/resources/mapper/GeneralMapper.xml
  21. 36
      src/main/resources/mapper/GoldDetailMapper.xml

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

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

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

@ -2,11 +2,13 @@ package com.example.demo.controller;
import com.example.demo.domain.vo.Consume;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.Page;
import com.example.demo.domain.vo.Result;
import com.example.demo.service.ConsumeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@ -32,16 +34,35 @@ public class ConsumeController {
//消耗明细
@PostMapping("/selectAll")
public Result selcetAll()
{
List<Consume> consumes = consumeService.selectAll();
return Result.success(consumes);
public Result selcetAll(@RequestBody Page page) {
if (ObjectUtils.isEmpty(page.getPageNum())) {
return Result.error("页码数为空!");
}
if (ObjectUtils.isEmpty(page.getPageSize())) {
return Result.error("页大小为空!");
} else {
return Result.success(consumeService.selectAll(page.getPageNum(), page.getPageSize()));
}
}
//消耗明细筛选
@PostMapping("/selectBy")
public Result selcetBy(@RequestBody Page page) {
if (ObjectUtils.isEmpty(page.getPageNum())) {
return Result.error("页码数为空!");
}
if (ObjectUtils.isEmpty(page.getPageSize())) {
return Result.error("页大小为空!");
} else {
return Result.success(consumeService.selectBy(page.getPageNum(), page.getPageSize(), page.getConsume()));
}
}
//消耗金币统计
@PostMapping("/statsGold")
public Result statsGold()
{
public Result statsGold() {
Gold gold = consumeService.statsGold();
return Result.success(gold);
}

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

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

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

@ -1,5 +1,6 @@
package com.example.demo.controller;
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;
@ -42,4 +43,18 @@ public class GoldDetailController {
public Result getTotal(@RequestBody GoldDetail goldDetail) {
return Result.success(goldDetailService.getTotal(goldDetail));
}
@PostMapping("/goldTotal")
public Result GoldTotal(@RequestBody User user) {
return Result.success(goldDetailService.GoldTotal(user));
}
@PostMapping("/getGold")
public Result getGold(@RequestBody Page page) {
if(ObjectUtils.isEmpty(page.getPageNum())){
return Result.error("页码数为空!");
}
if(ObjectUtils.isEmpty(page.getPageSize())){
return Result.error("页大小为空!");
}
return Result.success(goldDetailService.getGold(page.getPageNum(), page.getPageSize(), page.getUser()));
}
}

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

@ -0,0 +1,33 @@
package com.example.demo.domain.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @program: GOLD
* @ClassName Export
* @description:
* @author: huangqizhen
* @create: 202506-24 16:17
* @Version 1.0
**/
@Data
@NoArgsConstructor
public class Export {
private String token;
private Integer account;
private String url;
private String fileName;
private Byte type;
private Byte state;
private Integer dataNum;
private String reason;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date updateTime;
}

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

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

20
src/main/java/com/example/demo/domain/vo/Consume.java

@ -1,18 +1,20 @@
package com.example.demo.domain.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
@program: gold-java
@ClassName Consume
@description: 消费明细
@author: Double
@create: 202506-23 11:53
@Version 1.0
* @program: gold-java
* @ClassName Consume
* @description: 消费明细
* @author: Double
* @create: 202506-23 11:53
* @Version 1.0
**/
@Data
@ -21,8 +23,6 @@ import java.util.Date;
public class Consume implements Serializable {
private static final long serialVersionUID = 1L;
private Integer pageNum; //页数
private Integer pageSize; //页面大小
private String name; // 客户姓名
private Integer jwcode; // 精网号
@ -38,4 +38,8 @@ public class Consume implements Serializable {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date payTime; // 消费时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date startTime; // 开始时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date endTime; // 结束时间
}

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

@ -33,10 +33,8 @@ public class GoldDetail {
private Integer taskGold; // 任务金币
private String adminName; //提交人
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date startTime; // 开始时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endTime; // 结束时间
private String sortField; //排序字段
private String sortOrder; //排序顺序

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

@ -19,5 +19,6 @@ public class Page {
private Integer pageNum;
private Integer pageSize;
private GoldDetail goldDetail;
private Consume consume;
}

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

@ -18,4 +18,6 @@ import java.util.List;
public interface ConsumeMapper {
List<Consume> selectAll();
List<Consume> selectBy(Consume consume);
}

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

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

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

@ -1,5 +1,6 @@
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 org.apache.ibatis.annotations.Mapper;
@ -18,4 +19,7 @@ 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);
}

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

@ -3,6 +3,8 @@ package com.example.demo.service;
import com.example.demo.domain.vo.Consume;
import com.example.demo.domain.vo.Gold;
import com.example.demo.domain.vo.GoldDetail;
import com.github.pagehelper.PageInfo;
import java.util.List;
@ -16,7 +18,9 @@ import java.util.List;
**/
public interface ConsumeService {
List<Consume> selectAll();
PageInfo<Consume> selectAll(Integer pageNum, Integer pageSize);
Gold statsGold();
PageInfo<Consume> selectBy(Integer pageNum, Integer pageSize, Consume consume);
}

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

@ -20,6 +20,7 @@ public interface GeneralService {
List<String> getMarket();
//获取平台
List<String> getPlatform();
List<String> getGoods();
//获取昨天的日期
Date getYesterday();
//获取某天的开始时间(00:00:00)

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

@ -1,5 +1,6 @@
package com.example.demo.service;
import com.example.demo.domain.entity.User;
import com.example.demo.domain.vo.GoldDetail;
import com.example.demo.domain.vo.Total;
import com.github.pagehelper.PageInfo;
@ -15,4 +16,7 @@ import com.github.pagehelper.PageInfo;
public interface GoldDetailService {
PageInfo<GoldDetail> getGoldDetail(Integer pageNum, Integer pageSize, GoldDetail goldDetail);
Total getTotal(GoldDetail goldDetail);
PageInfo<User> getGold(Integer pageNum, Integer pageSize, User user);
Total GoldTotal(User user);
}

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

@ -4,6 +4,8 @@ import com.example.demo.domain.vo.Consume;
import com.example.demo.domain.vo.Gold;
import com.example.demo.mapper.ConsumeMapper;
import com.example.demo.service.ConsumeService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -26,9 +28,10 @@ public class ConsumeServiceImpl implements ConsumeService {
//消耗明细
@Override
public List<Consume> selectAll() {
public PageInfo<Consume> selectAll(Integer pageNum, Integer pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<Consume> consumes = consumeMapper.selectAll();
return consumes;
return new PageInfo<>(consumes);
}
//消耗金币统计
@ -65,4 +68,12 @@ public class ConsumeServiceImpl implements ConsumeService {
return gold;
}
//消耗明细筛选
@Override
public PageInfo<Consume> selectBy(Integer pageNum, Integer pageSize, Consume consume) {
PageHelper.startPage(pageNum, pageSize);
List<Consume> consumes = consumeMapper.selectBy(consume);
return new PageInfo<>(consumes);
}
}

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

@ -39,6 +39,12 @@ public class GeneralServiceImpl implements GeneralService {
return list;
}
@Override
public List<String> getGoods() {
List<String> list = generalMapper.getGoods();
return list;
}
/*
获取昨天的日期
*/

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

@ -1,5 +1,6 @@
package com.example.demo.serviceImpl;
import com.example.demo.domain.entity.User;
import com.example.demo.domain.vo.GoldDetail;
import com.example.demo.domain.vo.Total;
import com.example.demo.mapper.GoldDetailMapper;
@ -36,4 +37,16 @@ public class GoldDetailServiceImpl implements GoldDetailService {
return goldDetailMapper.getTotal(goldDetail);
}
@Override
public PageInfo<User> getGold(Integer pageNum, Integer pageSize, User user) {
PageHelper.startPage(pageNum, pageSize);
List<User> list= goldDetailMapper.getGold(user);
return new PageInfo<>(list);
}
@Override
public Total GoldTotal(User user) {
return goldDetailMapper.GoldTotal(user);
}
}

43
src/main/resources/mapper/ConsumeMapper.xml

@ -4,8 +4,7 @@
<!-- 查询所有消费记录 -->
<select id="selectAll" resultType="com.example.demo.domain.vo.Consume">
SELECT
u.name AS name,
SELECT u.name AS name,
u.jwcode AS jwcode,
u.market AS market,
ugr.goods_name AS goodsName,
@ -17,13 +16,47 @@
ugr.remark AS remark,
a.admin_name AS adminName,
ugr.pay_time AS payTime
FROM
user u
FROM user u
JOIN
user_gold_record ugr ON u.jwcode = ugr.jwcode
JOIN
admin a ON ugr.admin_id = a.id
WHERE
WHERE ugr.type = 1
</select>
<!-- 查询筛选后消费记录 -->
<select id="selectBy" resultType="com.example.demo.domain.vo.Consume">
SELECT u.name AS name,
u.jwcode AS jwcode,
u.market AS market,
ugr.goods_name AS goodsName,
ugr.pay_platform AS payPlatform,
ugr.sum_gold AS sumGold,
ugr.permanent_gold AS permanentGold,
(COALESCE(ugr.free_june, 0) + COALESCE(ugr.free_december, 0)) AS freeGold,
ugr.task_gold AS taskGold,
ugr.remark AS remark,
a.admin_name AS adminName,
ugr.pay_time AS payTime
FROM user u
JOIN
user_gold_record ugr ON u.jwcode = ugr.jwcode
JOIN
admin a ON ugr.admin_id = a.id
<where>
ugr.type = 1
<if test="goodsName != null and goodsName != ''">
AND ugr.goods_name = #{goodsName}
</if>
<if test="market != null and market != ''">
AND u.market = #{market}
</if>
<if test="payPlatform != null and payPlatform != ''">
AND ugr.pay_platform = #{payPlatform}
</if>
<if test="startTime != null and endTime != null">
AND ugr.pay_time BETWEEN #{startTime} AND #{endTime}
</if>
</where>
</select>
</mapper>

3
src/main/resources/mapper/GeneralMapper.xml

@ -8,4 +8,7 @@
<select id="getPlatform" resultType="java.lang.String">
select DISTINCT pay_platform from user_gold_record
</select>
<select id="getGoods" resultType="java.lang.String">
select DISTINCT goods_name from user_gold_record
</select>
</mapper>

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

@ -54,5 +54,41 @@
and ugr.`audit_time` BETWEEN #{startTime} AND #{endTime}
</if>
</where>
</select>
<select id="getGold" resultType="com.example.demo.domain.entity.User">
select * from user
<where>
<if test="jwcode != null and jwcode.length > 0">
and jwcode = #{jwcode}
</if>
<if test="market != null and market.length > 0">
and market = #{market}
</if>
</where>
<choose>
<when test="sortField != null and sortField.length > 0 or sortOrder != null and sortOrder.length > 0">
ORDER BY ${sortField} ${sortOrder}
</when>
<otherwise>
ORDER BY create_time DESC
</otherwise>
</choose>
</select>
<select id="GoldTotal" resultType="com.example.demo.domain.vo.Total">
select
sum(current_permanent_gold) as permanentGold,
sum(current_free_june + current_free_december) as freeGold,
sum(current_task_gold) as taskGold,
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">
and jwcode = #{jwcode}
</if>
<if test="market != null and market.length > 0">
and market = #{market}
</if>
</where>
</select>
</mapper>
Loading…
Cancel
Save