fix: 增加催促功能

This commit is contained in:
tangwei 2026-05-14 14:12:40 +08:00
parent b7d47f2268
commit 83038f6fbe
9 changed files with 133 additions and 14 deletions

View File

@ -46,7 +46,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -162,7 +161,6 @@ public class FishDraftDataController {
@PostMapping("/batchSaveDraft") @PostMapping("/batchSaveDraft")
@Operation(summary = "批量保存草稿") @Operation(summary = "批量保存草稿")
@Transactional(rollbackFor = Exception.class)
public ResponseResult saveDraft(@RequestBody FishImportRowRequest request) { public ResponseResult saveDraft(@RequestBody FishImportRowRequest request) {
String taskId = request.getTaskId(); String taskId = request.getTaskId();
ImportTask importTask = importTaskService.getById(taskId); ImportTask importTask = importTaskService.getById(taskId);
@ -185,7 +183,7 @@ public class FishDraftDataController {
data.setPicpthList(row.getPicpthList()); data.setPicpthList(row.getPicpthList());
fishDraftDataList.add(data); fishDraftDataList.add(data);
} }
boolean result = fishDraftDataService.saveBatch(fishDraftDataList); boolean result = fishDraftDataService.batchSaveDraft(fishDraftDataList);
fishImportService.processAttachmentsAsync(fishDraftDataList, importTask.getTempDir()); fishImportService.processAttachmentsAsync(fishDraftDataList, importTask.getTempDir());
importTaskService.markSuccess(taskId); importTaskService.markSuccess(taskId);
return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败"); return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败");

View File

@ -33,4 +33,6 @@ public class FishStatisticsVO implements Serializable {
private Date maxEnddt; private Date maxEnddt;
private Integer totalFcnt; private Integer totalFcnt;
private Integer hasData;
} }

View File

@ -96,4 +96,9 @@ public interface IFishDraftDataService extends IService<FishDraftData> {
* 审批人修改数据并记录变更日志 * 审批人修改数据并记录变更日志
*/ */
boolean updateByIdWithLog(FishDraftData fishDraftData); boolean updateByIdWithLog(FishDraftData fishDraftData);
/**
* 批量保存草稿带事务仅包裹 INSERT
*/
boolean batchSaveDraft(List<FishDraftData> fishDraftDataList);
} }

View File

@ -657,5 +657,15 @@ public class FishDraftDataServiceImpl extends ServiceImpl<FishDraftDataMapper, F
} }
} }
@Override
@Transactional(rollbackFor = Exception.class)
public boolean batchSaveDraft(List<FishDraftData> fishDraftDataList) {
if (fishDraftDataList == null || fishDraftDataList.isEmpty()) {
return false;
}
long start = System.currentTimeMillis();
boolean result = this.saveBatch(fishDraftDataList, 500);
log.info("批量保存草稿完成, 共{}条, 耗时{}ms", fishDraftDataList.size(), System.currentTimeMillis() - start);
return result;
}
} }

View File

@ -21,6 +21,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -41,6 +42,7 @@ import java.util.stream.Collectors;
@RestController @RestController
@RequestMapping("/sms") @RequestMapping("/sms")
@Tag(name = "短信验证码管理") @Tag(name = "短信验证码管理")
@Slf4j
public class SmsVerifyCodeController { public class SmsVerifyCodeController {
@Resource @Resource
@ -69,6 +71,7 @@ public class SmsVerifyCodeController {
@Value("${rsa.private_key}") @Value("${rsa.private_key}")
private String privateKey; private String privateKey;
private static final String URGE_CONTENT ="根据生态环境部要求,请贵电站尽快完成过鱼数据的报送工作,感谢支持。";
/** /**
* 发送验证码 * 发送验证码
@ -125,10 +128,10 @@ public class SmsVerifyCodeController {
/** /**
* 发送验证码 * 批量发送短信
*/ */
@PostMapping("/batchSendContent") @PostMapping("/batchSendContent")
@Operation(summary = "发送验证码") @Operation(summary = "批量发送短信")
public ResponseResult batchSendContent(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) { public ResponseResult batchSendContent(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
List<String> phoneList = smsVerifyCodeRequest.getPhoneList(); List<String> phoneList = smsVerifyCodeRequest.getPhoneList();
@ -140,6 +143,35 @@ public class SmsVerifyCodeController {
return ResponseResult.success(); return ResponseResult.success();
} }
/**
* 批量催促
*/
@PostMapping("/batchUrgeContent")
@Operation(summary = "催促")
public ResponseResult batchUrgeContent(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) {
List<String> userIds = smsVerifyCodeRequest.getUserIds();
String content = smsVerifyCodeRequest.getContent();
if ((userIds == null || userIds.isEmpty())) {
return ResponseResult.error("用户ID不能为空");
}
if (content == null || content.isEmpty()) {
content = URGE_CONTENT;
}
try {
int successCount = smsVerifyCodeService.urgeByUserIds(userIds, content);
Map<String, Object> result = new HashMap<>();
// result.put("successCount", successCount);
result.put("totalCount", userIds.size());
return ResponseResult.successData(result);
} catch (Exception e) {
log.error("批量催促短信发送失败", e);
return ResponseResult.error("短信发送失败: " + e.getMessage());
}
}
/** /**

View File

@ -67,5 +67,10 @@ public class SmsVerifyCodeRequest {
private String content; private String content;
/**
* 用户编号
*/
private List<String> userIds;
} }

View File

@ -50,4 +50,5 @@ public interface ISmsVerifyCodeService extends IService<SmsVerifyCode> {
boolean sendAuditNotify(String phone, String auditStatus, String reason); boolean sendAuditNotify(String phone, String auditStatus, String reason);
void batchSendContent(List<String> phoneList, String content); void batchSendContent(List<String> phoneList, String content);
int urgeByUserIds(List<String> userIds, String content);
} }

View File

@ -1,18 +1,24 @@
package com.yfd.platform.system.service.impl; package com.yfd.platform.system.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.system.domain.SmsVerifyCode; import com.yfd.platform.system.domain.SmsVerifyCode;
import com.yfd.platform.system.domain.SysUser;
import com.yfd.platform.system.mapper.SmsVerifyCodeMapper; import com.yfd.platform.system.mapper.SmsVerifyCodeMapper;
import com.yfd.platform.system.mapper.SysUserMapper;
import com.yfd.platform.system.service.ISmsVerifyCodeService; import com.yfd.platform.system.service.ISmsVerifyCodeService;
import com.yfd.platform.utils.SmsSender; import com.yfd.platform.utils.SmsSender;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/** /**
* <p> * <p>
@ -20,14 +26,19 @@ import java.util.Random;
* </p> * </p>
*/ */
@Service @Service
@Slf4j
public class SmsVerifyCodeServiceImpl extends ServiceImpl<SmsVerifyCodeMapper, SmsVerifyCode> implements ISmsVerifyCodeService { public class SmsVerifyCodeServiceImpl extends ServiceImpl<SmsVerifyCodeMapper, SmsVerifyCode> implements ISmsVerifyCodeService {
private static final int CODE_VALID_MINUTES = 5; private static final int CODE_VALID_MINUTES = 5;
private static final Random RANDOM = new Random(); private static final Random RANDOM = new Random();
private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
@Resource @Resource
private SmsSender smsSender; private SmsSender smsSender;
@Resource
private SysUserMapper sysUserMapper;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public String sendVerifyCode(String phone, Integer type) { public String sendVerifyCode(String phone, Integer type) {
@ -124,13 +135,66 @@ public class SmsVerifyCodeServiceImpl extends ServiceImpl<SmsVerifyCodeMapper, S
@Override @Override
public void batchSendContent(List<String> phoneList, String content) { public void batchSendContent(List<String> phoneList, String content) {
for (String phone : phoneList) { // for (String phone : phoneList) {
//
// }
String phone = StrUtil.join(",", phoneList);
try { try {
smsSender.send(phone, content); smsSender.send(phone, content);
} catch (Exception e) { } catch (Exception e) {
log.debug("批量发送短信失败"+phone); log.debug("批量发送短信失败"+phone);
} }
}
} }
@Override
public int urgeByUserIds(List<String> userIds, String content) {
if (userIds == null || userIds.isEmpty()) {
log.warn("催促短信发送失败用户ID列表为空");
return 0;
}
List<String> ids = userIds.stream().distinct().toList();
List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getId, ids)
.eq(SysUser::getRegStatus, "APPROVED").eq(SysUser::getStatus,1).select(SysUser::getPhone));
if (sysUsers.isEmpty()) {
log.warn("催促短信发送失败未找到有效的手机号userIds: {}", ids);
return 0;
}
List<String> validPhones = sysUsers.stream().map(SysUser::getPhone).filter(this::isValidPhone).toList();
if (validPhones.isEmpty()) {
log.warn("催促短信发送失败:没有合规的手机号");
return 0;
}
int successCount = 0;
// for (String phone : validPhones) {
//
// }
String phone = StrUtil.join(",", validPhones);
try {
boolean sent = smsSender.send(phone, content);
if (sent) {
successCount++;
log.info("催促短信发送成功: {}", phone);
} else {
log.warn("催促短信发送失败: {}", phone);
}
} catch (Exception e) {
log.error("催促短信发送异常: {}", phone, e);
}
log.info("催促短信发送完成,总数: {}, 成功: {}", validPhones.size(), successCount);
return successCount;
}
private boolean isValidPhone(String phone) {
if (StrUtil.isBlank(phone)) {
return false;
}
return PHONE_PATTERN.matcher(phone).matches();
}
} }

View File

@ -16,6 +16,7 @@
<result column="MIN_STRDT" property="minStrdt"/> <result column="MIN_STRDT" property="minStrdt"/>
<result column="MAX_ENDDT" property="maxEnddt"/> <result column="MAX_ENDDT" property="maxEnddt"/>
<result column="TOTAL_FCNT" property="totalFcnt"/> <result column="TOTAL_FCNT" property="totalFcnt"/>
<result column="HAS_DATA" property="hasData"/>
</resultMap> </resultMap>
<sql id="statisticsQuery"> <sql id="statisticsQuery">
@ -146,7 +147,8 @@
fm.REPORT_MONTH, fm.REPORT_MONTH,
fm.MIN_STRDT, fm.MIN_STRDT,
fm.MAX_ENDDT, fm.MAX_ENDDT,
fm.TOTAL_FCNT fm.TOTAL_FCNT,
CASE WHEN fm.CREATED_BY IS NOT NULL THEN 1 ELSE 0 END AS HAS_DATA
FROM all_users u FROM all_users u
JOIN QGC_REFA.SYS_USER su JOIN QGC_REFA.SYS_USER su
ON u.USER_ID = su.ID ON u.USER_ID = su.ID