修改体检接口,新增字段,及修复部分bug

This commit is contained in:
sangchengzhi
2026-01-14 17:15:54 +08:00
parent 7e61946025
commit bc92cfb31f
9 changed files with 155 additions and 27 deletions

View File

@@ -15,7 +15,7 @@ import tk.mybatis.spring.annotation.MapperScan;
@EnableAspectJAutoProxy(proxyTargetClass = true) @EnableAspectJAutoProxy(proxyTargetClass = true)
@SpringBootApplication(scanBasePackages = "com") @SpringBootApplication(scanBasePackages = "com")
@MapperScan(basePackages = {"com.guahao.*.mapper"}) @MapperScan(basePackages = {"com.guahao.*.mapper"})
@ServletComponentScan(basePackages = {"com.guahao.common.filter"}) @ServletComponentScan(basePackages = {"com.guahao.common.filter", "com.guahao.common.listener"})
@ComponentScan(basePackages = {"com.guahao"}) @ComponentScan(basePackages = {"com.guahao"})
@EnableScheduling @EnableScheduling
public class GuahaoApplication extends SpringBootServletInitializer { public class GuahaoApplication extends SpringBootServletInitializer {

View File

@@ -1,6 +1,6 @@
package com.guahao.api.task.mapper; package com.guahao.api.task.mapper;
import com.guahao.api.task.model.UserMzjf;
import com.guahao.api.task.model.UserReserve8; import com.guahao.api.task.model.UserReserve8;
import com.guahao.common.base.BaseMapper; import com.guahao.common.base.BaseMapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;

View File

@@ -0,0 +1,101 @@
package com.guahao.common.listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.stereotype.Component;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.lang.reflect.Method;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* MySQL连接清理监听器用于在应用关闭时正确清理MySQL连接
*/
@Component
@WebListener
public class MysqlCleanupListener implements ServletContextListener, ApplicationListener<ContextClosedEvent> {
private static final Logger logger = LoggerFactory.getLogger(MysqlCleanupListener.class);
@Override
public void contextInitialized(ServletContextEvent sce) {
// 应用启动时无需特殊处理
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
cleanup();
}
@Override
public void onApplicationEvent(ContextClosedEvent event) {
cleanup();
}
/**
* 清理MySQL连接和相关资源
*/
private void cleanup() {
try {
// 注销驱动程序,防止内存泄漏
deregisterJdbcDrivers();
// 尝试停止MySQL的AbandonedConnectionCleanupThread
stopMySqlAbandonedConnectionCleanupThread();
logger.info("MySQL连接及相关资源清理完成");
} catch (Exception e) {
logger.error("清理MySQL连接资源时发生错误", e);
}
}
/**
* 注销JDBC驱动程序
*/
private void deregisterJdbcDrivers() {
try {
DriverManager.getDrivers();
java.sql.Driver driver;
while (DriverManager.getDrivers().hasMoreElements()) {
driver = DriverManager.getDrivers().nextElement();
if (driver.getClass().getName().startsWith("com.mysql")) {
DriverManager.deregisterDriver(driver);
logger.info("已注销MySQL驱动: {}", driver.getClass().getName());
}
}
} catch (SQLException e) {
logger.error("注销JDBC驱动时发生错误", e);
}
}
/**
* 停止MySQL的AbandonedConnectionCleanupThread线程
*/
private void stopMySqlAbandonedConnectionCleanupThread() {
try {
Class<?> clazz;
try {
clazz = Class.forName("com.mysql.jdbc.AbandonedConnectionCleanupThread");
} catch (ClassNotFoundException e) {
// 对于MySQL 8.0+版本,类名可能不同
try {
clazz = Class.forName("com.mysql.cj.jdbc.AbandonedConnectionCleanupThread");
} catch (ClassNotFoundException ex) {
logger.debug("未找到MySQL连接清理线程类可能使用的是不同版本的驱动");
return;
}
}
Method shutdownMethod = clazz.getMethod("shutdown");
shutdownMethod.invoke(null);
logger.info("已停止MySQL AbandonedConnectionCleanupThread线程");
} catch (Exception e) {
logger.warn("停止MySQL连接清理线程时发生错误", e);
}
}
}

View File

@@ -702,17 +702,20 @@ public class XmlUtil {
str.append(vo.getPaynature()); str.append(vo.getPaynature());
str.append("</PayNature>"); str.append("</PayNature>");
// 当vo.getYbzhamount和ybtcamount都是0的时候且zfamount>=0则此处用微信其他情况用医保 // 当vo.getYbzhamount和ybtcamount都是0的时候且zfamount>=0则此处用微信其他情况用医保
if ((vo.getYbzhamount() == null || vo.getYbzhamount().compareTo(BigDecimal.valueOf(0.00)) == 0) && // if ((vo.getYbzhamount() == null || vo.getYbzhamount().compareTo(BigDecimal.valueOf(0.00)) == 0) &&
(vo.getYbtcamount() == null || vo.getYbtcamount().compareTo(BigDecimal.valueOf(0.00)) == 0) && // (vo.getYbtcamount() == null || vo.getYbtcamount().compareTo(BigDecimal.valueOf(0.00)) == 0) &&
vo.getZfamount().compareTo(BigDecimal.valueOf(0.00)) >= 0) { // vo.getZfamount().compareTo(BigDecimal.valueOf(0.00)) >= 0) {
// str.append("<PayType>");
// str.append("微信");
// str.append("</PayType>");
// } else {
// str.append("<PayType>");
// str.append("医保");
// str.append("</PayType>");
// }
str.append("<PayType>"); str.append("<PayType>");
str.append("微信"); str.append("微信");
str.append("</PayType>"); str.append("</PayType>");
} else {
str.append("<PayType>");
str.append("医保");
str.append("</PayType>");
}
str.append("<PowerTranID>"); str.append("<PowerTranID>");
str.append(vo.getPowertranid()); str.append(vo.getPowertranid());
str.append("</PowerTranID>"); str.append("</PowerTranID>");

View File

@@ -290,11 +290,11 @@ public class HsjcController {
*/ */
@RequestMapping("/opTiQuery") @RequestMapping("/opTiQuery")
@WebLog(description = "opTiQuery",logResponse = false) @WebLog(description = "opTiQuery",logResponse = false)
public Object opTiQuery(Integer userId, String token,String HospitalZone ,String startDate, String endDate) { public Object opTiQuery(Integer userId, String token,String HospitalZone ,String startDate, String endDate,String Type) {
try { try {
int retToken = getUserToken(userId, token); int retToken = getUserToken(userId, token);
if (retToken != 0) { if (retToken != 0) {
Map<String, Object> stringObjectMap = hsjcService.opTiQuery(HospitalZone, startDate, endDate); Map<String, Object> stringObjectMap = hsjcService.opTiQuery(HospitalZone, startDate, endDate,Type);
// log.info("后端返回数据为:"+stringObjectMap); // log.info("后端返回数据为:"+stringObjectMap);
return ResponseResult.success(stringObjectMap); return ResponseResult.success(stringObjectMap);
} else { } else {
@@ -309,11 +309,11 @@ public class HsjcController {
*/ */
@RequestMapping("/getDetail") @RequestMapping("/getDetail")
@WebLog(description = "getDetail") @WebLog(description = "getDetail")
public Object getDetail(Integer userId, String token, String programId,String bookindDate) { public Object getDetail(Integer userId, String token, String programId,String bookindDate,String Type) {
try { try {
int retToken = getUserToken(userId, token); int retToken = getUserToken(userId, token);
if (retToken != 0) { if (retToken != 0) {
Map<String, Object> stringObjectMap = hsjcService.getDetail(programId,bookindDate); Map<String, Object> stringObjectMap = hsjcService.getDetail(programId,bookindDate,Type);
// log.info("后端返回数据为:"+stringObjectMap); // log.info("后端返回数据为:"+stringObjectMap);
return ResponseResult.success(stringObjectMap); return ResponseResult.success(stringObjectMap);
} else { } else {

View File

@@ -151,7 +151,7 @@ public class HsjcService {
return resSuc; return resSuc;
} }
public Map<String, Object> opTiQuery(String hospitalZone, String startDate, String endDate) { public Map<String, Object> opTiQuery(String hospitalZone, String startDate, String endDate,String type) {
Map<String, Object> result = new HashMap<>(); Map<String, Object> result = new HashMap<>();
List<Map<String, Object>> dataList = new ArrayList<>(); List<Map<String, Object>> dataList = new ArrayList<>();
@@ -166,6 +166,9 @@ public class HsjcService {
str.append("&lt;EndDate&gt;"); str.append("&lt;EndDate&gt;");
str.append(endDate); str.append(endDate);
str.append("&lt;/EndDate&gt;"); str.append("&lt;/EndDate&gt;");
str.append("&lt;class&gt;");
str.append(type);
str.append("&lt;/class&gt;");
String respXml = SoapUtil.soapMethod4(str.toString(),"mop_canreservationphysicalprogram"); String respXml = SoapUtil.soapMethod4(str.toString(),"mop_canreservationphysicalprogram");
// log.debug("【原始SOAP响应】:\n{}", respXml); // log.debug("【原始SOAP响应】:\n{}", respXml);
@@ -240,7 +243,7 @@ public class HsjcService {
return ""; return "";
} }
public Map<String, Object> getDetail(String programId, String bookindDate) { public Map<String, Object> getDetail(String programId, String bookindDate,String Type) {
try { try {
StringBuffer str = new StringBuffer(); StringBuffer str = new StringBuffer();
str.append("&lt;program_id&gt;"); str.append("&lt;program_id&gt;");
@@ -249,6 +252,9 @@ public class HsjcService {
str.append("&lt;booking_date&gt;"); str.append("&lt;booking_date&gt;");
str.append(bookindDate); str.append(bookindDate);
str.append("&lt;/booking_date&gt;"); str.append("&lt;/booking_date&gt;");
str.append("&lt;class&gt;");
str.append(Type);
str.append("&lt;/class&gt;");
String respXml = SoapUtil.soapMethod4(str.toString(),"mop_queryphysicalprogramdetail"); String respXml = SoapUtil.soapMethod4(str.toString(),"mop_queryphysicalprogramdetail");
@@ -297,6 +303,7 @@ public class HsjcService {
str.append("&lt;program_id&gt;").append(programId).append("&lt;/program_id&gt;"); str.append("&lt;program_id&gt;").append(programId).append("&lt;/program_id&gt;");
str.append("&lt;time_period&gt;").append(detail.getTimePeriod()).append("&lt;/time_period&gt;"); str.append("&lt;time_period&gt;").append(detail.getTimePeriod()).append("&lt;/time_period&gt;");
str.append("&lt;time&gt;").append(detail.getTime()).append("&lt;/time&gt;"); str.append("&lt;time&gt;").append(detail.getTime()).append("&lt;/time&gt;");
str.append("&lt;class&gt;").append(detail.getType()).append("&lt;/class&gt;");
str.append("&lt;/program&gt;"); str.append("&lt;/program&gt;");
// 拼接到本地存储的字符串101,102,103 // 拼接到本地存储的字符串101,102,103

View File

@@ -5,9 +5,19 @@ public class ProgramDetailVO {
private String programId; // 项目ID字符串或 Long根据实际类型 private String programId; // 项目ID字符串或 Long根据实际类型
private String time; // 具体时间段,如 "8:00-12:00" private String time; // 具体时间段,如 "8:00-12:00"
private String timePeriod; // 时段AM / PM private String timePeriod; // 时段AM / PM
private String type; // 项目类型1 套餐/ 2 单项
// ======= Getters and Setters ======= // ======= Getters and Setters =======
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getProgramId() { public String getProgramId() {
return programId; return programId;
} }

View File

@@ -131,8 +131,11 @@ public class YbServiceImpl implements YbService {
return t; return t;
}); });
// 用于跟踪正在执行延时任务的订单,防止重复执行 // 用于跟踪正在执行findStatus延时任务的订单,防止重复执行
private static final Set<String> pendingDelayedTasks = ConcurrentHashMap.newKeySet(); private static final Set<String> pendingFindStatusTasks = ConcurrentHashMap.newKeySet();
// 用于跟踪正在执行关闭未支付订单延时任务的订单,防止重复执行
private static final Set<String> pendingCloseOrderTasks = ConcurrentHashMap.newKeySet();
@Autowired @Autowired
private WxPayConfig wxPayConfig; private WxPayConfig wxPayConfig;
@@ -1024,7 +1027,7 @@ public class YbServiceImpl implements YbService {
// 启动15分钟后检查订单状态的延时任务 // 启动15分钟后检查订单状态的延时任务
String finalHospOutTradeNo = req.getHosp_out_trade_no(); String finalHospOutTradeNo = req.getHosp_out_trade_no();
// 使用防重复机制提交延时任务 // 使用防重复机制提交延时任务
if (pendingDelayedTasks.add(finalHospOutTradeNo)) { if (pendingCloseOrderTasks.add(finalHospOutTradeNo)) {
scheduledExecutor.schedule(() -> { scheduledExecutor.schedule(() -> {
try { try {
// 检查订单状态是否仍为2未支付 // 检查订单状态是否仍为2未支付
@@ -1040,12 +1043,12 @@ public class YbServiceImpl implements YbService {
log.error("检查订单状态异常", e); log.error("检查订单状态异常", e);
} finally { } finally {
// 确保无论成功或失败都从待处理集合中移除 // 确保无论成功或失败都从待处理集合中移除
pendingDelayedTasks.remove(finalHospOutTradeNo); pendingCloseOrderTasks.remove(finalHospOutTradeNo);
} }
}, 15, TimeUnit.MINUTES); // 15分钟后执行 }, 15, TimeUnit.MINUTES); // 15分钟后执行
log.info("已为订单 {} 安排15分钟后检查状态", req.getHosp_out_trade_no()); log.info("已为订单 {} 安排15分钟后检查状态", req.getHosp_out_trade_no());
} else { } else {
log.info("订单 {} 已存在待执行的延时任务,跳过重复提交", req.getHosp_out_trade_no()); log.info("订单 {} 已存在待执行的关闭订单延时任务,跳过重复提交", req.getHosp_out_trade_no());
} }
resMap.put("appid", xml.get("appid")); resMap.put("appid", xml.get("appid"));
@@ -1708,7 +1711,7 @@ public class YbServiceImpl implements YbService {
// 使用独立调度线程池异步延时执行findStatus方法等待系统状态同步 // 使用独立调度线程池异步延时执行findStatus方法等待系统状态同步
String hospOutTradeNo = wxResult.getHosp_out_trade_no(); String hospOutTradeNo = wxResult.getHosp_out_trade_no();
// 使用防重复机制提交延时任务 // 使用防重复机制提交延时任务
if (pendingDelayedTasks.add(hospOutTradeNo)) { if (pendingFindStatusTasks.add(hospOutTradeNo)) {
scheduledExecutor.schedule(() -> { scheduledExecutor.schedule(() -> {
try { try {
log.info("用户退出流程启用延时执行findStatus方法写入His"); log.info("用户退出流程启用延时执行findStatus方法写入His");
@@ -1717,11 +1720,11 @@ public class YbServiceImpl implements YbService {
log.error("延时执行findStatus异常", e); log.error("延时执行findStatus异常", e);
} finally { } finally {
// 确保无论成功或失败都从待处理集合中移除 // 确保无论成功或失败都从待处理集合中移除
pendingDelayedTasks.remove(hospOutTradeNo); pendingFindStatusTasks.remove(hospOutTradeNo);
} }
}, 10, TimeUnit.SECONDS); }, 10, TimeUnit.SECONDS);
} else { } else {
log.info("订单 {} 已存在待执行的延时任务,跳过重复提交", hospOutTradeNo); log.info("订单 {} 已存在待执行的findStatus延时任务,跳过重复提交", hospOutTradeNo);
} }
} }
} else { } else {

View File

@@ -37,6 +37,10 @@ druid.testOnReturn=false
druid.poolPreparedStatements=true druid.poolPreparedStatements=true
druid.maxPoolPreparedStatementPerConnectionSize=20 druid.maxPoolPreparedStatementPerConnectionSize=20
druid.filters=stat druid.filters=stat
# 连接泄露检测配置
druid.removeAbandoned=true
druid.removeAbandonedTimeout=1800
druid.logAbandoned=true
#数据库连接信息 #数据库连接信息
#spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driver #spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/guahao?zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai #spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/guahao?zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai