diff --git a/backend/src/main/java/com/yfd/platform/data/controller/FishDraftDataController.java b/backend/src/main/java/com/yfd/platform/data/controller/FishDraftDataController.java index d637aed..5a84a7c 100644 --- a/backend/src/main/java/com/yfd/platform/data/controller/FishDraftDataController.java +++ b/backend/src/main/java/com/yfd/platform/data/controller/FishDraftDataController.java @@ -46,7 +46,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; @@ -162,7 +161,6 @@ public class FishDraftDataController { @PostMapping("/batchSaveDraft") @Operation(summary = "批量保存草稿") - @Transactional(rollbackFor = Exception.class) public ResponseResult saveDraft(@RequestBody FishImportRowRequest request) { String taskId = request.getTaskId(); ImportTask importTask = importTaskService.getById(taskId); @@ -185,8 +183,8 @@ public class FishDraftDataController { data.setPicpthList(row.getPicpthList()); fishDraftDataList.add(data); } - boolean result = fishDraftDataService.saveBatch(fishDraftDataList); - fishImportService.processAttachmentsAsync(fishDraftDataList,importTask.getTempDir()); + boolean result = fishDraftDataService.batchSaveDraft(fishDraftDataList); + fishImportService.processAttachmentsAsync(fishDraftDataList, importTask.getTempDir()); importTaskService.markSuccess(taskId); return result ? ResponseResult.success("保存成功") : ResponseResult.error("保存失败"); } diff --git a/backend/src/main/java/com/yfd/platform/data/domain/vo/FishStatisticsVO.java b/backend/src/main/java/com/yfd/platform/data/domain/vo/FishStatisticsVO.java index 17d4572..369cbf9 100644 --- a/backend/src/main/java/com/yfd/platform/data/domain/vo/FishStatisticsVO.java +++ b/backend/src/main/java/com/yfd/platform/data/domain/vo/FishStatisticsVO.java @@ -33,4 +33,6 @@ public class FishStatisticsVO implements Serializable { private Date maxEnddt; private Integer totalFcnt; + + private Integer hasData; } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/service/IFishDraftDataService.java b/backend/src/main/java/com/yfd/platform/data/service/IFishDraftDataService.java index d3b2486..2504172 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/IFishDraftDataService.java +++ b/backend/src/main/java/com/yfd/platform/data/service/IFishDraftDataService.java @@ -96,4 +96,9 @@ public interface IFishDraftDataService extends IService { * 审批人修改数据并记录变更日志 */ boolean updateByIdWithLog(FishDraftData fishDraftData); + + /** + * 批量保存草稿(带事务,仅包裹 INSERT) + */ + boolean batchSaveDraft(List fishDraftDataList); } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/data/service/impl/FishDraftDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/data/service/impl/FishDraftDataServiceImpl.java index 8be4845..4fd0c39 100644 --- a/backend/src/main/java/com/yfd/platform/data/service/impl/FishDraftDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/data/service/impl/FishDraftDataServiceImpl.java @@ -657,5 +657,15 @@ public class FishDraftDataServiceImpl extends ServiceImpl 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; + } } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java b/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java index ea12096..e318367 100644 --- a/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java +++ b/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java @@ -21,6 +21,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -41,6 +42,7 @@ import java.util.stream.Collectors; @RestController @RequestMapping("/sms") @Tag(name = "短信验证码管理") +@Slf4j public class SmsVerifyCodeController { @Resource @@ -69,6 +71,7 @@ public class SmsVerifyCodeController { @Value("${rsa.private_key}") private String privateKey; + private static final String URGE_CONTENT ="根据生态环境部要求,请贵电站尽快完成过鱼数据的报送工作,感谢支持。"; /** * 发送验证码 @@ -125,10 +128,10 @@ public class SmsVerifyCodeController { /** - * 发送验证码 + * 批量发送短信 */ @PostMapping("/batchSendContent") - @Operation(summary = "发送验证码") + @Operation(summary = "批量发送短信") public ResponseResult batchSendContent(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) { List phoneList = smsVerifyCodeRequest.getPhoneList(); @@ -140,6 +143,35 @@ public class SmsVerifyCodeController { return ResponseResult.success(); } + /** + * 批量催促 + */ + @PostMapping("/batchUrgeContent") + @Operation(summary = "催促") + public ResponseResult batchUrgeContent(@RequestBody SmsVerifyCodeRequest smsVerifyCodeRequest) { + List 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 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()); + } + } + /** diff --git a/backend/src/main/java/com/yfd/platform/system/domain/SmsVerifyCodeRequest.java b/backend/src/main/java/com/yfd/platform/system/domain/SmsVerifyCodeRequest.java index 7a7bc9c..1b92d54 100644 --- a/backend/src/main/java/com/yfd/platform/system/domain/SmsVerifyCodeRequest.java +++ b/backend/src/main/java/com/yfd/platform/system/domain/SmsVerifyCodeRequest.java @@ -67,5 +67,10 @@ public class SmsVerifyCodeRequest { private String content; + /** + * 用户编号 + */ + private List userIds; + } diff --git a/backend/src/main/java/com/yfd/platform/system/service/ISmsVerifyCodeService.java b/backend/src/main/java/com/yfd/platform/system/service/ISmsVerifyCodeService.java index a674a47..909a6ae 100644 --- a/backend/src/main/java/com/yfd/platform/system/service/ISmsVerifyCodeService.java +++ b/backend/src/main/java/com/yfd/platform/system/service/ISmsVerifyCodeService.java @@ -50,4 +50,5 @@ public interface ISmsVerifyCodeService extends IService { boolean sendAuditNotify(String phone, String auditStatus, String reason); void batchSendContent(List phoneList, String content); + int urgeByUserIds(List userIds, String content); } \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/system/service/impl/SmsVerifyCodeServiceImpl.java b/backend/src/main/java/com/yfd/platform/system/service/impl/SmsVerifyCodeServiceImpl.java index 4a070ab..20f531d 100644 --- a/backend/src/main/java/com/yfd/platform/system/service/impl/SmsVerifyCodeServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/system/service/impl/SmsVerifyCodeServiceImpl.java @@ -1,18 +1,24 @@ 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.extension.service.impl.ServiceImpl; 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.SysUserMapper; import com.yfd.platform.system.service.ISmsVerifyCodeService; import com.yfd.platform.utils.SmsSender; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Date; import java.util.List; import java.util.Random; +import java.util.regex.Pattern; +import java.util.stream.Collectors; /** *

@@ -20,14 +26,19 @@ import java.util.Random; *

*/ @Service +@Slf4j public class SmsVerifyCodeServiceImpl extends ServiceImpl implements ISmsVerifyCodeService { private static final int CODE_VALID_MINUTES = 5; private static final Random RANDOM = new Random(); + private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$"); @Resource private SmsSender smsSender; + @Resource + private SysUserMapper sysUserMapper; + @Override @Transactional(rollbackFor = Exception.class) public String sendVerifyCode(String phone, Integer type) { @@ -124,13 +135,66 @@ public class SmsVerifyCodeServiceImpl extends ServiceImpl phoneList, String content) { - for (String phone : phoneList) { - try { - smsSender.send(phone, content); - } catch (Exception e) { - log.debug("批量发送短信失败"+phone); - } +// for (String phone : phoneList) { +// +// } + String phone = StrUtil.join(",", phoneList); + try { + smsSender.send(phone, content); + } catch (Exception e) { + log.debug("批量发送短信失败"+phone); } } + + + @Override + public int urgeByUserIds(List userIds, String content) { + if (userIds == null || userIds.isEmpty()) { + log.warn("催促短信发送失败:用户ID列表为空"); + return 0; + } + List ids = userIds.stream().distinct().toList(); + List sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper().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 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(); + } } \ No newline at end of file diff --git a/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml b/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml index a08d7de..d652a58 100644 --- a/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml +++ b/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml @@ -16,6 +16,7 @@ + @@ -146,7 +147,8 @@ fm.REPORT_MONTH, fm.MIN_STRDT, 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 JOIN QGC_REFA.SYS_USER su ON u.USER_ID = su.ID