232 预约管理-》门诊预约挂号:打开界面报错且无医生排班预约号源数据

This commit is contained in:
HuangXinQuan
2026-03-26 17:09:08 +08:00
parent 3f0fa3bbb3
commit 11cf88fd49
22 changed files with 1411 additions and 764 deletions

View File

@@ -0,0 +1,40 @@
package com.openhis.appointmentmanage.domain;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 预约挂号提交表单 (防篡改设计)
*/
@Data
public class AppointmentBookDTO implements Serializable {
@NotNull(message = "号源槽位ID不能为空")
private Long slotId;
// 兼容前端发来的旧字段,即使发了我们底层也不用,防报错接收
private Long ticketId;
private Long patientId;
@NotBlank(message = "患者姓名不能为空")
private String patientName;
@NotBlank(message = "就诊卡号不能为空")
private String medicalCard;
@NotBlank(message = "手机号不能为空")
private String phone;
private Integer gender;
// 前端传的 tenant_id我们为了兼容它带下划线的写法
private Integer tenant_id;
// 前端还会强行发这俩危险字段,我们只管接收堵口子,到了后端全丢弃不用
private BigDecimal fee;
private String regType;
}

View File

@@ -0,0 +1,15 @@
package com.openhis.appointmentmanage.domain;
import lombok.Data;
/**
* 医生余号汇总DTO按号源池聚合
*/
@Data
public class DoctorAvailabilityDTO {
private Long doctorId;
private String doctorName;
private Integer available;
private String ticketType;
}

View File

@@ -33,7 +33,7 @@ public class ScheduleSlot extends HisBaseEntity {
private Integer status;
/** 预约订单ID */
private Integer orderId;
private Long orderId;
/** 预计叫号时间 */
private LocalTime expectTime;

View File

@@ -0,0 +1,42 @@
package com.openhis.appointmentmanage.domain;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalTime;
/**
* 专门用于承接底层的号源池与具体槽位联查结果 (不对外暴露)
*/
@Data
public class TicketSlotDTO {
// 基础信息
private Long slotId;
private Long scheduleId;
private String doctor;
private Long doctorId;
private Long departmentId;
private String departmentName;
private String fee;
private String patientName;
private String medicalCard;
private Long patientId;
private String phone;
private Integer orderStatus;
// 底层逻辑判断专属字段
private Integer slotStatus;
private LocalTime expectTime;
private LocalDate scheduleDate;
private Integer regType;
private Integer poolStatus;
private String stopReason;
private Boolean isStopped;
public Boolean getIsStopped() {
return isStopped;
}
public void setIsStopped(Boolean isStopped) {
this.isStopped = isStopped;
}
}

View File

@@ -0,0 +1,43 @@
package com.openhis.appointmentmanage.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 门诊预约挂号查询条件 DTO
*/
@Data
public class TicketQueryDTO implements Serializable {
private static final long serialVersionUID = 1L;
// 看诊日期 (例如: 2026-03-25)
private String date;
// 号源状态 (unbooked, booked, checked, cancelled, all)
private String status;
// 号源类型 (general: 普通号, expert: 专家号)
private String type;
// 科室名称 (例如: 内科)
private String department;
// 医生ID
private Long doctorId;
// 患者姓名 (模糊搜索)
private String name;
// 就诊卡号 (模糊搜索)
private String card;
// 手机号 (模糊搜索)
private String phone;
// 当前页码 (默认第一页)
private Integer page = 1;
// 每页显示条数 (默认查20条)
private Integer limit = 20;
}

View File

@@ -2,8 +2,39 @@ package com.openhis.appointmentmanage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.openhis.appointmentmanage.domain.SchedulePool;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;
@Repository
public interface SchedulePoolMapper extends BaseMapper<SchedulePool> {
/**
* 按号源池实时重算统计值,避免并发场景下计数漂移。
*
* 说明available_num 在当前项目中可能为数据库生成列,因此这里仅维护
* booked_num / locked_num剩余号由数据库或查询逻辑计算。
*/
@Update("""
UPDATE adm_schedule_pool p
SET
booked_num = COALESCE((
SELECT COUNT(1)
FROM adm_schedule_slot s
WHERE s.pool_id = p.id
AND s.delete_flag = '0'
AND s.status = 1
), 0),
locked_num = COALESCE((
SELECT COUNT(1)
FROM adm_schedule_slot s
WHERE s.pool_id = p.id
AND s.delete_flag = '0'
AND s.status = 3
), 0),
update_time = now()
WHERE p.id = #{poolId}
AND p.delete_flag = '0'
""")
int refreshPoolStats(@Param("poolId") Long poolId);
}

View File

@@ -1,10 +1,53 @@
package com.openhis.appointmentmanage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.openhis.appointmentmanage.domain.DoctorAvailabilityDTO;
import com.openhis.appointmentmanage.domain.ScheduleSlot;
import com.openhis.appointmentmanage.domain.TicketSlotDTO;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.openhis.appointmentmanage.dto.TicketQueryDTO;
import java.util.List;
import org.springframework.stereotype.Repository;
import org.apache.ibatis.annotations.Param;
@Repository
public interface ScheduleSlotMapper extends BaseMapper<ScheduleSlot> {
//
// 多表查询排班信息展示来预约挂号
List<TicketSlotDTO> selectAllTicketSlots();
/**
* 根据槽位ID精确查出完整的聚合信息
*/
TicketSlotDTO selectTicketSlotById(@Param("id") Long id);
/**
* 原子抢占槽位:仅当当前状态=0(可用)时更新为1(已预约)。
*/
int lockSlotForBooking(@Param("slotId") Long slotId);
/**
* 按主键更新槽位状态。
*/
int updateSlotStatus(@Param("slotId") Long slotId, @Param("status") Integer status);
/**
* 根据槽位ID查询所属号源池ID。
*/
Long selectPoolIdBySlotId(@Param("slotId") Long slotId);
/**
* 预约成功后回填对应订单ID到号源槽位。
*/
int bindOrderToSlot(@Param("slotId") Long slotId, @Param("orderId") Long orderId);
/**
* 带分页和动态条件过滤的真实查询接口
*/
Page<TicketSlotDTO> selectTicketSlotsPage(Page<TicketSlotDTO> page, @Param("query") TicketQueryDTO query);
/**
* 按号源池聚合医生余号(不受分页影响)。
*/
List<DoctorAvailabilityDTO> selectDoctorAvailabilitySummary(@Param("query") TicketQueryDTO query);
}