Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"java.compile.nullAnalysis.mode": "automatic"
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@
import com.cl.annotation.SysLog;

import com.cl.entity.YishengyuyueEntity;
import com.cl.entity.YishengEntity;
import com.cl.entity.YonghuEntity;
import com.cl.entity.view.YishengyuyueView;

import com.cl.service.YishengyuyueService;
import com.cl.service.YishengService;
import com.cl.service.YonghuService;
import com.cl.service.SmsService;
import com.cl.service.TokenService;
import com.cl.utils.PageUtils;
import com.cl.utils.R;
Expand All @@ -48,6 +53,15 @@ public class YishengyuyueController {
@Autowired
private YishengyuyueService yishengyuyueService;

@Autowired
private YishengService yishengService;

@Autowired
private YonghuService yonghuService;

@Autowired
private SmsService smsService;




Expand Down Expand Up @@ -159,7 +173,19 @@ public R save(@RequestBody YishengyuyueEntity yishengyuyue, HttpServletRequest r
@RequestMapping("/add")
public R add(@RequestBody YishengyuyueEntity yishengyuyue, HttpServletRequest request){
//ValidatorUtils.validateEntity(yishengyuyue);

// 校验用户手机号码
if (yishengyuyue.getShouji() != null && !yishengyuyue.getShouji().trim().isEmpty()) {
if (!smsService.isValidPhoneNumber(yishengyuyue.getShouji())) {
return R.error("用户手机号码格式不正确");
}
}

yishengyuyueService.insert(yishengyuyue);

// 预约成功后发送短信通知医生
sendSmsToDoctor(yishengyuyue);

return R.ok();
}

Expand Down Expand Up @@ -190,13 +216,121 @@ public R update(@RequestBody Long[] ids, @RequestParam String sfsh, @RequestPara
yishengyuyue.setSfsh(sfsh);
yishengyuyue.setShhf(shhf);
list.add(yishengyuyue);

// 审核通过后发送短信通知用户
if ("是".equals(sfsh)) {
sendSmsToUser(yishengyuyue);
}
}
yishengyuyueService.updateBatchById(list);
return R.ok();
}

/**
* 发送短信通知医生
* @param yishengyuyue 预约信息
*/
private void sendSmsToDoctor(YishengyuyueEntity yishengyuyue) {
try {
// 获取医生信息
String yishengzhanghao = yishengyuyue.getYishengzhanghao();
if (yishengzhanghao == null || yishengzhanghao.trim().isEmpty()) {
return;
}


YishengEntity yisheng = yishengService.selectOne(
new EntityWrapper<YishengEntity>().eq("yishengzhanghao", yishengzhanghao)
);

if (yisheng == null) {
return;
}

// 校验医生手机号码
String doctorPhone = yisheng.getDianhua();
if (doctorPhone == null || doctorPhone.trim().isEmpty()) {
return;
}

if (!smsService.isValidPhoneNumber(doctorPhone)) {
return;
}

// 构建短信内容
String message = String.format(
"【医疗预约系统】您好,%s医生,用户%s预约了您的诊疗服务,预约时间:%s,请登录系统查看详情。",
yisheng.getYishengxingming() != null ? yisheng.getYishengxingming() : yishengzhanghao,
yishengyuyue.getZhanghao() != null ? yishengyuyue.getZhanghao() : "未知用户",
yishengyuyue.getYuyueshijian() != null ?
new SimpleDateFormat("yyyy-MM-dd HH:mm").format(yishengyuyue.getYuyueshijian()) : "待定"
);

// 发送短信(带重试机制,最多重试2次)
smsService.sendSmsWithRetry(doctorPhone, message, 2);

} catch (Exception e) {
// 短信发送失败不影响主业务流程
}
}

/**
* 发送短信通知用户
* @param yishengyuyue 预约信息
*/
private void sendSmsToUser(YishengyuyueEntity yishengyuyue) {
try {
// 获取用户信息
String zhanghao = yishengyuyue.getZhanghao();
if (zhanghao == null || zhanghao.trim().isEmpty()) {
return;
}

YonghuEntity yonghu = yonghuService.selectOne(
new EntityWrapper<YonghuEntity>().eq("zhanghao", zhanghao)
);

if (yonghu == null) {
return;
}

// 校验用户手机号码
String userPhone = yonghu.getShouji();
if (userPhone == null || userPhone.trim().isEmpty()) {
return;
}

if (!smsService.isValidPhoneNumber(userPhone)) {
return;
}

// 获取医生信息
String yishengzhanghao = yishengyuyue.getYishengzhanghao();
String yishengName = yishengzhanghao;
if (yishengzhanghao != null && !yishengzhanghao.trim().isEmpty()) {
YishengEntity yisheng = yishengService.selectOne(
new EntityWrapper<YishengEntity>().eq("yishengzhanghao", yishengzhanghao)
);
if (yisheng != null && yisheng.getYishengxingming() != null) {
yishengName = yisheng.getYishengxingming();
}
}

// 构建短信内容
String message = String.format(
"【医疗预约系统】您好,%s,您的预约申请已被%s医生审核通过,预约时间:%s,请按时就诊。",
yonghu.getXingming() != null ? yonghu.getXingming() : zhanghao,
yishengName,
yishengyuyue.getYuyueshijian() != null ?
new SimpleDateFormat("yyyy-MM-dd HH:mm").format(yishengyuyue.getYuyueshijian()) : "待定"
);

// 发送短信(带重试机制,最多重试2次)
smsService.sendSmsWithRetry(userPhone, message, 2);

} catch (Exception e) {
// 短信发送失败不影响主业务流程
}
}

/**
* 删除
Expand Down
34 changes: 34 additions & 0 deletions server_code/src/main/java/com/cl/service/SmsService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.cl.service;

/**
* 短信服务接口
* @author
* @email
* @date 2025-03-27 15:44:15
*/
public interface SmsService {

/**
* 发送短信
* @param phoneNumber 手机号码
* @param message 短信内容
* @return 是否发送成功
*/
boolean sendSms(String phoneNumber, String message);

/**
* 发送短信(带重试机制)
* @param phoneNumber 手机号码
* @param message 短信内容
* @param maxRetries 最大重试次数
* @return 是否发送成功
*/
boolean sendSmsWithRetry(String phoneNumber, String message, int maxRetries);

/**
* 验证手机号码格式
* @param phoneNumber 手机号码
* @return 是否有效
*/
boolean isValidPhoneNumber(String phoneNumber);
}
143 changes: 143 additions & 0 deletions server_code/src/main/java/com/cl/service/impl/SmsServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package com.cl.service.impl;

import com.cl.service.SmsService;
import com.cl.service.SyslogService;
import com.cl.entity.SyslogEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.regex.Pattern;

/**
* 短信服务实现类
* @author
* @email
* @date 2025-03-27 15:44:15
*/
@Service("smsService")
public class SmsServiceImpl implements SmsService {

private static final Logger logger = LoggerFactory.getLogger(SmsServiceImpl.class);

private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");

private static final int DEFAULT_MAX_RETRIES = 2;

@Autowired
private SyslogService syslogService;

@Override
public boolean sendSms(String phoneNumber, String message) {
if (!isValidPhoneNumber(phoneNumber)) {
logger.error("手机号码格式不正确: {}", phoneNumber);
saveSmsLog(phoneNumber, message, "发送失败:手机号码格式不正确", 0);
return false;
}

try {
boolean success = doSendSms(phoneNumber, message);
if (success) {
saveSmsLog(phoneNumber, message, "发送成功", 100);
logger.info("短信发送成功,手机号: {}", phoneNumber);
} else {
saveSmsLog(phoneNumber, message, "发送失败", 0);
logger.error("短信发送失败,手机号: {}", phoneNumber);
}
return success;
} catch (Exception e) {
saveSmsLog(phoneNumber, message, "发送异常:" + e.getMessage(), 0);
logger.error("短信发送异常,手机号: {},错误: {}", phoneNumber, e.getMessage());
return false;
}
}

@Override
public boolean sendSmsWithRetry(String phoneNumber, String message, int maxRetries) {
if (!isValidPhoneNumber(phoneNumber)) {
logger.error("手机号码格式不正确: {}", phoneNumber);
saveSmsLog(phoneNumber, message, "发送失败:手机号码格式不正确", 0);
return false;
}

int attempt = 0;
boolean success = false;
String lastError = "";

while (attempt <= maxRetries && !success) {
attempt++;
try {
success = doSendSms(phoneNumber, message);
if (success) {
saveSmsLog(phoneNumber, message, "发送成功,第" + attempt + "次尝试", 100);
logger.info("短信发送成功,手机号: {},第{}次尝试", phoneNumber, attempt);
return true;
} else {
lastError = "发送失败";
logger.warn("短信发送失败,手机号: {},第{}次尝试", phoneNumber, attempt);
if (attempt <= maxRetries) {
Thread.sleep(1000);
}
}
} catch (Exception e) {
lastError = e.getMessage();
logger.error("短信发送异常,手机号: {},第{}次尝试,错误: {}", phoneNumber, attempt, e.getMessage());
if (attempt <= maxRetries) {
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
}

saveSmsLog(phoneNumber, message, "发送失败,已重试" + maxRetries + "次,最后错误:" + lastError, 0);
logger.error("短信发送最终失败,手机号: {},已重试{}次", phoneNumber, maxRetries);
return false;
}

@Override
public boolean isValidPhoneNumber(String phoneNumber) {
if (phoneNumber == null || phoneNumber.trim().isEmpty()) {
return false;
}
return PHONE_PATTERN.matcher(phoneNumber.trim()).matches();
}

/**
* 实际发送短信的模拟实现
* @param phoneNumber 手机号码
* @param message 短信内容
* @return 是否发送成功
*/
private boolean doSendSms(String phoneNumber, String message) {
logger.info("【模拟短信发送】手机号: {},内容: {}", phoneNumber, message);
return true;
}

/**
* 保存短信发送日志到syslog表
* @param phoneNumber 手机号码
* @param message 短信内容
* @param result 发送结果
* @param time 耗时
*/
private void saveSmsLog(String phoneNumber, String message, String result, long time) {
try {
SyslogEntity syslog = new SyslogEntity();
syslog.setUsername("SMS_SERVICE");
syslog.setOperation("短信发送");
syslog.setMethod("SmsService.sendSms");
syslog.setParams("手机号: " + phoneNumber + ", 内容: " + message + ", 结果: " + result);
syslog.setTime(time);
syslog.setIp("127.0.0.1");
syslog.setAddtime(new Date());
syslogService.insert(syslog);
} catch (Exception e) {
logger.error("保存短信日志失败: {}", e.getMessage());
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading