|
@@ -7,11 +7,17 @@ import com.xuekairui.common.ErrorCode;
|
|
|
import com.xuekairui.invite.dto.InviteConfigRequest;
|
|
import com.xuekairui.invite.dto.InviteConfigRequest;
|
|
|
import com.xuekairui.invite.entity.InviteConfig;
|
|
import com.xuekairui.invite.entity.InviteConfig;
|
|
|
import com.xuekairui.invite.mapper.InviteConfigMapper;
|
|
import com.xuekairui.invite.mapper.InviteConfigMapper;
|
|
|
|
|
+import com.xuekairui.user.enums.OperationSource;
|
|
|
|
|
+import com.xuekairui.user.enums.OperationType;
|
|
|
|
|
+import com.xuekairui.user.enums.OperatorRole;
|
|
|
|
|
+import com.xuekairui.user.service.OperationAuditLogService;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 邀请配置服务(运营管理)
|
|
* 邀请配置服务(运营管理)
|
|
@@ -23,47 +29,60 @@ import java.util.List;
|
|
|
public class InviteConfigService {
|
|
public class InviteConfigService {
|
|
|
|
|
|
|
|
private final InviteConfigMapper inviteConfigMapper;
|
|
private final InviteConfigMapper inviteConfigMapper;
|
|
|
|
|
+ private final OperationAuditLogService auditLogService;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 获取当前生效的邀请配置
|
|
|
|
|
|
|
+ * 获取当前生效的邀请配置(优先 status=1,LIMIT 1 避免全表加载)
|
|
|
*/
|
|
*/
|
|
|
public InviteConfig getActiveConfig() {
|
|
public InviteConfig getActiveConfig() {
|
|
|
- List<InviteConfig> configs = inviteConfigMapper.selectList(null);
|
|
|
|
|
- if (configs.isEmpty()) {
|
|
|
|
|
- // 返回默认配置
|
|
|
|
|
- return InviteConfig.builder()
|
|
|
|
|
- .rewardType("MEMBERSHIP")
|
|
|
|
|
- .rewardMonths(1)
|
|
|
|
|
- .rewardCrawlerCount(5)
|
|
|
|
|
- .maxDailyReward(50)
|
|
|
|
|
- .inviteCodeExpireDays(30)
|
|
|
|
|
- .maxInvitePerDay(10)
|
|
|
|
|
- .maxTotalInvites(30)
|
|
|
|
|
- .landingTitle("邀请你加入智价云(药店版)")
|
|
|
|
|
- .landingDesc("登录智价云(药店版),邀请好友各得好礼")
|
|
|
|
|
- .appName("智价云(药店版)")
|
|
|
|
|
- .status(1)
|
|
|
|
|
- .build();
|
|
|
|
|
- }
|
|
|
|
|
- // 返回第一个启用的配置,如果没有启用的则返回第一个
|
|
|
|
|
- return configs.stream()
|
|
|
|
|
- .filter(c -> c.getStatus() != null && c.getStatus() == 1)
|
|
|
|
|
- .findFirst()
|
|
|
|
|
- .orElse(configs.get(0));
|
|
|
|
|
|
|
+ // 优先查启用的配置
|
|
|
|
|
+ InviteConfig config = inviteConfigMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<InviteConfig>()
|
|
|
|
|
+ .eq(InviteConfig::getStatus, 1)
|
|
|
|
|
+ .orderByDesc(InviteConfig::getCreateTime)
|
|
|
|
|
+ .last("LIMIT 1"));
|
|
|
|
|
+ if (config != null) {
|
|
|
|
|
+ return config;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 无启用配置时返回默认
|
|
|
|
|
+ return InviteConfig.builder()
|
|
|
|
|
+ .rewardType("MEMBERSHIP")
|
|
|
|
|
+ .rewardMonths(1)
|
|
|
|
|
+ .rewardCrawlerCount(0)
|
|
|
|
|
+ .maxDailyReward(50)
|
|
|
|
|
+ .inviteCodeExpireDays(30)
|
|
|
|
|
+ .maxInvitePerDay(10)
|
|
|
|
|
+ .maxTotalInvites(30)
|
|
|
|
|
+ .landingTitle("邀请你加入智价云(药店版)")
|
|
|
|
|
+ .landingDesc("登录智价云(药店版),邀请好友各得好礼")
|
|
|
|
|
+ .appName("智价云(药店版)")
|
|
|
|
|
+ .status(1)
|
|
|
|
|
+ .build();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 更新当前生效的邀请配置(无则自动创建)
|
|
|
|
|
|
|
+ * 更新当前生效的邀请配置(无已存在配置时报错,需先创建)
|
|
|
*/
|
|
*/
|
|
|
public InviteConfig updateConfig(InviteConfigRequest request) {
|
|
public InviteConfig updateConfig(InviteConfigRequest request) {
|
|
|
- InviteConfig config = getActiveConfig();
|
|
|
|
|
|
|
+ InviteConfig config = inviteConfigMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<InviteConfig>()
|
|
|
|
|
+ .eq(InviteConfig::getStatus, 1)
|
|
|
|
|
+ .orderByDesc(InviteConfig::getCreateTime)
|
|
|
|
|
+ .last("LIMIT 1"));
|
|
|
|
|
+ if (config == null) {
|
|
|
|
|
+ throw new BusinessException(ErrorCode.BUSINESS_ERROR, "暂无可更新的邀请配置,请先创建");
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Object> beforeData = configSnapshot(config);
|
|
|
buildConfigFromRequest(config, request);
|
|
buildConfigFromRequest(config, request);
|
|
|
|
|
+ inviteConfigMapper.updateById(config);
|
|
|
|
|
|
|
|
- if (config.getId() != null) {
|
|
|
|
|
- inviteConfigMapper.updateById(config);
|
|
|
|
|
- } else {
|
|
|
|
|
- inviteConfigMapper.insert(config);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ Map<String, Object> afterData = configSnapshot(config);
|
|
|
|
|
+ auditLogService.logSuccess(
|
|
|
|
|
+ 0L, OperatorRole.ADMIN, OperationType.INVITE_CONFIG_UPDATE,
|
|
|
|
|
+ "INVITE_CONFIG:" + config.getId(), config.getId(),
|
|
|
|
|
+ beforeData, afterData,
|
|
|
|
|
+ "邀请配置变更",
|
|
|
|
|
+ OperationSource.ADMIN_CREATE);
|
|
|
|
|
|
|
|
log.info("邀请配置已更新: rewardType={}, rewardMonths={}, appDownloadUrl={}, miniappPath={}",
|
|
log.info("邀请配置已更新: rewardType={}, rewardMonths={}, appDownloadUrl={}, miniappPath={}",
|
|
|
config.getRewardType(), config.getRewardMonths(), config.getAppDownloadUrl(), config.getMiniappPath());
|
|
config.getRewardType(), config.getRewardMonths(), config.getAppDownloadUrl(), config.getMiniappPath());
|
|
@@ -104,15 +123,23 @@ public class InviteConfigService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 更新指定ID的邀请配置
|
|
|
|
|
|
|
+ * 更新指定ID的邀请配置(含变更前后快照)
|
|
|
*/
|
|
*/
|
|
|
public InviteConfig updateConfig(Long id, InviteConfigRequest request) {
|
|
public InviteConfig updateConfig(Long id, InviteConfigRequest request) {
|
|
|
InviteConfig config = inviteConfigMapper.selectById(id);
|
|
InviteConfig config = inviteConfigMapper.selectById(id);
|
|
|
if (config == null) {
|
|
if (config == null) {
|
|
|
throw new BusinessException(ErrorCode.NOT_FOUND, "邀请配置不存在");
|
|
throw new BusinessException(ErrorCode.NOT_FOUND, "邀请配置不存在");
|
|
|
}
|
|
}
|
|
|
|
|
+ Map<String, Object> beforeData = configSnapshot(config);
|
|
|
buildConfigFromRequest(config, request);
|
|
buildConfigFromRequest(config, request);
|
|
|
inviteConfigMapper.updateById(config);
|
|
inviteConfigMapper.updateById(config);
|
|
|
|
|
+ Map<String, Object> afterData = configSnapshot(config);
|
|
|
|
|
+ auditLogService.logSuccess(
|
|
|
|
|
+ 0L, OperatorRole.ADMIN, OperationType.INVITE_CONFIG_UPDATE,
|
|
|
|
|
+ "INVITE_CONFIG:" + id, id,
|
|
|
|
|
+ beforeData, afterData,
|
|
|
|
|
+ "邀请配置变更(指定ID)",
|
|
|
|
|
+ OperationSource.ADMIN_CREATE);
|
|
|
log.info("更新邀请配置: id={}, rewardType={}, rewardMonths={}", config.getId(), config.getRewardType(), config.getRewardMonths());
|
|
log.info("更新邀请配置: id={}, rewardType={}, rewardMonths={}", config.getId(), config.getRewardType(), config.getRewardMonths());
|
|
|
return config;
|
|
return config;
|
|
|
}
|
|
}
|
|
@@ -222,4 +249,24 @@ public class InviteConfigService {
|
|
|
}
|
|
}
|
|
|
return config;
|
|
return config;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /** 邀请配置快照(用于变更前后对比审计) */
|
|
|
|
|
+ private Map<String, Object> configSnapshot(InviteConfig c) {
|
|
|
|
|
+ Map<String, Object> s = new HashMap<>();
|
|
|
|
|
+ s.put("status", c.getStatus());
|
|
|
|
|
+ s.put("rewardType", c.getRewardType());
|
|
|
|
|
+ s.put("rewardMonths", c.getRewardMonths());
|
|
|
|
|
+ s.put("rewardCrawlerCount", c.getRewardCrawlerCount());
|
|
|
|
|
+ s.put("maxDailyReward", c.getMaxDailyReward());
|
|
|
|
|
+ s.put("inviteCodeExpireDays", c.getInviteCodeExpireDays());
|
|
|
|
|
+ s.put("maxInvitePerDay", c.getMaxInvitePerDay());
|
|
|
|
|
+ s.put("maxTotalInvites", c.getMaxTotalInvites());
|
|
|
|
|
+ s.put("appName", c.getAppName());
|
|
|
|
|
+ s.put("landingTitle", c.getLandingTitle());
|
|
|
|
|
+ s.put("landingDesc", c.getLandingDesc());
|
|
|
|
|
+ s.put("appDownloadUrl", c.getAppDownloadUrl());
|
|
|
|
|
+ s.put("miniappPath", c.getMiniappPath());
|
|
|
|
|
+ s.put("remark", c.getRemark());
|
|
|
|
|
+ return s;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|