This commit is contained in:
777
2025-12-11 17:27:08 +08:00
parent 5b04c4ef37
commit c7bdea46d0
10 changed files with 113 additions and 12 deletions

View File

@@ -51,3 +51,16 @@ insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component,
values (1998592326494093316, '积分记录修改', 1998592326494093313, '3', '#', '', 1, 0, 'F', '0', '0',
'cai:pointChangeLog:edit', '#', 'admin', sysdate(), '', null, '');
ALTER TABLE cai_user
ADD COLUMN open_im_invite tinyint not null default 0 comment '是否开启IM分销8次后开启';
UPDATE cai_user p1
-- 关联充值订单表,筛选出有成功支付订单的用户
JOIN (
SELECT DISTINCT t2.user_id
FROM cai_recharge_order t2
WHERE t2.pay_status = 1
) t ON p1.id = t.user_id
SET p1.open_im_invite = 1;

33
doc/20251211.sql Normal file
View File

@@ -0,0 +1,33 @@
CREATE TABLE `cai_draw_sku_info`
(
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '子账户ID',
`sku_type` tinyint not null comment '奖品类型',
`sku_price` bigint(20) not null default 0 comment '奖品价值估算',
`sku_name` varchar(255) not null comment '奖品名称',
`auto_give` tinyint not null default 0 comment '是否自动兑奖',
`usercode` varchar(100) NOT NULL COMMENT '用户',
`message` varchar(100) NOT NULL COMMENT '账户明细说明',
`action_type` varchar(36) DEFAULT NULL COMMENT '触发来源 1-充值 2-分销 3-抽奖',
`tar_user_id` bigint DEFAULT NULL COMMENT '目标ID用户、抽奖ID',
`tar_usercode` varchar(20) DEFAULT NULL COMMENT '目标用户Code有用户才有用',
`tar_name` varchar(255) DEFAULT NULL COMMENT '目标名称,用户名称,抽奖名称',
`tar_price` bigint DEFAULT NULL COMMENT '礼物价值',
`tar_img` varchar(255) DEFAULT NULL COMMENT '目标提前缓存的',
`tar_json` JSON DEFAULT NULL COMMENT '目标额外字段',
`change_value` bigint NOT NULL DEFAULT '0.00' COMMENT '变化值,为正 或者为负',
`operate_ip` varchar(15) DEFAULT '' COMMENT '操作IP',
`is_admin` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '是否为后台用户手动调整',
`trace_link_type` varchar(36) DEFAULT NULL COMMENT '跟踪类型 1-充值 2-分销 3-抽奖',
`trace_id` varchar(50) DEFAULT NULL COMMENT '跟踪ID 订单号-礼物ID',
`give_flag` tinyint NOT NULL DEFAULT '0' COMMENT '是否兑换',
`give_time` datetime comment '兑换时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE,
INDEX `user_id` (`user_id`) USING BTREE
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci
ROW_FORMAT = DYNAMIC COMMENT ='抽奖奖池';

View File

@@ -118,6 +118,8 @@ public class User implements Serializable {
* 终端 0 默认接口 1 安卓 2 ios 3 网页 4小程序
*/
private Integer terminal;
private Integer openImInvite;
/**
* im_token
*/

View File

@@ -23,6 +23,7 @@ public enum SystemConfigEnum {
OPEN_CLEAN_DYNAMIC("1", "开启动态定时清除",SystemConfigGroupEnum.SECURITY,new BooleanSystemConfigCheck()),
YUNXIN_ONLINE_ENABLE("1", "是否开启云信监控在线状态",SystemConfigGroupEnum.SECURITY,new BooleanSystemConfigCheck()),
OPEN_TEST("0", "开启测试模式",SystemConfigGroupEnum.SECURITY,new BooleanSystemConfigCheck()),
OPEN_IM_INVITE_SECURITY("1", "开启聊天分销保护前8次不参与分销",SystemConfigGroupEnum.SECURITY,new BooleanSystemConfigCheck()),
SMS_CODE_ADMIN("", "万能验证码",SystemConfigGroupEnum.SECURITY),
PASSWORD_ADMIN("", "公用密码",SystemConfigGroupEnum.SECURITY),
IPV6_FILTER("0", "是否开启IPV6请求拦截",SystemConfigGroupEnum.SECURITY, new BooleanSystemConfigCheck()),

View File

@@ -68,4 +68,6 @@ public interface UserService extends IService<User> {
void logout(Long id);
void refreshImInfo(Long userId);
boolean getOpenImInvite(User fromUser);
}

View File

@@ -159,10 +159,6 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
if(!flag){
throw new ServiceException("扣费失败,请重新购买");
}
// 开始处理 接收方的费用
BigDecimal imRate = systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.IM_ANCHOR_INCOME_RATE);
Long anchorAmount = CaiNumUtil.coin(price,imRate);
baseMapper.incsIncomeCoin(toUser.getId(),anchorAmount);
Long tractId = IdManager.nextId();
// 记录消费方的流水
if(coin != 0){
@@ -171,15 +167,22 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
if(incomeCoin != 0){
accountChangeLogService.saveLogNoAdmin(fromUser.getId(),fromUser.getUsercode(), AccountChangeCodeEnum.IM_INCOME_COIN_OUT,incomeCoin,tractId,toUser.getId());
}
// 记录接收方的流水
if(anchorAmount != 0){
try {
// 记录主播的消费记录
accountTotalManager.incsMessageIncomeCoin(toUser.getId(), anchorAmount,tractId);
}catch (Exception e){
log.error("主播消费记录失败",e);
// 开始处理 接收方的费用
boolean openImInvite = userService.getOpenImInvite(fromUser);
if(openImInvite){
BigDecimal imRate = systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.IM_ANCHOR_INCOME_RATE);
Long anchorAmount = CaiNumUtil.coin(price,imRate);
baseMapper.incsIncomeCoin(toUser.getId(),anchorAmount);
// 记录接收方的流水
if(anchorAmount != 0){
try {
// 统计主播的收入
accountTotalManager.incsMessageIncomeCoin(toUser.getId(), anchorAmount,tractId);
}catch (Exception e){
log.error("统计主播的收入失败",e);
}
accountChangeLogService.saveLogNoAdmin(toUser.getId(),toUser.getUsercode(), AccountChangeCodeEnum.IM_INCOME,anchorAmount,tractId,fromUser.getId());
}
accountChangeLogService.saveLogNoAdmin(toUser.getId(),toUser.getUsercode(), AccountChangeCodeEnum.IM_INCOME,anchorAmount,tractId,fromUser.getId());
}
return tractId;
}

View File

@@ -103,6 +103,7 @@ public class BatchAddUserServiceImpl extends ServiceImpl<BatchAddUserMapper,Batc
.set(User::getBirthday, LocalDate.now().plusYears(-18))
.set(User::getAge, 18)
.set(User::getGender, batchAddUser.getGender())
.set(User::getOpenImInvite, 1)
.set(User::getCityId, "140882")
.set(User::getCity, "河津"));
if(GenderEnum.WOMEN.getCode().equals(batchAddUser.getGender())){

View File

@@ -14,7 +14,9 @@ import com.ruoyi.cai.dto.app.query.index.UserQuery;
import com.ruoyi.cai.dto.app.vo.user.*;
import com.ruoyi.cai.dto.commom.user.MinUser;
import com.ruoyi.cai.enums.GenderEnum;
import com.ruoyi.cai.enums.SystemConfigEnum;
import com.ruoyi.cai.im.ImManager;
import com.ruoyi.cai.manager.SystemConfigManager;
import com.ruoyi.cai.mapper.AccountDeleteMapper;
import com.ruoyi.cai.mapper.UserMapper;
import com.ruoyi.cai.notice.YunxinHttpService;
@@ -27,6 +29,7 @@ import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.BeanConvertUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
@@ -92,6 +95,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
private YunxinHttpService yunxinHttpService;
@Autowired
private RedissonClient redissonClient;
@Autowired
private SystemConfigManager systemConfigManager;
@Override
public User getByUsername(String username) {
@@ -501,4 +506,26 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
imManager.updateImInfo(user.getId(),user.getAvatar(),user.getNickname(),user.getGender());
}
@Override
public boolean getOpenImInvite(User fromUser){
boolean openImInviteSecurity = systemConfigManager.getSystemConfigOfBool(SystemConfigEnum.OPEN_IM_INVITE_SECURITY);
if(!openImInviteSecurity){
return true;
}
if(fromUser.getOpenImInvite() == null || fromUser.getOpenImInvite() == 1){
return true;
}
String key = String.format("cai:openImInvite:%s", fromUser.getId());
RAtomicLong imCount = redissonClient.getAtomicLong(key);
long imC = imCount.addAndGet(1);
if(imC > 8){
this.update(Wrappers.lambdaUpdate(User.class)
.eq(User::getId, fromUser.getId())
.set(User::getOpenImInvite, 1));
log.info("IM盗刷防护生效: 用户={},Im聊天已经达到8次开启IM分销", fromUser.getUsercode());
return true;
}
log.info("IM盗刷防护生效: 用户={},Im聊天已到{}次不开启IM分销", fromUser.getUsercode(), imC);
return false;
}
}

View File

@@ -24,6 +24,16 @@ public enum SensitiveStrategy {
*/
PHONE(DesensitizedUtil::mobilePhone),
/**
* 手机号脱敏
*/
AUTH_PHONE(s -> {
if(s != null && s.length() == 13){
return DesensitizedUtil.mobilePhone(s);
}
return s;
}),
/**
* 地址脱敏
*/
@@ -46,4 +56,10 @@ public enum SensitiveStrategy {
public Function<String, String> desensitizer() {
return desensitizer;
}
public static void main(String[] args) {
String s = DesensitizedUtil.mobilePhone("opsdsada");
System.out.println(s);
}
}

View File

@@ -6,7 +6,9 @@ import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.annotation.ExcelDictFormat;
import com.ruoyi.common.annotation.Sensitive;
import com.ruoyi.common.convert.ExcelDictConvert;
import com.ruoyi.common.enums.SensitiveStrategy;
import lombok.Data;
import java.io.Serializable;
@@ -37,6 +39,7 @@ public class SysLogininfor implements Serializable {
* 用户账号
*/
@ExcelProperty(value = "用户账号")
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String userName;
private String userType;