src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java
@@ -65,4 +65,21 @@ } // === 自动发送 end === // === 自动发送 start === @Bean public DirectExchange imOverdueSendExchange() { return new DirectExchange(RabbitQueueEnum.IM_REDBAG_OVERDUE.getExchange()); } @Bean public Queue imOverdueSendQueue() { return new Queue(RabbitQueueEnum.IM_REDBAG_OVERDUE.getQueue()); } @Bean public Binding imOverdueSendBind() { return BindingBuilder.bind(imOverdueSendQueue()).to(imOverdueSendExchange()).with(RabbitQueueEnum.IM_REDBAG_OVERDUE.getRoute()); } // === 自动发送 end === } src/main/java/cc/mrbird/febs/mall/controller/AdminChatController.java
@@ -46,6 +46,19 @@ } /** * 用户收益列表 * * @param chatUser * @param request * @return */ @GetMapping("getUserPerkList") public FebsResponse getUserPerkList(ChatUser chatUser, QueryRequest request) { Map<String, Object> data = getDataTable(iAdminChatService.getUserPerkList(chatUser, request)); return new FebsResponse().success().data(data); } /** * 用户列表---开启 * * @param userId src/main/java/cc/mrbird/febs/mall/controller/ViewChatController.java
@@ -46,6 +46,16 @@ } /** * 用户收益列表 * @return */ @GetMapping("userPerkList") @RequiresPermissions("userPerkList:view") public String userPerkList() { return FebsUtil.view("modules/chat/userPerkList"); } /** * 用户列表-新增会员 * @param model * @return src/main/java/cc/mrbird/febs/mall/mapper/ChatUserMapper.java
@@ -17,6 +17,8 @@ IPage<AdminChatUserVo> selectUserListInPage(Page<AdminChatUserVo> page, @Param("record")ChatUser chatUser); IPage<AdminChatUserPerkVo> selectUserPerkListInPage(Page<AdminChatUserPerkVo> page, @Param("record")ChatUser chatUser); ChatUser selectByUserId(@Param("userId")String userId); void updateStatusByUserId(@Param("userId")String userId, @Param("status")String code); @@ -67,5 +69,11 @@ BigDecimal selectTotalType(@Param("type")int i,@Param("dateType") String type, @Param("date") Date date); List<AdminChatRedBagVo> selectListByMsgType(@Param("userId")Long userId,@Param("msgType")String msgType, @Param("date") Date date); List<ChatUser> selectUserList(@Param("isRobot")int i,@Param("dateType") String type, @Param("date") Date date); List<AdminChatRedBagVo> selectByOverDueStatueAndTime(@Param("overdueState")Integer overdueState, @Param("overdueTime")Date overdueTime); void updateOverdueStatusById(@Param("overdueState")Integer overdueState, @Param("id")Long id); } src/main/java/cc/mrbird/febs/mall/quartz/ProfitJob.java
@@ -15,6 +15,7 @@ import cc.mrbird.febs.mall.service.IApiMallMemberWalletService; import cc.mrbird.febs.mall.service.IMemberProfitService; import cc.mrbird.febs.mall.service.impl.CommonService; import cc.mrbird.febs.mall.vo.AdminChatRedBagVo; import cc.mrbird.febs.rabbit.producter.AgentProducer; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; @@ -55,7 +56,7 @@ /** * 代理分红 */ // @Scheduled(cron = "0 0/1 * * * ? ") @Scheduled(cron = "0 0/1 * * * ? ") @Scheduled(cron = "0/2 * * * * ? ") // @Scheduled(cron = "0/30 * * * * ? ") public void profitJob() { @@ -70,12 +71,24 @@ } // @Scheduled(cron = "0/2 * * * * ? ") // @Scheduled(cron = "0 0 0/1 * * ? ") // public void robotNickNameJob() { // List<ChatUser> chatUsers = chatUserMapper.selectListByIsRobot(1); // if(CollUtil.isNotEmpty(chatUsers)){ // for(ChatUser chatUser : chatUsers){ // chatUserMapper.updateNicknameById(chatUser.getUserId(),randomName(RandomUtil.randomInt(1, 5))); // } // } // } // @Scheduled(cron = "0/2 * * * * ? ") @Scheduled(cron = "0 0 0/1 * * ? ") public void robotNickNameJob() { List<ChatUser> chatUsers = chatUserMapper.selectListByIsRobot(1); if(CollUtil.isNotEmpty(chatUsers)){ for(ChatUser chatUser : chatUsers){ chatUserMapper.updateNicknameById(chatUser.getUserId(),randomName(RandomUtil.randomInt(1, 5))); public void returnRedBagAmount() { List<AdminChatRedBagVo> adminChatRedBagVos = chatUserMapper.selectByOverDueStatueAndTime(2, DateUtil.date()); if(CollUtil.isNotEmpty(adminChatRedBagVos)){ for(AdminChatRedBagVo adminChatRedBagVo : adminChatRedBagVos){ chatUserMapper.updateOverdueStatusById(1,adminChatRedBagVo.getId()); agentProducer.sendOverdueSendMsg(adminChatRedBagVo.getId()); } } } src/main/java/cc/mrbird/febs/mall/service/IAdminChatService.java
@@ -12,6 +12,8 @@ IPage<AdminChatUserVo> getUserList(ChatUser chatUser, QueryRequest request); IPage<AdminChatUserPerkVo> getUserPerkList(ChatUser chatUser, QueryRequest request); FebsResponse openAccount(String userId); FebsResponse closeAccount(String userId); src/main/java/cc/mrbird/febs/mall/service/impl/AdminChatServiceImpl.java
@@ -10,6 +10,7 @@ import cc.mrbird.febs.mall.service.IAdminChatService; import cc.mrbird.febs.mall.vo.*; import cc.mrbird.febs.rabbit.producter.AgentProducer; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -22,6 +23,7 @@ import org.springframework.util.StringUtils; import java.math.BigDecimal; import java.util.List; @Slf4j @Service @@ -44,6 +46,25 @@ } @Override public IPage<AdminChatUserPerkVo> getUserPerkList(ChatUser chatUser, QueryRequest request) { Page<AdminChatUserPerkVo> page = new Page<>(request.getPageNum(), request.getPageSize()); IPage<AdminChatUserPerkVo> chatUserPerkVoIPage = this.baseMapper.selectUserPerkListInPage(page, chatUser); List<AdminChatUserPerkVo> records = chatUserPerkVoIPage.getRecords(); if(CollUtil.isNotEmpty(records)){ for(AdminChatUserPerkVo adminChatUserPerkVo : records){ Long userId = adminChatUserPerkVo.getUserId(); List<AdminChatRedBagVo> group = this.baseMapper.selectListByMsgType(userId,"GROUP", null); adminChatUserPerkVo.setGroupRedBagNum(CollUtil.isEmpty(group) ? 0 : group.size()); BigDecimal redBagTotalAmount = group.stream().map(AdminChatRedBagVo::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); adminChatUserPerkVo.setRedBagTotalAmount(redBagTotalAmount); BigDecimal redBagAvaAmount = group.stream().map(AdminChatRedBagVo::getAmountAva).reduce(BigDecimal.ZERO, BigDecimal::add); adminChatUserPerkVo.setRedBagAvaAmount(redBagAvaAmount); } } return chatUserPerkVoIPage; } @Override public FebsResponse openAccount(String userId) { ChatUser chatUser = this.baseMapper.selectByUserId(userId); if(ObjectUtil.isEmpty(chatUser)) { src/main/java/cc/mrbird/febs/mall/vo/AdminChatRedBagVo.java
New file @@ -0,0 +1,71 @@ package cc.mrbird.febs.mall.vo; import lombok.Data; import java.math.BigDecimal; import java.util.Date; @Data public class AdminChatRedBagVo { private Long id; /** * 消息ID */ private Long msgId; /** * 消息类型SINGLE/GROUP */ private String msgType; /** * 红包z总个数 */ private Integer totalCnt; /** * 剩余红包个数 */ private Integer avaCnt; /** * 金额 */ private BigDecimal amount; /** * 剩余金额 */ private BigDecimal amountAva; /** * 钱包类型 USDT RMB */ private String amountType; /** * 是否被领取 1:是 2:否 */ private Integer state; /** * 是否已过期 1:是2:否 */ private Integer overdueState; /** * 创建时间 */ private Date createTime; /** * 过期时间 */ private Date overdueTime; /** * 版本控制 */ private Integer version; /** * 发送方 */ private Long fromUserId; /** * 接收方 */ private Long toUserId; /** * 雷 */ private Integer boomNum; } src/main/java/cc/mrbird/febs/mall/vo/AdminChatUserPerkVo.java
New file @@ -0,0 +1,59 @@ package cc.mrbird.febs.mall.vo; import lombok.Data; import java.math.BigDecimal; @Data public class AdminChatUserPerkVo { private Long userId; /** * 昵称 */ private String nickName; /** * 微聊号 */ private String chatNo; /** * 注册时间 */ private String createTime; /** * 账户总额 */ private BigDecimal totalAmount; /** * 账户可用 */ private BigDecimal avaAmount; /** * 邀请码 */ private String inviteId; /** * 邀请码 */ private String phone; /** * 是否是机器人 0:否 1:是 */ private Integer isRobot; /** * 发红包个数 */ private Integer groupRedBagNum; /** * 发出去的红包总额 */ private BigDecimal redBagTotalAmount; /** * 剩余未领取的总额 */ private BigDecimal redBagAvaAmount; } src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java
@@ -15,4 +15,9 @@ * 添加机器人 */ public static final String QUEUE_IM_REDBAG_ADD_ROBOT = "queue_im_redbag_add_robot"; /** * 自动返还 */ public static final String QUEUE_IM_REDBAG_OVERDUE = "queue_im_redbag_overdue"; } src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java
@@ -6,6 +6,7 @@ @Getter public enum RabbitQueueEnum { IM_REDBAG_OVERDUE("exchange_im_redbag_overdue", "route_key_im_redbag_overdue", QueueConstants.QUEUE_IM_REDBAG_OVERDUE), IM_REDBAG_AUTO_SEND("exchange_im_redbag_auto_send", "route_key_im_redbag_auto_send", QueueConstants.QUEUE_IM_REDBAG_AUTO_SEND), IM_REDBAG_GET_ADD_ROBOT("exchange_im_redbag_add_robot", "route_key_im_redbag_add_robot", QueueConstants.QUEUE_IM_REDBAG_ADD_ROBOT); src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java
@@ -70,4 +70,16 @@ correlationData); } /** * 自动返还 */ public void sendOverdueSendMsg(Long redbagId) { log.info("自动返还:{}", redbagId); CorrelationData correlationData = new CorrelationData(IdUtil.simpleUUID()); rabbitTemplate.convertAndSend(RabbitQueueEnum.IM_REDBAG_OVERDUE.getExchange(), RabbitQueueEnum.IM_REDBAG_OVERDUE.getRoute(), redbagId, correlationData); } } src/main/resources/mapper/modules/ChatUserMapper.xml
@@ -35,6 +35,36 @@ order by a.create_time desc </select> <select id="selectUserPerkListInPage" resultType="cc.mrbird.febs.mall.vo.AdminChatUserPerkVo"> select a.user_id userId, a.nick_name nickName, a.chat_no chatNo, a.phone phone, a.invite_id inviteId, a.is_robot isRobot, date_format(a.create_time, '%Y-%m-%d %H:%m:%s') createTime, IFNULL(sum(b.total_amount), 0) totalAmount, IFNULL(sum(b.ava_amount), 0) avaAmount from chat_user a left join chat_wallet b on b.user_id = a.user_id and type = 'USDT' <where> <if test="record != null"> <if test="record.nickName != null and record.nickName != ''"> and a.nick_name like CONCAT('%', CONCAT(#{record.nickName}, '%')) </if> <if test="record.inviteId != null and record.inviteId != ''"> and a.invite_id = #{record.inviteId} </if> <if test="record.status != null and record.status != ''"> and a.status = #{record.status} </if> </if> </where> group by a.user_id order by a.create_time desc </select> <select id="selectByUserId" resultType="cc.mrbird.febs.mall.entity.ChatUser"> select a.* @@ -317,5 +347,33 @@ </if> </select> <select id="selectListByMsgType" resultType="cc.mrbird.febs.mall.vo.AdminChatRedBagVo"> select a.* from chat_red_bag a where a.msg_type = #{msgType} <if test='date != "" and date != null'> and date_format(a.create_time, '%Y-%m-%d') = date_format(#{date}, '%Y-%m-%d') </if> and a.from_user_id = #{userId} </select> <select id="selectByOverDueStatueAndTime" resultType="cc.mrbird.febs.mall.vo.AdminChatRedBagVo"> select * from chat_red_bag where overdue_state = #{overdueState} and #{overdueTime} > overdue_time order by id asc limit 500 </select> <update id="updateOverdueStatusById"> update chat_red_bag set overdue_state = #{overdueState} where id = #{id} </update> </mapper> src/main/resources/templates/febs/views/modules/chat/userPerkList.html
New file @@ -0,0 +1,229 @@ <div class="layui-fluid layui-anim febs-anim" id="febs-chat-user-perk-list" lay-title="用户收益列表"> <div class="layui-row febs-container"> <div class="layui-col-md12"> <div class="layui-card"> <div class="layui-card-body febs-table-full"> <form class="layui-form layui-table-form" lay-filter="user-table-form"> <div class="layui-row"> <div class="layui-col-md10"> <div class="layui-form-item"> <div class="layui-inline"> <label class="layui-form-label">昵称:</label> <div class="layui-input-inline"> <input type="text" placeholder="昵称" name="nickName" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-inline"> <label class="layui-form-label">邀请码:</label> <div class="layui-input-inline"> <input type="text" placeholder="邀请码" name="inviteId" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-inline"> <label class="layui-form-label">账号状态:</label> <div class="layui-input-inline"> <select name="status"> <option value="">请选择</option> <option value="Y">正常</option> <option value="N">禁用</option> </select> </div> </div> </div> </div> <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area"> <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query"> <i class="layui-icon"></i> </div> <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset"> <i class="layui-icon"></i> </div> </div> </div> </form> <table lay-filter="userChatTable" lay-data="{id: 'userChatTable'}"></table> </div> </div> </div> </div> </div> <!-- 表格操作栏 start --> <script type="text/html" id="user-option"> <span shiro:lacksPermission="user:view,user:update,user:delete"> <span class="layui-badge-dot febs-bg-orange"></span> 无权限 </span> <a lay-event="edit" shiro:hasPermission="user:update"><i class="layui-icon febs-edit-area febs-blue"></i></a> </script> <script type="text/html" id="switchIsRobot"> {{# if(d.isRobot === 1) { }} <input type="checkbox" value={{d.userId}} lay-text="是|否" checked lay-skin="switch" lay-filter="switchIsRobot"> {{# } else { }} <input type="checkbox" value={{d.userId}} lay-text="是|否" lay-skin="switch" lay-filter="switchIsRobot"> {{# } }} </script> <style> .layui-form-onswitch { background-color: #5FB878 !important; } </style> <script type="text/html" id="toolbar"> <div class="layui-btn-container"> <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" lay-event="registerMember">添加会员</button> <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" lay-event="balance">拨付余额</button> </div> </script> <!-- 表格操作栏 end --> <script data-th-inline="none" type="text/javascript"> // 引入组件并初始化 layui.use([ 'jquery', 'form', 'table', 'febs'], function () { var $ = layui.jquery, febs = layui.febs, form = layui.form, table = layui.table, $view = $('#febs-chat-user-perk-list'), $query = $view.find('#query'), $reset = $view.find('#reset'), $searchForm = $view.find('form'), sortObject = {field: 'phone', type: null}, tableIns; form.render(); let currPageUser = 1;//首先默认值为1,防止出错 //获取当前页 currPageUser = $view.find(".layui-laypage-em").next().html(); // 表格初始化 initTable(); // 查询按钮 $query.on('click', function () { var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type}); tableIns.reload({where: params, page: {curr: 1}}); }); // 刷新按钮 $reset.on('click', function () { $searchForm[0].reset(); sortObject.type = 'null'; tableIns.reload({where: getQueryParams(), page: {curr: currPageUser}, initSort: sortObject}); }); // 获取查询参数 function getQueryParams() { return { nickName: $searchForm.find('input[name="nickName"]').val().trim(), inviteId: $searchForm.find('input[name="inviteId"]').val().trim(), status: $searchForm.find("select[name='status']").val() }; } function initTable() { tableIns = febs.table.init({ elem: $view.find('table'), id: 'userChatTable', url: ctx + 'admin/chat/getUserPerkList', toolbar:"#toolbar", defaultToolbar:[], totalRow: true ,// 开启合计行 cols: [[ {type: 'checkbox'}, {field: 'userId', title: '标识', minWidth: 150,align:'left'}, {field: 'nickName', title: '昵称', minWidth: 100,align:'left', totalRowText: '合计:',align:'center'}, {field: 'inviteId', title: '邀请码', minWidth: 100,align:'left',align:'center'}, {field: 'phone', title: '注册号码', minWidth: 150,align:'left',align:'center'}, {field: 'totalAmount', title: '账户总额', minWidth: 80,align:'left',totalRow: '{{= parseInt(d.totalAmount) }}',align:'center'}, {field: 'avaAmount', title: '账户余额', minWidth: 80,align:'left',totalRow: '{{= parseInt(d.avaAmount) }}',align:'center'}, {field: 'groupRedBagNum', title: '群红包数', minWidth: 80,align:'left'}, {field: 'redBagTotalAmount', title: '红包总额', minWidth: 80,align:'left'}, {field: 'redBagAvaAmount', title: '未领取', minWidth: 80,align:'left'}, // {field: 'isRobot', title: '机器人', templet: '#switchIsRobot', minWidth: 80,align:'center'}, {field: 'createTime', title: '注册时间', minWidth: 180,align:'center'}, ]] }); } table.on('toolbar(userChatTable)', function(obj){ var data = obj.data, layEvent = obj.event; // if (layEvent === 'registerMember') { // febs.get(ctx + 'admin/chat/registerMember/', null, function () { // febs.alert.success('操作成功'); // $query.click(); // }); // } if (layEvent === 'registerMember') { var checkData = table.checkStatus('userChatTable').data; if (checkData.length <= 0) { febs.alert.warn('请选择需要的用户'); return; } if (checkData.length > 1) { febs.alert.warn('请选择一个用户'); return; } registerMember("添加会员", checkData[0].inviteId, 1); } if (layEvent === 'balance') { var checkData = table.checkStatus('userChatTable').data; if (checkData.length <= 0) { febs.alert.warn('请选择需要的用户'); return; } if (checkData.length > 1) { febs.alert.warn('请选择一个用户'); return; } systemPay("修改余额", checkData[0].userId, 1); } }); function registerMember(text, inviteId, type) { febs.modal.open(text, 'modules/chat/mallRegisterMember/'+ inviteId, { btn: ['提交', '取消'], yes: function (index, layero) { $('#chat-register-member').find('#submit').trigger('click'); }, btn2: function () { layer.closeAll(); } }); } function systemPay(text, userId, type) { febs.modal.open(text, 'modules/chat/mallSystemPay/'+ userId, { btn: ['提交', '取消'], yes: function (index, layero) { $('#chat-systemPay-update').find('#submit').trigger('click'); }, btn2: function () { layer.closeAll(); } }); } form.on('switch(switchIsRobot)', function (data) { if (data.elem.checked) { openSwitchIsRobot(data.value); } else { closeSwitchIsRobot(data.value); } }) function openSwitchIsRobot(userId) { febs.get(ctx + 'admin/chat/openSwitchIsRobot/' + userId, null, function () { febs.alert.success('操作成功'); $reset.click(); }); } function closeSwitchIsRobot(userId) { febs.get(ctx + 'admin/chat/closeSwitchIsRobot/' + userId, null, function () { febs.alert.success('操作成功'); $reset.click(); }); } }) </script>