会诊管理中 门诊会诊申请确认和门诊会诊申请管理模块全部功能的实现。包括数据库设计,前端UI设计,后端接口开发。
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
package com.openhis.web.consultation.appservice;
|
package com.openhis.web.consultation.appservice;
|
||||||
|
|
||||||
import com.openhis.web.consultation.dto.ConsultationActivityDto;
|
import com.openhis.web.consultation.dto.*;
|
||||||
import com.openhis.web.consultation.dto.ConsultationRequestDto;
|
|
||||||
import com.openhis.web.consultation.dto.DepartmentTreeDto;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -23,6 +21,24 @@ public interface IConsultationAppService {
|
|||||||
*/
|
*/
|
||||||
List<ConsultationRequestDto> getConsultationList(Long encounterId);
|
List<ConsultationRequestDto> getConsultationList(Long encounterId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会诊申请列表(支持多条件查询)
|
||||||
|
*
|
||||||
|
* @param dto 查询条件DTO
|
||||||
|
* @return 会诊列表
|
||||||
|
*/
|
||||||
|
List<ConsultationRequestDto> queryConsultationList(ConsultationRequestDto dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询会诊申请列表(支持多条件查询)
|
||||||
|
*
|
||||||
|
* @param dto 查询条件DTO
|
||||||
|
* @param pageNum 页码
|
||||||
|
* @param pageSize 每页大小
|
||||||
|
* @return 分页结果
|
||||||
|
*/
|
||||||
|
com.baomidou.mybatisplus.extension.plugins.pagination.Page<ConsultationRequestDto> queryConsultationListPage(ConsultationRequestDto dto, Integer pageNum, Integer pageSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存会诊申请
|
* 保存会诊申请
|
||||||
*
|
*
|
||||||
@@ -84,6 +100,55 @@ public interface IConsultationAppService {
|
|||||||
* @return 会诊项目列表
|
* @return 会诊项目列表
|
||||||
*/
|
*/
|
||||||
List<ConsultationActivityDto> getConsultationActivities();
|
List<ConsultationActivityDto> getConsultationActivities();
|
||||||
|
|
||||||
|
// ==================== 会诊确认相关接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待确认的会诊列表(当前医生被邀请的会诊)
|
||||||
|
*
|
||||||
|
* @return 待确认的会诊列表
|
||||||
|
*/
|
||||||
|
List<ConsultationConfirmationDto> getPendingConfirmationList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认会诊
|
||||||
|
*
|
||||||
|
* @param dto 会诊确认DTO
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
Boolean confirmConsultation(ConsultationConfirmationDto dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消确认会诊
|
||||||
|
*
|
||||||
|
* @param consultationId 会诊申请单号
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
Boolean cancelConfirmation(String consultationId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名会诊
|
||||||
|
*
|
||||||
|
* @param consultationId 会诊申请单号
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
Boolean signConsultation(String consultationId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊确认详情
|
||||||
|
*
|
||||||
|
* @param consultationId 会诊申请单号
|
||||||
|
* @return 会诊确认详情
|
||||||
|
*/
|
||||||
|
ConsultationConfirmationDto getConfirmationDetail(String consultationId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊意见列表
|
||||||
|
*
|
||||||
|
* @param consultationId 会诊申请单号
|
||||||
|
* @return 会诊意见列表
|
||||||
|
*/
|
||||||
|
List<ConsultationOpinionDto> getConsultationOpinions(String consultationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,8 @@ package com.openhis.web.consultation.controller;
|
|||||||
import com.core.common.core.domain.R;
|
import com.core.common.core.domain.R;
|
||||||
import com.openhis.web.consultation.appservice.IConsultationAppService;
|
import com.openhis.web.consultation.appservice.IConsultationAppService;
|
||||||
import com.openhis.web.consultation.dto.ConsultationActivityDto;
|
import com.openhis.web.consultation.dto.ConsultationActivityDto;
|
||||||
|
import com.openhis.web.consultation.dto.ConsultationConfirmationDto;
|
||||||
|
import com.openhis.web.consultation.dto.ConsultationOpinionDto;
|
||||||
import com.openhis.web.consultation.dto.ConsultationRequestDto;
|
import com.openhis.web.consultation.dto.ConsultationRequestDto;
|
||||||
import com.openhis.web.consultation.dto.DepartmentTreeDto;
|
import com.openhis.web.consultation.dto.DepartmentTreeDto;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
@@ -49,6 +51,41 @@ public class ConsultationController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会诊申请列表(支持多条件查询)
|
||||||
|
*/
|
||||||
|
@ApiOperation("查询会诊申请列表")
|
||||||
|
@PostMapping("/query")
|
||||||
|
public R<List<ConsultationRequestDto>> queryConsultationList(@RequestBody ConsultationRequestDto dto) {
|
||||||
|
try {
|
||||||
|
List<ConsultationRequestDto> list = consultationAppService.queryConsultationList(dto);
|
||||||
|
return R.ok(list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询会诊申请列表失败", e);
|
||||||
|
return R.fail("查询会诊申请列表失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询会诊申请列表(支持多条件查询)
|
||||||
|
*/
|
||||||
|
@ApiOperation("分页查询会诊申请列表")
|
||||||
|
@PostMapping("/queryPage")
|
||||||
|
public R<com.baomidou.mybatisplus.extension.plugins.pagination.Page<ConsultationRequestDto>> queryConsultationListPage(
|
||||||
|
@RequestBody ConsultationRequestDto dto,
|
||||||
|
@ApiParam("页码") @RequestParam(required = false, defaultValue = "1") Integer pageNum,
|
||||||
|
@ApiParam("每页大小") @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
|
||||||
|
try {
|
||||||
|
log.info("分页查询会诊申请列表,pageNum: {}, pageSize: {}", pageNum, pageSize);
|
||||||
|
com.baomidou.mybatisplus.extension.plugins.pagination.Page<ConsultationRequestDto> page =
|
||||||
|
consultationAppService.queryConsultationListPage(dto, pageNum, pageSize);
|
||||||
|
return R.ok(page);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("分页查询会诊申请列表失败", e);
|
||||||
|
return R.fail("分页查询会诊申请列表失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存会诊申请
|
* 保存会诊申请
|
||||||
*/
|
*/
|
||||||
@@ -173,5 +210,99 @@ public class ConsultationController {
|
|||||||
return R.fail("获取会诊项目列表失败: " + e.getMessage());
|
return R.fail("获取会诊项目列表失败: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 会诊确认相关接口 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待确认的会诊列表(当前医生被邀请的会诊)
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取待确认的会诊列表")
|
||||||
|
@GetMapping("/confirmation/pending")
|
||||||
|
public R<List<ConsultationConfirmationDto>> getPendingConfirmationList() {
|
||||||
|
try {
|
||||||
|
List<ConsultationConfirmationDto> list = consultationAppService.getPendingConfirmationList();
|
||||||
|
return R.ok(list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取待确认会诊列表失败", e);
|
||||||
|
return R.fail("获取待确认会诊列表失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认会诊
|
||||||
|
*/
|
||||||
|
@ApiOperation("确认会诊")
|
||||||
|
@PostMapping("/confirmation/confirm")
|
||||||
|
public R<String> confirmConsultation(@RequestBody ConsultationConfirmationDto dto) {
|
||||||
|
try {
|
||||||
|
Boolean result = consultationAppService.confirmConsultation(dto);
|
||||||
|
return result ? R.ok("确认成功") : R.fail("确认失败");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("确认会诊失败", e);
|
||||||
|
return R.fail("确认会诊失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消确认会诊
|
||||||
|
*/
|
||||||
|
@ApiOperation("取消确认会诊")
|
||||||
|
@PostMapping("/confirmation/cancelConfirm")
|
||||||
|
public R<String> cancelConfirmation(@ApiParam("会诊申请单号") @RequestParam String consultationId) {
|
||||||
|
try {
|
||||||
|
Boolean result = consultationAppService.cancelConfirmation(consultationId);
|
||||||
|
return result ? R.ok("取消确认成功") : R.fail("取消确认失败");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("取消确认会诊失败", e);
|
||||||
|
return R.fail("取消确认会诊失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名会诊
|
||||||
|
*/
|
||||||
|
@ApiOperation("签名会诊")
|
||||||
|
@PostMapping("/confirmation/sign")
|
||||||
|
public R<String> signConsultation(@ApiParam("会诊申请单号") @RequestParam String consultationId) {
|
||||||
|
try {
|
||||||
|
Boolean result = consultationAppService.signConsultation(consultationId);
|
||||||
|
return result ? R.ok("签名成功") : R.fail("签名失败");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("签名会诊失败", e);
|
||||||
|
return R.fail("签名会诊失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊确认详情
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取会诊确认详情")
|
||||||
|
@GetMapping("/confirmation/detail")
|
||||||
|
public R<ConsultationConfirmationDto> getConfirmationDetail(
|
||||||
|
@ApiParam("会诊申请单号") @RequestParam String consultationId) {
|
||||||
|
try {
|
||||||
|
ConsultationConfirmationDto detail = consultationAppService.getConfirmationDetail(consultationId);
|
||||||
|
return R.ok(detail);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取会诊确认详情失败", e);
|
||||||
|
return R.fail("获取会诊确认详情失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊意见列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取会诊意见列表")
|
||||||
|
@GetMapping("/confirmation/opinions")
|
||||||
|
public R<List<ConsultationOpinionDto>> getConsultationOpinions(
|
||||||
|
@ApiParam("会诊申请单号") @RequestParam String consultationId) {
|
||||||
|
try {
|
||||||
|
List<ConsultationOpinionDto> opinions = consultationAppService.getConsultationOpinions(consultationId);
|
||||||
|
return R.ok(opinions);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取会诊意见列表失败", e);
|
||||||
|
return R.fail("获取会诊意见列表失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
package com.openhis.web.consultation.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊确认表实体类
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-02-06
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("consultation_confirmation")
|
||||||
|
public class ConsultationConfirmation implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊申请ID(外键:consultation_request.id)
|
||||||
|
*/
|
||||||
|
@TableField("consultation_request_id")
|
||||||
|
private Long consultationRequestId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊申请单号
|
||||||
|
*/
|
||||||
|
@TableField("consultation_id")
|
||||||
|
private String consultationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认会诊的医生ID(操作【确认】按钮的当前医生ID)
|
||||||
|
*/
|
||||||
|
@TableField("confirming_physician_id")
|
||||||
|
private Long confirmingPhysicianId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认会诊的医生姓名(操作【确认】按钮的当前医生姓名)
|
||||||
|
*/
|
||||||
|
@TableField("confirming_physician_name")
|
||||||
|
private String confirmingPhysicianName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代表科室ID(操作【确认】按钮的当前开单科室ID)
|
||||||
|
*/
|
||||||
|
@TableField("confirming_dept_id")
|
||||||
|
private Long confirmingDeptId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代表科室名称(操作【确认】按钮的当前开单科室)
|
||||||
|
*/
|
||||||
|
@TableField("confirming_dept_name")
|
||||||
|
private String confirmingDeptName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认会诊的日期(操作【确认】按钮当前系统时间)
|
||||||
|
*/
|
||||||
|
@TableField("confirming_date")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date confirmingDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊状态:0-取消确认(作废),20-已确认(会诊医生已查看/同意,可写初步意见),30-已签名(已电子签名,意见最终生效),40-已完成(会诊报告已回写,流程关闭)
|
||||||
|
*/
|
||||||
|
@TableField("consultation_status")
|
||||||
|
private Integer consultationStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊意见(最多500字)
|
||||||
|
*/
|
||||||
|
@TableField("consultation_opinion")
|
||||||
|
private String consultationOpinion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊确认参加医师(多个医师信息,JSON格式)
|
||||||
|
*/
|
||||||
|
@TableField("confirming_physicians")
|
||||||
|
private String confirmingPhysicians;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有医生都确认的时间
|
||||||
|
*/
|
||||||
|
@TableField("all_confirmed_date")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date allConfirmedDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有医生都签名的时间
|
||||||
|
*/
|
||||||
|
@TableField("all_signed_date")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date allSignedDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名医生姓名
|
||||||
|
*/
|
||||||
|
@TableField("signature")
|
||||||
|
private String signature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名医生ID
|
||||||
|
*/
|
||||||
|
@TableField("signature_physician_id")
|
||||||
|
private Long signaturePhysicianId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名时间
|
||||||
|
*/
|
||||||
|
@TableField("signature_date")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date signatureDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(value = "create_time", fill = FieldFill.INSERT)
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间(由 Java 代码维护)
|
||||||
|
*/
|
||||||
|
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建人
|
||||||
|
*/
|
||||||
|
@TableField(value = "create_by", fill = FieldFill.INSERT)
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新人
|
||||||
|
*/
|
||||||
|
@TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户ID
|
||||||
|
*/
|
||||||
|
@TableField("tenant_id")
|
||||||
|
private Long tenantId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 逻辑删除标识:0-未删除,1-已删除
|
||||||
|
*/
|
||||||
|
@TableField("is_deleted")
|
||||||
|
@TableLogic
|
||||||
|
private Integer isDeleted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@TableField("remark")
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,13 @@ public class ConsultationInvited implements Serializable {
|
|||||||
private String invitedPhysicianName;
|
private String invitedPhysicianName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 邀请状态(0-待确认,1-已确认,2-已拒绝)
|
* 邀请状态(使用ConsultationStatusEnum)
|
||||||
|
* 0-新开(待确认)
|
||||||
|
* 10-已提交(待确认)
|
||||||
|
* 20-已确认
|
||||||
|
* 30-已签名
|
||||||
|
* 40-已完成
|
||||||
|
* 50-已取消(已拒绝)
|
||||||
*/
|
*/
|
||||||
@TableField("invited_status")
|
@TableField("invited_status")
|
||||||
private Integer invitedStatus;
|
private Integer invitedStatus;
|
||||||
@@ -69,11 +75,18 @@ public class ConsultationInvited implements Serializable {
|
|||||||
private Date confirmTime;
|
private Date confirmTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 确认意见
|
* 确认意见(格式:科室-医生:意见内容)
|
||||||
*/
|
*/
|
||||||
@TableField("confirm_opinion")
|
@TableField("confirm_opinion")
|
||||||
private String confirmOpinion;
|
private String confirmOpinion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名时间
|
||||||
|
*/
|
||||||
|
@TableField("signature_time")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date signatureTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -218,6 +218,24 @@ public class ConsultationRequest implements Serializable {
|
|||||||
@TableField("cancel_reason")
|
@TableField("cancel_reason")
|
||||||
private String cancelReason;
|
private String cancelReason;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已确认的医生数量
|
||||||
|
*/
|
||||||
|
@TableField("confirmed_count")
|
||||||
|
private Integer confirmedCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已签名的医生数量
|
||||||
|
*/
|
||||||
|
@TableField("signed_count")
|
||||||
|
private Integer signedCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被邀请的医生总数
|
||||||
|
*/
|
||||||
|
@TableField("invited_count")
|
||||||
|
private Integer invitedCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
package com.openhis.web.consultation.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊确认DTO
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-02-06
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel("会诊确认DTO")
|
||||||
|
public class ConsultationConfirmationDto implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ApiModelProperty("主键ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty("会诊申请ID")
|
||||||
|
private Long consultationRequestId;
|
||||||
|
|
||||||
|
@ApiModelProperty("会诊申请单号")
|
||||||
|
private String consultationId;
|
||||||
|
|
||||||
|
@ApiModelProperty("确认医生ID")
|
||||||
|
private Long confirmingPhysicianId;
|
||||||
|
|
||||||
|
@ApiModelProperty("确认医生姓名")
|
||||||
|
private String confirmingPhysicianName;
|
||||||
|
|
||||||
|
@ApiModelProperty("代表科室ID")
|
||||||
|
private Long confirmingDeptId;
|
||||||
|
|
||||||
|
@ApiModelProperty("代表科室名称")
|
||||||
|
private String confirmingDeptName;
|
||||||
|
|
||||||
|
@ApiModelProperty("确认日期")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date confirmingDate;
|
||||||
|
|
||||||
|
@ApiModelProperty("会诊状态:0-取消确认,20-已确认,30-已签名,40-已完成")
|
||||||
|
private Integer consultationStatus;
|
||||||
|
|
||||||
|
@ApiModelProperty("会诊意见")
|
||||||
|
private String consultationOpinion;
|
||||||
|
|
||||||
|
@ApiModelProperty("会诊确认参加医师")
|
||||||
|
private String confirmingPhysician;
|
||||||
|
|
||||||
|
@ApiModelProperty("签名医生姓名")
|
||||||
|
private String signature;
|
||||||
|
|
||||||
|
@ApiModelProperty("签名医生ID")
|
||||||
|
private Long signaturePhysicianId;
|
||||||
|
|
||||||
|
@ApiModelProperty("签名时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date signatureDate;
|
||||||
|
|
||||||
|
@ApiModelProperty("备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
// ========== 扩展字段(用于前端显示) ==========
|
||||||
|
|
||||||
|
@ApiModelProperty("患者姓名")
|
||||||
|
private String patientName;
|
||||||
|
|
||||||
|
@ApiModelProperty("性别")
|
||||||
|
private String genderText;
|
||||||
|
|
||||||
|
@ApiModelProperty("年龄")
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
@ApiModelProperty("就诊卡号")
|
||||||
|
private String patientIdentifierNo;
|
||||||
|
|
||||||
|
@ApiModelProperty("申请科室")
|
||||||
|
private String applyDept;
|
||||||
|
|
||||||
|
@ApiModelProperty("申请医师")
|
||||||
|
private String applyDoctor;
|
||||||
|
|
||||||
|
@ApiModelProperty("申请时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date applyTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("会诊时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date consultationDate;
|
||||||
|
|
||||||
|
@ApiModelProperty("紧急标志")
|
||||||
|
private Boolean urgent;
|
||||||
|
|
||||||
|
@ApiModelProperty("会诊邀请对象")
|
||||||
|
private String invitedObject;
|
||||||
|
|
||||||
|
@ApiModelProperty("病史及目的")
|
||||||
|
private String consultationPurpose;
|
||||||
|
|
||||||
|
@ApiModelProperty("门诊诊断")
|
||||||
|
private String provisionalDiagnosis;
|
||||||
|
|
||||||
|
@ApiModelProperty("提交医生")
|
||||||
|
private String submittingPhysician;
|
||||||
|
|
||||||
|
@ApiModelProperty("提交时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date submittingTime;
|
||||||
|
|
||||||
|
// ========== 当前医生的个人状态 ==========
|
||||||
|
|
||||||
|
@ApiModelProperty("当前医生的邀请状态:0-待确认,1-已确认,2-已拒绝,3-已签名")
|
||||||
|
private Integer myInvitedStatus;
|
||||||
|
|
||||||
|
@ApiModelProperty("当前医生的确认时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date myConfirmTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("当前医生的签名时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date mySignatureTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.openhis.web.consultation.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊意见DTO
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-02-09
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel("会诊意见DTO")
|
||||||
|
public class ConsultationOpinionDto implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ApiModelProperty("医生ID")
|
||||||
|
private Long physicianId;
|
||||||
|
|
||||||
|
@ApiModelProperty("医生姓名")
|
||||||
|
private String physicianName;
|
||||||
|
|
||||||
|
@ApiModelProperty("科室ID")
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
@ApiModelProperty("科室名称")
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
@ApiModelProperty("会诊意见(已包含科室-医生前缀)")
|
||||||
|
private String opinion;
|
||||||
|
|
||||||
|
@ApiModelProperty("确认时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date confirmTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("签名时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date signatureTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("状态:0-待确认,1-已确认,2-已拒绝,3-已签名")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@ApiModelProperty("是否已签名")
|
||||||
|
private Boolean isSigned;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ public class ConsultationRequestDto implements Serializable {
|
|||||||
*/
|
*/
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date consultationDate;
|
private Date consultationDate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 申请时间
|
* 申请时间
|
||||||
*/
|
*/
|
||||||
@@ -132,7 +132,7 @@ public class ConsultationRequestDto implements Serializable {
|
|||||||
* 会诊项目名称(如:院内会诊、远程会诊等)
|
* 会诊项目名称(如:院内会诊、远程会诊等)
|
||||||
*/
|
*/
|
||||||
private String consultationActivityName;
|
private String consultationActivityName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 紧急程度(1=普通,2=紧急)
|
* 紧急程度(1=普通,2=紧急)
|
||||||
*/
|
*/
|
||||||
@@ -185,6 +185,34 @@ public class ConsultationRequestDto implements Serializable {
|
|||||||
*/
|
*/
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date myConfirmTime;
|
private Date myConfirmTime;
|
||||||
|
|
||||||
|
// ==================== 会诊记录相关字段(会诊完成后显示) ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊邀请参加医师(已签名医生列表,格式:科室-姓名、科室-姓名)
|
||||||
|
*/
|
||||||
|
private String invitedPhysiciansText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所属医生(第一个签名的医生)
|
||||||
|
*/
|
||||||
|
private String attendingPhysician;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 代表科室(第一个签名医生的科室)
|
||||||
|
*/
|
||||||
|
private String representDepartment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名医生(第一个签名的医生)
|
||||||
|
*/
|
||||||
|
private String signPhysician;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名时间(第一个签名医生的签名时间)
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date signTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 邀请对象DTO
|
* 邀请对象DTO
|
||||||
@@ -38,6 +39,20 @@ public class InvitedObjectDto implements Serializable {
|
|||||||
* 医生姓名
|
* 医生姓名
|
||||||
*/
|
*/
|
||||||
private String physicianName;
|
private String physicianName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请状态:0=待确认,1=已确认,3=已签名
|
||||||
|
*/
|
||||||
|
private Integer invitedStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认时间
|
||||||
|
*/
|
||||||
|
private Date confirmTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名时间
|
||||||
|
*/
|
||||||
|
private Date signatureTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public enum ConsultationStatusEnum {
|
|||||||
* 判断是否可以编辑
|
* 判断是否可以编辑
|
||||||
*/
|
*/
|
||||||
public boolean canEdit() {
|
public boolean canEdit() {
|
||||||
return this == NEW || this == SUBMITTED;
|
return this == NEW;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,3 +83,6 @@ public enum ConsultationStatusEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -49,3 +49,8 @@ public enum ConsultationUrgencyEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -54,3 +54,7 @@ public enum InvitedStatusEnum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.openhis.web.consultation.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.openhis.web.consultation.domain.ConsultationConfirmation;
|
||||||
|
import org.apache.ibatis.annotations.Delete;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊确认Mapper接口
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-02-06
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ConsultationConfirmationMapper extends BaseMapper<ConsultationConfirmation> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物理删除确认记录(根据会诊申请ID)
|
||||||
|
*
|
||||||
|
* @param consultationRequestId 会诊申请ID
|
||||||
|
* @return 删除的记录数
|
||||||
|
*/
|
||||||
|
@Delete("DELETE FROM consultation_confirmation WHERE consultation_request_id = #{consultationRequestId}")
|
||||||
|
int physicalDeleteByRequestId(@Param("consultationRequestId") Long consultationRequestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
-- ============================================
|
||||||
|
-- 修复会诊确认表的 NOT NULL 约束问题
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 将 confirming_physician_id 等字段改为可空
|
||||||
|
-- 因为在新的方案中,这些字段在所有医生确认后才会填充
|
||||||
|
|
||||||
|
ALTER TABLE hisdev.consultation_confirmation
|
||||||
|
ALTER COLUMN confirming_physician_id DROP NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE hisdev.consultation_confirmation
|
||||||
|
ALTER COLUMN confirming_physician_name DROP NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE hisdev.consultation_confirmation
|
||||||
|
ALTER COLUMN confirming_dept_id DROP NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE hisdev.consultation_confirmation
|
||||||
|
ALTER COLUMN confirming_dept_name DROP NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE hisdev.consultation_confirmation
|
||||||
|
ALTER COLUMN confirming_date DROP NOT NULL;
|
||||||
|
|
||||||
|
-- 说明:
|
||||||
|
-- 在新的方案中,consultation_confirmation 记录在所有医生确认后才创建
|
||||||
|
-- 这些字段用于记录"最后一个确认的医生"或"代表性医生"
|
||||||
|
-- 因此允许为 NULL,实际的医生信息存储在 confirming_physicians (JSON) 字段中
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
-- ============================================
|
||||||
|
-- 会诊确认功能优化 - 数据库表结构修改 (PostgreSQL版本)
|
||||||
|
-- ============================================
|
||||||
|
|
||||||
|
-- 1. 修改 consultation_request 表(添加计数字段)
|
||||||
|
ALTER TABLE hisdev.consultation_request
|
||||||
|
ADD COLUMN IF NOT EXISTS confirmed_count INT DEFAULT 0;
|
||||||
|
|
||||||
|
ALTER TABLE hisdev.consultation_request
|
||||||
|
ADD COLUMN IF NOT EXISTS signed_count INT DEFAULT 0;
|
||||||
|
|
||||||
|
ALTER TABLE hisdev.consultation_request
|
||||||
|
ADD COLUMN IF NOT EXISTS invited_count INT DEFAULT 0;
|
||||||
|
|
||||||
|
-- 2. 修改 consultation_invited 表(添加签名时间字段)
|
||||||
|
ALTER TABLE hisdev.consultation_invited
|
||||||
|
ADD COLUMN IF NOT EXISTS signature_time TIMESTAMP NULL;
|
||||||
|
|
||||||
|
-- 3. 修改 consultation_confirmation 表(优化字段)
|
||||||
|
ALTER TABLE hisdev.consultation_confirmation
|
||||||
|
ADD COLUMN IF NOT EXISTS all_confirmed_date TIMESTAMP NULL;
|
||||||
|
|
||||||
|
ALTER TABLE hisdev.consultation_confirmation
|
||||||
|
ADD COLUMN IF NOT EXISTS all_signed_date TIMESTAMP NULL;
|
||||||
|
|
||||||
|
-- 检查 confirming_physicians 字段是否存在,如果不存在则添加
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM information_schema.columns
|
||||||
|
WHERE table_schema = 'hisdev'
|
||||||
|
AND table_name = 'consultation_confirmation'
|
||||||
|
AND column_name = 'confirming_physicians'
|
||||||
|
) THEN
|
||||||
|
-- 如果 confirming_physician 存在,则重命名
|
||||||
|
IF EXISTS (
|
||||||
|
SELECT 1 FROM information_schema.columns
|
||||||
|
WHERE table_schema = 'hisdev'
|
||||||
|
AND table_name = 'consultation_confirmation'
|
||||||
|
AND column_name = 'confirming_physician'
|
||||||
|
) THEN
|
||||||
|
ALTER TABLE hisdev.consultation_confirmation
|
||||||
|
RENAME COLUMN confirming_physician TO confirming_physicians;
|
||||||
|
ELSE
|
||||||
|
-- 如果都不存在,则新增
|
||||||
|
ALTER TABLE hisdev.consultation_confirmation
|
||||||
|
ADD COLUMN confirming_physicians TEXT;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- 4. 为现有数据初始化计数字段
|
||||||
|
UPDATE hisdev.consultation_request cr
|
||||||
|
SET invited_count = (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM hisdev.consultation_invited ci
|
||||||
|
WHERE ci.consultation_request_id = cr.id
|
||||||
|
AND ci.is_deleted = 0
|
||||||
|
)
|
||||||
|
WHERE cr.invited_count = 0 OR cr.invited_count IS NULL;
|
||||||
|
|
||||||
|
UPDATE hisdev.consultation_request cr
|
||||||
|
SET confirmed_count = (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM hisdev.consultation_invited ci
|
||||||
|
WHERE ci.consultation_request_id = cr.id
|
||||||
|
AND ci.invited_status >= 1
|
||||||
|
AND ci.is_deleted = 0
|
||||||
|
)
|
||||||
|
WHERE cr.confirmed_count = 0 OR cr.confirmed_count IS NULL;
|
||||||
|
|
||||||
|
UPDATE hisdev.consultation_request cr
|
||||||
|
SET signed_count = (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM hisdev.consultation_invited ci
|
||||||
|
WHERE ci.consultation_request_id = cr.id
|
||||||
|
AND ci.invited_status >= 3
|
||||||
|
AND ci.is_deleted = 0
|
||||||
|
)
|
||||||
|
WHERE cr.signed_count = 0 OR cr.signed_count IS NULL;
|
||||||
|
|
||||||
|
-- 5. 添加索引优化查询性能(如果不存在)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_invited_status ON hisdev.consultation_invited(invited_status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_confirm_time ON hisdev.consultation_invited(confirm_time);
|
||||||
|
|
||||||
|
-- 6. 添加字段注释
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_request.confirmed_count IS '已确认的医生数量';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_request.signed_count IS '已签名的医生数量';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_request.invited_count IS '被邀请的医生总数';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.signature_time IS '签名时间';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_confirmation.all_confirmed_date IS '所有医生都确认的时间';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_confirmation.all_signed_date IS '所有医生都签名的时间';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_confirmation.confirming_physicians IS '参与确认的医生列表(JSON格式)';
|
||||||
|
|
||||||
@@ -86,6 +86,19 @@ function resolvePath(routePath, routeQuery) {
|
|||||||
return props.basePath
|
return props.basePath
|
||||||
}
|
}
|
||||||
if (routeQuery) {
|
if (routeQuery) {
|
||||||
|
try {
|
||||||
|
// 检查 routeQuery 是否已经是对象
|
||||||
|
if (typeof routeQuery === 'object') {
|
||||||
|
return { path: getNormalPath(props.basePath + '/' + routePath), query: routeQuery }
|
||||||
|
}
|
||||||
|
// 尝试解析 JSON 字符串
|
||||||
|
let query = JSON.parse(routeQuery);
|
||||||
|
return { path: getNormalPath(props.basePath + '/' + routePath), query: query }
|
||||||
|
} catch (e) {
|
||||||
|
// 如果解析失败,将其作为普通字符串处理
|
||||||
|
console.warn('Failed to parse routeQuery as JSON:', routeQuery, e);
|
||||||
|
return getNormalPath(props.basePath + '/' + routePath)
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
let query = JSON.parse(routeQuery);
|
let query = JSON.parse(routeQuery);
|
||||||
return { path: getNormalPath(props.basePath + '/' + routePath), query: query }
|
return { path: getNormalPath(props.basePath + '/' + routePath), query: query }
|
||||||
@@ -93,6 +106,19 @@ function resolvePath(routePath, routeQuery) {
|
|||||||
console.error('Failed to parse routeQuery:', routeQuery, e);
|
console.error('Failed to parse routeQuery:', routeQuery, e);
|
||||||
return getNormalPath(props.basePath + '/' + routePath)
|
return getNormalPath(props.basePath + '/' + routePath)
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
// 检查 routeQuery 是否已经是对象
|
||||||
|
if (typeof routeQuery === 'object') {
|
||||||
|
return { path: getNormalPath(props.basePath + '/' + routePath), query: routeQuery }
|
||||||
|
}
|
||||||
|
// 尝试解析 JSON 字符串
|
||||||
|
let query = JSON.parse(routeQuery);
|
||||||
|
return { path: getNormalPath(props.basePath + '/' + routePath), query: query }
|
||||||
|
} catch (e) {
|
||||||
|
// 如果解析失败,将其作为普通字符串处理
|
||||||
|
console.warn('Failed to parse routeQuery as JSON:', routeQuery, e);
|
||||||
|
return getNormalPath(props.basePath + '/' + routePath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return getNormalPath(props.basePath + '/' + routePath)
|
return getNormalPath(props.basePath + '/' + routePath)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,6 +237,21 @@ export const dynamicRoutes = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/doctorstation',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/doctorstation/index',
|
||||||
|
name: 'DoctorStation',
|
||||||
|
meta: { title: '医生工作站', icon: 'operation' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'pending-emr',
|
||||||
|
component: () => import('@/views/doctorstation/pendingEmr.vue'),
|
||||||
|
name: 'PendingEmr',
|
||||||
|
meta: { title: '待写病历', icon: 'document', permissions: ['doctorstation:pending-emr:view'] }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/features',
|
path: '/features',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
@@ -298,6 +313,40 @@ export const dynamicRoutes = [
|
|||||||
meta: { title: '门诊日结', icon: 'document' }
|
meta: { title: '门诊日结', icon: 'document' }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/consultationmanagement',
|
||||||
|
component: Layout,
|
||||||
|
name: 'ConsultationManagement',
|
||||||
|
meta: { title: '会诊管理', icon: 'operation' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'consultationapplication',
|
||||||
|
component: () => import('@/views/consultationmanagement/consultationapplication/index.vue'),
|
||||||
|
name: 'ConsultationApplication',
|
||||||
|
meta: { title: '门诊会诊申请管理', icon: 'document' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'consultationconfirmation',
|
||||||
|
component: () => import('@/views/consultationmanagement/consultationconfirmation/index.vue'),
|
||||||
|
name: 'ConsultationConfirmation',
|
||||||
|
meta: { title: '门诊会诊申请确认', icon: 'document' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/medicationmanagement',
|
||||||
|
component: Layout,
|
||||||
|
name: 'MedicationManagement',
|
||||||
|
meta: { title: '药房管理', icon: 'medication' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'dayEndSettlement',
|
||||||
|
component: () => import('@/views/medicationmanagement/dayEndSettlement/index.vue'),
|
||||||
|
name: 'DayEndSettlement',
|
||||||
|
meta: { title: '日结结算单管理', icon: 'document' }
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊申请列表(简单查询)
|
||||||
|
* @param {Object} params 查询参数
|
||||||
|
*/
|
||||||
|
export function getConsultationList(params) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会诊申请列表(支持多条件查询)
|
||||||
|
* @param {Object} data 查询条件
|
||||||
|
*/
|
||||||
|
export function queryConsultationList(data) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/query',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询会诊申请列表(支持多条件查询)
|
||||||
|
* @param {Object} data 查询条件
|
||||||
|
* @param {Number} pageNum 页码
|
||||||
|
* @param {Number} pageSize 每页大小
|
||||||
|
*/
|
||||||
|
export function queryConsultationListPage(data, pageNum, pageSize) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/queryPage',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
params: { pageNum, pageSize },
|
||||||
|
headers: {
|
||||||
|
repeatSubmit: false // 关键:告诉后端不要进行防重复提交检查
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存会诊申请(新增或修改)
|
||||||
|
* @param {Object} data 会诊申请数据
|
||||||
|
*/
|
||||||
|
export function saveConsultation(data) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/save',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交会诊申请
|
||||||
|
* @param {String} consultationId 会诊申请单号
|
||||||
|
*/
|
||||||
|
export function submitConsultation(consultationId) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/submit',
|
||||||
|
method: 'post',
|
||||||
|
params: { consultationId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 作废会诊申请
|
||||||
|
* @param {String} consultationId 会诊申请单号
|
||||||
|
* @param {String} cancelReason 作废原因
|
||||||
|
*/
|
||||||
|
export function cancelConsultation(consultationId, cancelReason) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/cancel',
|
||||||
|
method: 'post',
|
||||||
|
params: { consultationId, cancelReason }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束会诊申请
|
||||||
|
* @param {String} consultationId 会诊申请单号
|
||||||
|
*/
|
||||||
|
export function completeConsultation(consultationId) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/complete',
|
||||||
|
method: 'post',
|
||||||
|
params: { consultationId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取科室医生树
|
||||||
|
*/
|
||||||
|
export function getDepartmentTree() {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/departmentTree',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主诊断
|
||||||
|
* @param {Number} encounterId 就诊ID
|
||||||
|
*/
|
||||||
|
export function getMainDiagnosis(encounterId) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/mainDiagnosis',
|
||||||
|
method: 'get',
|
||||||
|
params: { encounterId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊项目列表
|
||||||
|
*/
|
||||||
|
export function getConsultationActivities() {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/activities',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,743 @@
|
|||||||
|
<template>
|
||||||
|
<div class="consultation-application-container">
|
||||||
|
<!-- 页面标题 -->
|
||||||
|
<div class="page-header">
|
||||||
|
<span class="tab-title">门诊会诊申请管理</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 查询条件 -->
|
||||||
|
<div class="search-section">
|
||||||
|
<el-form :model="queryParams" inline>
|
||||||
|
<el-form-item label="时间类型">
|
||||||
|
<el-select v-model="queryParams.timeType" placeholder="请选择" style="width: 120px">
|
||||||
|
<el-option label="会诊时间" value="consultation" />
|
||||||
|
<el-option label="开始时间" value="start" />
|
||||||
|
<el-option label="结束时间" value="end" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="开始时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="queryParams.startTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="年/月/日 --:--"
|
||||||
|
format="YYYY/MM/DD HH:mm"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 180px"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="结束时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="queryParams.endTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="年/月/日 --:--"
|
||||||
|
format="YYYY/MM/DD HH:mm"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 180px"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="申请科室">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.applyDept"
|
||||||
|
placeholder="请输入或输入科室"
|
||||||
|
clearable
|
||||||
|
style="width: 150px"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="申请医生">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.applyDoctor"
|
||||||
|
placeholder="请输入或输入医生"
|
||||||
|
clearable
|
||||||
|
style="width: 150px"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="紧急程度">
|
||||||
|
<el-select v-model="queryParams.urgency" placeholder="全部" style="width: 120px">
|
||||||
|
<el-option label="全部" value="" />
|
||||||
|
<el-option label="一般" value="1" />
|
||||||
|
<el-option label="紧急" value="2" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="会诊状态">
|
||||||
|
<el-select v-model="queryParams.consultationStatus" placeholder="全部" style="width: 120px">
|
||||||
|
<el-option label="全部" value="" />
|
||||||
|
<el-option label="未提交" value="0" />
|
||||||
|
<el-option label="提交" value="10" />
|
||||||
|
<el-option label="结束" value="40" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="病人姓名">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.patientName"
|
||||||
|
placeholder="请输入病人姓名"
|
||||||
|
clearable
|
||||||
|
style="width: 150px"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleQuery">
|
||||||
|
<el-icon><Search /></el-icon> 查询
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="handleReset">
|
||||||
|
<el-icon><Refresh /></el-icon> 重置
|
||||||
|
</el-button>
|
||||||
|
<el-button type="success" @click="handlePrint">
|
||||||
|
<el-icon><Printer /></el-icon> 打印
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<div class="table-section">
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
highlight-current-row
|
||||||
|
@current-change="handleRowChange"
|
||||||
|
v-loading="loading"
|
||||||
|
height="400"
|
||||||
|
>
|
||||||
|
<el-table-column type="index" label="ID" width="60" align="center" />
|
||||||
|
<el-table-column label="急" width="60" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-checkbox :model-value="scope.row.consultationUrgency === '2'" disabled />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="patientName" label="病人姓名" min-width="100" />
|
||||||
|
<el-table-column prop="consultationDate" label="会诊时间" min-width="160">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ formatDateTime(scope.row.consultationDate) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="department" label="申请科室" min-width="120" />
|
||||||
|
<el-table-column prop="invitedObject" label="邀请对象" min-width="150" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="consultationRequestDate" label="申请时间" min-width="160">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ formatDateTime(scope.row.consultationRequestDate) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="requestingPhysician" label="申请医师" min-width="100" />
|
||||||
|
<el-table-column label="提交" width="70" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-checkbox :model-value="scope.row.consultationStatus >= 10" disabled />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="结束" width="70" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-checkbox :model-value="scope.row.consultationStatus >= 40" disabled />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="200" fixed="right" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
:icon="Edit"
|
||||||
|
@click="handleEdit(scope.row)"
|
||||||
|
:disabled="scope.row.consultationStatus >= 40"
|
||||||
|
title="编辑"
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
type="info"
|
||||||
|
size="small"
|
||||||
|
:icon="View"
|
||||||
|
@click="handleView(scope.row)"
|
||||||
|
title="查看"
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
size="small"
|
||||||
|
:icon="Delete"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
:disabled="scope.row.consultationStatus >= 40"
|
||||||
|
title="作废"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页组件 -->
|
||||||
|
<div class="pagination-container">
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="pagination.currentPage"
|
||||||
|
v-model:page-size="pagination.pageSize"
|
||||||
|
:page-sizes="[10, 20, 30, 50, 100]"
|
||||||
|
:total="pagination.total"
|
||||||
|
:disabled="loading"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 编辑/查看弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:title="dialogTitle"
|
||||||
|
width="800px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
@close="handleDialogClose"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="formRules"
|
||||||
|
label-width="120px"
|
||||||
|
:disabled="isViewMode"
|
||||||
|
>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="申请单号">
|
||||||
|
<el-input v-model="formData.consultationId" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="申请时间">
|
||||||
|
<el-input :model-value="formatDateTime(formData.consultationRequestDate)" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="病人姓名">
|
||||||
|
<el-input v-model="formData.patientName" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="性别">
|
||||||
|
<el-input :model-value="formData.genderEnum === 1 ? '男' : '女'" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="年龄">
|
||||||
|
<el-input v-model="formData.age" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="就诊卡号">
|
||||||
|
<el-input v-model="formData.patientIdentifierNo" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="申请医师" prop="requestingPhysician">
|
||||||
|
<el-input v-model="formData.requestingPhysician" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="会诊时间" prop="consultationDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formData.consultationDate"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="年/月/日 --:--"
|
||||||
|
format="YYYY/MM/DD HH:mm"
|
||||||
|
value-format="YYYY-MM-DD HH:mm:ss"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="申请科室">
|
||||||
|
<el-input v-model="formData.department" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="门诊诊断">
|
||||||
|
<el-input v-model="formData.provisionalDiagnosis" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-form-item label="患者病史及会诊目的" prop="consultationPurpose">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.consultationPurpose"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入患者病史及会诊目的"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="会诊邀请对象">
|
||||||
|
<el-input v-model="formData.invitedObject" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="会诊邀请参加医师">
|
||||||
|
<el-input placeholder="请输入参加医师姓名" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<div class="section-title">会诊记录</div>
|
||||||
|
<el-form-item label="会诊意见">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.consultationOpinion"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="会诊意见"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="所属医生">
|
||||||
|
<el-input v-model="formData.attendingPhysician" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="代表科室">
|
||||||
|
<el-input v-model="formData.representDepartment" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="签名医生">
|
||||||
|
<el-input v-model="formData.signPhysician" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="签名时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formData.signTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="年/月/日 --:--"
|
||||||
|
format="YYYY/MM/DD HH:mm"
|
||||||
|
disabled
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="dialogVisible = false">{{ isViewMode ? '关闭' : '取消' }}</el-button>
|
||||||
|
<el-button v-if="!isViewMode" type="primary" @click="handleSave" :loading="saving">
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="ConsultationApplication">
|
||||||
|
import { ref, reactive, onMounted, computed } from 'vue'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { Search, Refresh, Printer, Edit, View, Delete } from '@element-plus/icons-vue'
|
||||||
|
import { queryConsultationListPage, cancelConsultation, saveConsultation } from './api'
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const saving = ref(false)
|
||||||
|
const tableData = ref([])
|
||||||
|
const currentRow = ref(null)
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const isViewMode = ref(false)
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
// 用于取消请求的控制器
|
||||||
|
let abortController = null
|
||||||
|
|
||||||
|
// 分页参数
|
||||||
|
const pagination = reactive({
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
total: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const queryParams = reactive({
|
||||||
|
timeType: 'consultation',
|
||||||
|
startTime: '',
|
||||||
|
endTime: '',
|
||||||
|
applyDept: '',
|
||||||
|
applyDoctor: '',
|
||||||
|
urgency: '',
|
||||||
|
consultationStatus: '',
|
||||||
|
patientName: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const formData = ref({
|
||||||
|
id: null,
|
||||||
|
consultationId: '',
|
||||||
|
patientName: '',
|
||||||
|
genderEnum: null,
|
||||||
|
age: null,
|
||||||
|
patientIdentifierNo: '',
|
||||||
|
requestingPhysician: '',
|
||||||
|
consultationDate: '',
|
||||||
|
department: '',
|
||||||
|
provisionalDiagnosis: '',
|
||||||
|
consultationPurpose: '',
|
||||||
|
invitedObject: '',
|
||||||
|
consultationOpinion: '',
|
||||||
|
attendingPhysician: '',
|
||||||
|
representDepartment: '',
|
||||||
|
signPhysician: '',
|
||||||
|
signTime: null,
|
||||||
|
consultationRequestDate: null
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRules = {
|
||||||
|
requestingPhysician: [
|
||||||
|
{ required: true, message: '请输入申请医师', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
consultationDate: [
|
||||||
|
{ required: true, message: '请选择会诊时间', trigger: 'change' }
|
||||||
|
],
|
||||||
|
consultationPurpose: [
|
||||||
|
{ required: true, message: '请输入患者病史及会诊目的', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const dialogTitle = computed(() => {
|
||||||
|
return isViewMode.value ? '会诊申请查看' : '会诊申请编辑'
|
||||||
|
})
|
||||||
|
|
||||||
|
const formatDateTime = (date) => {
|
||||||
|
if (!date) return ''
|
||||||
|
const d = new Date(date)
|
||||||
|
if (isNaN(d.getTime())) return ''
|
||||||
|
|
||||||
|
const pad = (value) => String(value).padStart(2, '0')
|
||||||
|
const yyyy = d.getFullYear()
|
||||||
|
const mm = pad(d.getMonth() + 1)
|
||||||
|
const dd = pad(d.getDate())
|
||||||
|
const hh = pad(d.getHours())
|
||||||
|
const mi = pad(d.getMinutes())
|
||||||
|
const ss = pad(d.getSeconds())
|
||||||
|
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleQuery = async () => {
|
||||||
|
// 验证时间范围
|
||||||
|
if (queryParams.startTime && queryParams.endTime) {
|
||||||
|
const start = new Date(queryParams.startTime)
|
||||||
|
const end = new Date(queryParams.endTime)
|
||||||
|
if (end < start) {
|
||||||
|
ElMessage.warning('结束时间不能早于开始时间')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置到第一页
|
||||||
|
pagination.currentPage = 1
|
||||||
|
await loadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
Object.keys(queryParams).forEach(key => {
|
||||||
|
if (key === 'timeType') {
|
||||||
|
queryParams[key] = 'consultation'
|
||||||
|
} else {
|
||||||
|
queryParams[key] = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
pagination.currentPage = 1
|
||||||
|
loadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pagination.pageSize = val
|
||||||
|
pagination.currentPage = 1
|
||||||
|
loadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
// 如果正在加载,忽略此次操作
|
||||||
|
if (loading.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pagination.currentPage = val
|
||||||
|
loadData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePrint = () => {
|
||||||
|
if (!currentRow.value) {
|
||||||
|
ElMessage.warning('请先选择一条记录')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
window.print()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRowChange = (row) => {
|
||||||
|
currentRow.value = row
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEdit = (row) => {
|
||||||
|
// 检查是否已结束
|
||||||
|
if (row.consultationStatus >= 40) {
|
||||||
|
ElMessage.warning('已结束的会诊申请不可编辑')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isViewMode.value = false
|
||||||
|
formData.value = { ...row }
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleView = (row) => {
|
||||||
|
isViewMode.value = true
|
||||||
|
formData.value = { ...row }
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDialogClose = () => {
|
||||||
|
formRef.value?.clearValidate()
|
||||||
|
formData.value = {
|
||||||
|
id: null,
|
||||||
|
consultationId: '',
|
||||||
|
patientName: '',
|
||||||
|
genderEnum: null,
|
||||||
|
age: null,
|
||||||
|
patientIdentifierNo: '',
|
||||||
|
requestingPhysician: '',
|
||||||
|
consultationDate: '',
|
||||||
|
department: '',
|
||||||
|
provisionalDiagnosis: '',
|
||||||
|
consultationPurpose: '',
|
||||||
|
invitedObject: '',
|
||||||
|
consultationOpinion: '',
|
||||||
|
attendingPhysician: '',
|
||||||
|
representDepartment: '',
|
||||||
|
signPhysician: '',
|
||||||
|
signTime: null,
|
||||||
|
consultationRequestDate: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
try {
|
||||||
|
// 表单验证
|
||||||
|
await formRef.value.validate()
|
||||||
|
|
||||||
|
saving.value = true
|
||||||
|
const res = await saveConsultation(formData.value)
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success('保存成功')
|
||||||
|
dialogVisible.value = false
|
||||||
|
await loadData()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '保存失败,请重试')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error !== 'cancel') {
|
||||||
|
console.error('保存失败:', error)
|
||||||
|
ElMessage.error('保存失败,请重试')
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
saving.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = async (row) => {
|
||||||
|
// 检查是否已结束
|
||||||
|
if (row.consultationStatus >= 40) {
|
||||||
|
ElMessage.warning('已结束的会诊申请不可作废')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm('确定要作废该会诊申请吗?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
const res = await cancelConsultation(row.consultationId, '用户作废')
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success('作废成功')
|
||||||
|
await loadData()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '作废失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error !== 'cancel') {
|
||||||
|
console.error('作废失败:', error)
|
||||||
|
ElMessage.error('作废失败')
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadData = async () => {
|
||||||
|
// 如果正在加载,取消上一个请求
|
||||||
|
if (loading.value && abortController) {
|
||||||
|
abortController.abort()
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
|
// 创建新的 AbortController
|
||||||
|
abortController = new AbortController()
|
||||||
|
|
||||||
|
// 构建查询参数
|
||||||
|
const queryData = {
|
||||||
|
department: queryParams.applyDept,
|
||||||
|
requestingPhysician: queryParams.applyDoctor,
|
||||||
|
consultationStatus: queryParams.consultationStatus,
|
||||||
|
patientName: queryParams.patientName,
|
||||||
|
consultationRequestDate: queryParams.startTime,
|
||||||
|
consultationUrgency: queryParams.urgency
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('查询参数:', queryData, '页码:', pagination.currentPage, '每页:', pagination.pageSize)
|
||||||
|
|
||||||
|
const res = await queryConsultationListPage(queryData, pagination.currentPage, pagination.pageSize)
|
||||||
|
|
||||||
|
console.log('查询结果:', res)
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
tableData.value = res.data.records || []
|
||||||
|
pagination.total = res.data.total || 0
|
||||||
|
|
||||||
|
// 如果没有查询结果,显示提示
|
||||||
|
if (tableData.value.length === 0 && pagination.currentPage === 1) {
|
||||||
|
ElMessage.info('暂无查询结果')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 忽略"数据正在处理"的错误提示
|
||||||
|
if (!res.msg || !res.msg.includes('数据正在处理')) {
|
||||||
|
ElMessage.error(res.msg || '加载数据失败')
|
||||||
|
}
|
||||||
|
tableData.value = []
|
||||||
|
pagination.total = 0
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 忽略取消请求的错误
|
||||||
|
if (error.name === 'AbortError' || error.name === 'CanceledError') {
|
||||||
|
console.log('请求已取消')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error('加载数据失败:', error)
|
||||||
|
|
||||||
|
// 忽略"数据正在处理"的错误提示
|
||||||
|
const errorMsg = error.message || error.msg || '网络错误'
|
||||||
|
if (!errorMsg.includes('数据正在处理')) {
|
||||||
|
ElMessage.error('加载数据失败: ' + errorMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
tableData.value = []
|
||||||
|
pagination.total = 0
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
abortController = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.consultation-application-container {
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
min-height: calc(100vh - 84px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
padding-bottom: 12px;
|
||||||
|
border-bottom: 2px solid #e5e7eb;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-title {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #2563eb;
|
||||||
|
border-bottom: 3px solid #2563eb;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 16px;
|
||||||
|
background: #f9fafb;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-section {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-container {
|
||||||
|
margin-top: 16px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin: 20px 0 16px 0;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 2px solid #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.search-section,
|
||||||
|
.pagination-container,
|
||||||
|
.el-table__column--selection,
|
||||||
|
.el-table-column--action {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 表单样式优化 */
|
||||||
|
:deep(.el-form-item__label) {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input.is-disabled .el-input__inner) {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-textarea.is-disabled .el-textarea__inner) {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待确认的会诊列表(当前医生被邀请的会诊)
|
||||||
|
*/
|
||||||
|
export function getPendingConfirmationList() {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/confirmation/pending',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认会诊
|
||||||
|
* @param {Object} data 会诊确认数据
|
||||||
|
*/
|
||||||
|
export function confirmConsultation(data) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/confirmation/confirm',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消确认会诊
|
||||||
|
* @param {String} consultationId 会诊申请单号
|
||||||
|
*/
|
||||||
|
export function cancelConfirmation(consultationId) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/confirmation/cancelConfirm',
|
||||||
|
method: 'post',
|
||||||
|
params: { consultationId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名会诊
|
||||||
|
* @param {String} consultationId 会诊申请单号
|
||||||
|
*/
|
||||||
|
export function signConsultation(consultationId) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/confirmation/sign',
|
||||||
|
method: 'post',
|
||||||
|
params: { consultationId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊确认详情
|
||||||
|
* @param {String} consultationId 会诊申请单号
|
||||||
|
*/
|
||||||
|
export function getConfirmationDetail(consultationId) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/confirmation/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: { consultationId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊意见列表
|
||||||
|
* @param {String} consultationId 会诊申请单号
|
||||||
|
*/
|
||||||
|
export function getConsultationOpinions(consultationId) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/confirmation/opinions',
|
||||||
|
method: 'get',
|
||||||
|
params: { consultationId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -30,28 +30,37 @@
|
|||||||
stripe
|
stripe
|
||||||
highlight-current-row
|
highlight-current-row
|
||||||
@current-change="handleRowChange"
|
@current-change="handleRowChange"
|
||||||
|
v-loading="loading"
|
||||||
>
|
>
|
||||||
<el-table-column type="index" width="60" label="序号" align="center" />
|
<el-table-column type="index" width="60" label="序号" align="center" />
|
||||||
<el-table-column label="紧急" width="70" align="center">
|
<el-table-column label="紧急" width="70" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-checkbox v-model="scope.row.urgent" />
|
<el-checkbox v-model="scope.row.urgent" disabled />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="consultationId" label="申请单号" min-width="160" />
|
<el-table-column prop="consultationId" label="申请单号" min-width="160" />
|
||||||
<el-table-column prop="patientName" label="病人姓名" min-width="100" />
|
<el-table-column prop="patientName" label="病人姓名" min-width="100" />
|
||||||
<el-table-column prop="consultationTime" label="会诊时间" min-width="160" />
|
<el-table-column prop="consultationDate" label="会诊时间" min-width="160">
|
||||||
<el-table-column prop="invitee" label="邀请对象" min-width="120" />
|
<template #default="scope">
|
||||||
|
{{ formatDateTime(scope.row.consultationDate) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="invitedObject" label="邀请对象" min-width="120" />
|
||||||
<el-table-column prop="applyDept" label="申请科室" min-width="120" />
|
<el-table-column prop="applyDept" label="申请科室" min-width="120" />
|
||||||
<el-table-column prop="applyDoctor" label="申请医师" min-width="120" />
|
<el-table-column prop="applyDoctor" label="申请医师" min-width="120" />
|
||||||
<el-table-column prop="applyTime" label="申请时间" min-width="160" />
|
<el-table-column prop="applyTime" label="申请时间" min-width="160">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ formatDateTime(scope.row.applyTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="确认" width="70" align="center">
|
<el-table-column label="确认" width="70" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-checkbox v-model="scope.row.confirmed" disabled />
|
<el-checkbox :model-value="scope.row.myInvitedStatus >= 20" disabled />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="签名" width="70" align="center">
|
<el-table-column label="签名" width="70" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-checkbox v-model="scope.row.signed" disabled />
|
<el-checkbox :model-value="scope.row.myInvitedStatus >= 30" disabled />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -68,7 +77,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="性别">
|
<el-form-item label="性别">
|
||||||
<el-input v-model="formData.gender" disabled />
|
<el-input v-model="formData.genderText" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
@@ -78,7 +87,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="就诊卡号">
|
<el-form-item label="就诊卡号">
|
||||||
<el-input v-model="formData.cardNo" disabled />
|
<el-input v-model="formData.patientIdentifierNo" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
@@ -93,7 +102,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="会诊时间">
|
<el-form-item label="会诊时间">
|
||||||
<el-input v-model="formData.consultationTime" disabled />
|
<el-input :model-value="formatDateTime(formData.consultationDate)" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
@@ -103,52 +112,92 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="会诊邀请对象">
|
<el-form-item label="会诊邀请对象">
|
||||||
<el-input v-model="formData.invitee" disabled />
|
<el-input v-model="formData.invitedObject" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="提交医生">
|
<el-form-item label="提交医生">
|
||||||
<el-input v-model="formData.applyDoctor" disabled />
|
<el-input v-model="formData.submittingPhysician" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="提交时间">
|
<el-form-item label="提交时间">
|
||||||
<el-input v-model="formData.applyTime" disabled />
|
<el-input :model-value="formatDateTime(formData.submittingTime)" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-form-item label="病史及目的">
|
<el-form-item label="病史及目的">
|
||||||
<el-input v-model="formData.history" type="textarea" :rows="3" disabled />
|
<el-input v-model="formData.consultationPurpose" type="textarea" :rows="3" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="会诊确认参加医师" required>
|
<el-form-item label="门诊诊断">
|
||||||
<el-input v-model="formData.confirmingPhysician" placeholder="请输入会诊确认参加医师" />
|
<el-input v-model="formData.provisionalDiagnosis" type="textarea" :rows="2" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="会诊意见" required>
|
<el-form-item label="会诊意见" required>
|
||||||
<el-input v-model="formData.opinion" type="textarea" :rows="4" placeholder="请输入会诊意见" />
|
<el-input
|
||||||
|
v-model="formData.consultationOpinion"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="请输入会诊意见"
|
||||||
|
:disabled="!canEdit"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 会诊意见列表 -->
|
||||||
|
<el-form-item label="所有会诊意见">
|
||||||
|
<div class="opinions-container">
|
||||||
|
<el-timeline v-if="opinionList.length > 0">
|
||||||
|
<el-timeline-item
|
||||||
|
v-for="opinion in opinionList"
|
||||||
|
:key="opinion.physicianId"
|
||||||
|
:timestamp="formatDateTime(opinion.confirmTime)"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<el-card shadow="hover">
|
||||||
|
<div class="opinion-header">
|
||||||
|
<span class="physician-info">
|
||||||
|
<el-tag type="info" size="small">{{ opinion.deptName }}</el-tag>
|
||||||
|
<span style="margin-left: 8px; font-weight: bold;">{{ opinion.physicianName }}</span>
|
||||||
|
</span>
|
||||||
|
<el-tag v-if="opinion.isSigned" type="success" size="small">
|
||||||
|
<el-icon><Check /></el-icon> 已签名
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else type="warning" size="small">已确认</el-tag>
|
||||||
|
</div>
|
||||||
|
<div class="opinion-content">
|
||||||
|
{{ opinion.opinion }}
|
||||||
|
</div>
|
||||||
|
<div v-if="opinion.signatureTime" class="opinion-footer">
|
||||||
|
签名时间:{{ formatDateTime(opinion.signatureTime) }}
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-timeline-item>
|
||||||
|
</el-timeline>
|
||||||
|
<el-empty v-else description="暂无会诊意见" :image-size="80" />
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="所属医生">
|
<el-form-item label="所属医生">
|
||||||
<el-input v-model="formData.confirmDoctor" disabled />
|
<el-input v-model="formData.confirmingPhysicianName" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="代表科室">
|
<el-form-item label="代表科室">
|
||||||
<el-input v-model="formData.confirmDept" disabled />
|
<el-input v-model="formData.confirmingDeptName" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="签名医生">
|
<el-form-item label="签名医生">
|
||||||
<el-input v-model="formData.signDoctor" disabled />
|
<el-input v-model="formData.signature" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="签名时间">
|
<el-form-item label="签名时间">
|
||||||
<el-input v-model="formData.signTime" disabled />
|
<el-input :model-value="formatDateTime(formData.signatureDate)" disabled />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -158,94 +207,85 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="consultationConfirmation">
|
<script setup name="consultationConfirmation">
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref, onMounted, watch } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { Check } from '@element-plus/icons-vue'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
|
import {
|
||||||
|
getPendingConfirmationList,
|
||||||
|
confirmConsultation,
|
||||||
|
cancelConfirmation,
|
||||||
|
signConsultation,
|
||||||
|
getConsultationOpinions
|
||||||
|
} from './api'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const buildMockRows = () => ([
|
const loading = ref(false)
|
||||||
{
|
const tableData = ref([])
|
||||||
consultationId: 'CS20250812001',
|
|
||||||
urgent: false,
|
|
||||||
patientName: '陈明',
|
|
||||||
gender: '男',
|
|
||||||
age: '45',
|
|
||||||
cardNo: 'CARD20250812001',
|
|
||||||
consultationTime: '2025-08-12 17:48',
|
|
||||||
invitee: '演示测试',
|
|
||||||
applyDept: '内科',
|
|
||||||
applyDoctor: '徐斌',
|
|
||||||
applyTime: '2025-08-12 16:30',
|
|
||||||
history: '胸闷、气短一周,既往有高血压史。',
|
|
||||||
confirmingPhysician: '',
|
|
||||||
opinion: '',
|
|
||||||
confirmed: false,
|
|
||||||
signed: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
consultationId: 'CS20250812002',
|
|
||||||
urgent: true,
|
|
||||||
patientName: '赵敏',
|
|
||||||
gender: '女',
|
|
||||||
age: '32',
|
|
||||||
cardNo: 'CARD20250812002',
|
|
||||||
consultationTime: '2025-08-12 18:10',
|
|
||||||
invitee: '李医生',
|
|
||||||
applyDept: '神经内科',
|
|
||||||
applyDoctor: '王婷',
|
|
||||||
applyTime: '2025-08-12 16:50',
|
|
||||||
history: '头晕伴视物模糊3天。',
|
|
||||||
confirmingPhysician: '',
|
|
||||||
opinion: '',
|
|
||||||
confirmed: false,
|
|
||||||
signed: false
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
const tableData = ref(buildMockRows())
|
|
||||||
const currentRow = ref(null)
|
const currentRow = ref(null)
|
||||||
|
const opinionList = ref([]) // 会诊意见列表
|
||||||
|
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
|
id: null,
|
||||||
|
consultationRequestId: null,
|
||||||
consultationId: '',
|
consultationId: '',
|
||||||
urgent: false,
|
|
||||||
patientName: '',
|
patientName: '',
|
||||||
gender: '',
|
genderText: '',
|
||||||
age: '',
|
age: '',
|
||||||
cardNo: '',
|
patientIdentifierNo: '',
|
||||||
consultationTime: '',
|
|
||||||
invitee: '',
|
|
||||||
applyDept: '',
|
applyDept: '',
|
||||||
applyDoctor: '',
|
applyDoctor: '',
|
||||||
applyTime: '',
|
applyTime: null,
|
||||||
history: '',
|
consultationDate: null,
|
||||||
|
urgent: false,
|
||||||
|
invitedObject: '',
|
||||||
|
consultationPurpose: '',
|
||||||
|
provisionalDiagnosis: '',
|
||||||
confirmingPhysician: '',
|
confirmingPhysician: '',
|
||||||
opinion: '',
|
consultationOpinion: '',
|
||||||
confirmDoctor: '',
|
confirmingPhysicianName: '',
|
||||||
confirmDept: '',
|
confirmingDeptName: '',
|
||||||
signDoctor: '',
|
signature: '',
|
||||||
signTime: ''
|
signatureDate: null,
|
||||||
|
submittingPhysician: '',
|
||||||
|
submittingTime: null,
|
||||||
|
consultationStatus: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
const confirmButtonText = computed(() => {
|
const confirmButtonText = computed(() => {
|
||||||
if (!currentRow.value) {
|
if (!currentRow.value) {
|
||||||
return '确认'
|
return '确认'
|
||||||
}
|
}
|
||||||
return currentRow.value.confirmed ? '取消确认' : '确认'
|
// 基于当前医生的个人状态判断(使用ConsultationStatusEnum:20=已确认)
|
||||||
|
return currentRow.value.myInvitedStatus >= 20 ? '取消确认' : '确认'
|
||||||
})
|
})
|
||||||
|
|
||||||
const canSign = computed(() => {
|
const canSign = computed(() => {
|
||||||
return !!currentRow.value && currentRow.value.confirmed && !currentRow.value.signed
|
// 只要当前医生已确认但未签名,就可以签名(不需要等待所有医生都确认)
|
||||||
|
// 使用ConsultationStatusEnum:20=已确认,30=已签名
|
||||||
|
return !!currentRow.value &&
|
||||||
|
currentRow.value.myInvitedStatus >= 20 && // 已确认
|
||||||
|
currentRow.value.myInvitedStatus < 30 // 但还未签名
|
||||||
})
|
})
|
||||||
|
|
||||||
const formatDateTime = (date = new Date()) => {
|
const canEdit = computed(() => {
|
||||||
|
// 当前医生未确认时可以编辑(使用ConsultationStatusEnum:10=已提交/待确认,20=已确认)
|
||||||
|
return !!currentRow.value && (!currentRow.value.myInvitedStatus || currentRow.value.myInvitedStatus < 20)
|
||||||
|
})
|
||||||
|
|
||||||
|
const formatDateTime = (date) => {
|
||||||
|
if (!date) return ''
|
||||||
|
const d = new Date(date)
|
||||||
|
if (isNaN(d.getTime())) return ''
|
||||||
|
|
||||||
const pad = (value) => String(value).padStart(2, '0')
|
const pad = (value) => String(value).padStart(2, '0')
|
||||||
const yyyy = date.getFullYear()
|
const yyyy = d.getFullYear()
|
||||||
const mm = pad(date.getMonth() + 1)
|
const mm = pad(d.getMonth() + 1)
|
||||||
const dd = pad(date.getDate())
|
const dd = pad(d.getDate())
|
||||||
const hh = pad(date.getHours())
|
const hh = pad(d.getHours())
|
||||||
const mi = pad(date.getMinutes())
|
const mi = pad(d.getMinutes())
|
||||||
const ss = pad(date.getSeconds())
|
const ss = pad(d.getSeconds())
|
||||||
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}`
|
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,84 +295,207 @@ const getDoctorDept = () => userStore.orgName || '当前科室'
|
|||||||
const applyRowToForm = (row) => {
|
const applyRowToForm = (row) => {
|
||||||
if (!row) {
|
if (!row) {
|
||||||
Object.keys(formData.value).forEach((key) => {
|
Object.keys(formData.value).forEach((key) => {
|
||||||
formData.value[key] = key === 'urgent' ? false : ''
|
if (key === 'urgent') {
|
||||||
|
formData.value[key] = false
|
||||||
|
} else if (key === 'consultationStatus') {
|
||||||
|
formData.value[key] = 0
|
||||||
|
} else {
|
||||||
|
formData.value[key] = key === 'id' || key === 'consultationRequestId' ? null : ''
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
formData.value.consultationId = row.consultationId
|
|
||||||
formData.value.urgent = row.urgent
|
formData.value = {
|
||||||
formData.value.patientName = row.patientName
|
id: row.id,
|
||||||
formData.value.gender = row.gender
|
consultationRequestId: row.consultationRequestId,
|
||||||
formData.value.age = row.age
|
consultationId: row.consultationId,
|
||||||
formData.value.cardNo = row.cardNo
|
patientName: row.patientName,
|
||||||
formData.value.consultationTime = row.consultationTime
|
genderText: row.genderText,
|
||||||
formData.value.invitee = row.invitee
|
age: row.age,
|
||||||
formData.value.applyDept = row.applyDept
|
patientIdentifierNo: row.patientIdentifierNo,
|
||||||
formData.value.applyDoctor = row.applyDoctor
|
applyDept: row.applyDept,
|
||||||
formData.value.applyTime = row.applyTime
|
applyDoctor: row.applyDoctor,
|
||||||
formData.value.history = row.history
|
applyTime: row.applyTime,
|
||||||
formData.value.confirmingPhysician = row.confirmingPhysician
|
consultationDate: row.consultationDate,
|
||||||
formData.value.opinion = row.opinion
|
urgent: row.urgent,
|
||||||
formData.value.confirmDoctor = row.confirmDoctor || ''
|
invitedObject: row.invitedObject,
|
||||||
formData.value.confirmDept = row.confirmDept || ''
|
consultationPurpose: row.consultationPurpose,
|
||||||
formData.value.signDoctor = row.signDoctor || ''
|
provisionalDiagnosis: row.provisionalDiagnosis,
|
||||||
formData.value.signTime = row.signTime || ''
|
confirmingPhysician: row.confirmingPhysician || '',
|
||||||
|
consultationOpinion: '', // 先清空,后面从 opinionList 中获取
|
||||||
|
confirmingPhysicianName: row.confirmingPhysicianName || '',
|
||||||
|
confirmingDeptName: row.confirmingDeptName || '',
|
||||||
|
signature: row.signature || '',
|
||||||
|
signatureDate: row.signatureDate,
|
||||||
|
submittingPhysician: row.submittingPhysician,
|
||||||
|
submittingTime: row.submittingTime,
|
||||||
|
consultationStatus: row.consultationStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从会诊意见列表中获取当前医生的信息
|
||||||
|
if (opinionList.value.length > 0) {
|
||||||
|
const currentPhysicianId = userStore.practitionerId || userStore.user?.practitionerId
|
||||||
|
const myOpinion = opinionList.value.find(op => op.physicianId === currentPhysicianId)
|
||||||
|
|
||||||
|
if (myOpinion) {
|
||||||
|
// 如果当前医生已确认,回显其信息
|
||||||
|
formData.value.confirmingPhysicianName = myOpinion.physicianName
|
||||||
|
formData.value.confirmingDeptName = myOpinion.deptName
|
||||||
|
|
||||||
|
// 回显会诊意见(去掉前缀"科室-医生:")
|
||||||
|
if (myOpinion.opinion) {
|
||||||
|
// 格式:科室-医生:意见内容
|
||||||
|
const opinionText = myOpinion.opinion
|
||||||
|
const colonIndex = opinionText.indexOf(':')
|
||||||
|
if (colonIndex > 0) {
|
||||||
|
// 提取冒号后面的内容
|
||||||
|
formData.value.consultationOpinion = opinionText.substring(colonIndex + 1)
|
||||||
|
} else {
|
||||||
|
formData.value.consultationOpinion = opinionText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myOpinion.isSigned) {
|
||||||
|
formData.value.signature = myOpinion.physicianName
|
||||||
|
formData.value.signatureDate = myOpinion.signatureTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleRowChange = (row) => {
|
const handleRowChange = async (row) => {
|
||||||
currentRow.value = row
|
currentRow.value = row
|
||||||
|
|
||||||
|
// 先加载会诊意见列表
|
||||||
|
if (row) {
|
||||||
|
await loadConsultationOpinions(row.consultationId)
|
||||||
|
} else {
|
||||||
|
opinionList.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 然后应用数据到表单(这样可以使用 opinionList 中的数据)
|
||||||
applyRowToForm(row)
|
applyRowToForm(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleConfirm = () => {
|
// 加载会诊意见列表
|
||||||
|
const loadConsultationOpinions = async (consultationId) => {
|
||||||
|
try {
|
||||||
|
const res = await getConsultationOpinions(consultationId)
|
||||||
|
if (res.code === 200) {
|
||||||
|
opinionList.value = res.data || []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载会诊意见失败', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfirm = async () => {
|
||||||
if (!currentRow.value) {
|
if (!currentRow.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!currentRow.value.confirmed) {
|
|
||||||
if (!formData.value.opinion.trim()) {
|
try {
|
||||||
|
// 如果已确认,则取消确认(使用ConsultationStatusEnum:20=已确认,30=已签名)
|
||||||
|
if (currentRow.value.myInvitedStatus >= 20) {
|
||||||
|
// 已签名不能取消确认
|
||||||
|
if (currentRow.value.myInvitedStatus >= 30) {
|
||||||
|
ElMessage.warning('已签名的会诊无法取消确认')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await ElMessageBox.confirm('确定要取消确认吗?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
const res = await cancelConfirmation(currentRow.value.consultationId)
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success('取消确认成功')
|
||||||
|
await loadData()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '取消确认失败')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 确认会诊
|
||||||
|
if (!formData.value.consultationOpinion.trim()) {
|
||||||
ElMessage.warning('请先填写会诊意见')
|
ElMessage.warning('请先填写会诊意见')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!formData.value.confirmingPhysician.trim()) {
|
|
||||||
ElMessage.warning('请先填写会诊确认参加医师')
|
loading.value = true
|
||||||
return
|
const data = {
|
||||||
|
consultationId: formData.value.consultationId,
|
||||||
|
consultationOpinion: formData.value.consultationOpinion,
|
||||||
|
confirmingPhysician: getDoctorName(), // 自动使用当前医生姓名
|
||||||
|
confirmingDeptName: getDoctorDept() // 自动使用当前科室
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await confirmConsultation(data)
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success('会诊确认成功')
|
||||||
|
await loadData()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '会诊确认失败')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
currentRow.value.confirmed = true
|
} catch (error) {
|
||||||
currentRow.value.confirmingPhysician = formData.value.confirmingPhysician
|
if (error !== 'cancel') {
|
||||||
currentRow.value.opinion = formData.value.opinion
|
console.error('操作失败:', error)
|
||||||
currentRow.value.confirmDoctor = getDoctorName()
|
ElMessage.error('操作失败')
|
||||||
currentRow.value.confirmDept = getDoctorDept()
|
}
|
||||||
formData.value.confirmDoctor = currentRow.value.confirmDoctor
|
} finally {
|
||||||
formData.value.confirmDept = currentRow.value.confirmDept
|
loading.value = false
|
||||||
ElMessage.success('会诊已确认')
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if (currentRow.value.signed) {
|
|
||||||
ElMessage.warning('已签名的会诊无法取消确认')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
currentRow.value.confirmed = false
|
|
||||||
currentRow.value.confirmDoctor = ''
|
|
||||||
currentRow.value.confirmDept = ''
|
|
||||||
formData.value.confirmDoctor = ''
|
|
||||||
formData.value.confirmDept = ''
|
|
||||||
ElMessage.success('已取消确认')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSign = () => {
|
const handleSign = async () => {
|
||||||
if (!currentRow.value) {
|
if (!currentRow.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!currentRow.value.confirmed) {
|
|
||||||
ElMessage.warning('请先确认会诊申请')
|
// 检查当前医生是否已确认(使用ConsultationStatusEnum:20=已确认,30=已签名)
|
||||||
|
if (!currentRow.value.myInvitedStatus || currentRow.value.myInvitedStatus < 20) {
|
||||||
|
ElMessage.warning('请先确认会诊后再签名')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
currentRow.value.signed = true
|
|
||||||
currentRow.value.signDoctor = getDoctorName()
|
// 检查是否已签名
|
||||||
currentRow.value.signTime = formatDateTime()
|
if (currentRow.value.myInvitedStatus >= 30) {
|
||||||
formData.value.signDoctor = currentRow.value.signDoctor
|
ElMessage.warning('您已经签名过了')
|
||||||
formData.value.signTime = currentRow.value.signTime
|
return
|
||||||
ElMessage.success('签名完成')
|
}
|
||||||
|
|
||||||
|
// 🎯 移除整体状态检查:只要当前医生已确认就可以签名,不需要等待所有医生都确认
|
||||||
|
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm('确定要签名吗?签名后将无法修改会诊意见。', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
const res = await signConsultation(currentRow.value.consultationId)
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success('签名成功')
|
||||||
|
await loadData()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '签名失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error !== 'cancel') {
|
||||||
|
console.error('签名失败:', error)
|
||||||
|
ElMessage.error('签名失败')
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePrint = () => {
|
const handlePrint = () => {
|
||||||
@@ -343,12 +506,50 @@ const handlePrint = () => {
|
|||||||
window.print()
|
window.print()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleRefresh = () => {
|
const handleRefresh = async () => {
|
||||||
tableData.value = buildMockRows()
|
await loadData()
|
||||||
currentRow.value = null
|
|
||||||
applyRowToForm(null)
|
|
||||||
ElMessage.success('已刷新')
|
ElMessage.success('已刷新')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadData = async () => {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const res = await getPendingConfirmationList()
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
tableData.value = res.data || []
|
||||||
|
|
||||||
|
// 如果当前选中的行还在列表中,重新选中
|
||||||
|
if (currentRow.value) {
|
||||||
|
const updatedRow = tableData.value.find(
|
||||||
|
item => item.consultationId === currentRow.value.consultationId
|
||||||
|
)
|
||||||
|
if (updatedRow) {
|
||||||
|
currentRow.value = updatedRow
|
||||||
|
// 重新加载会诊意见
|
||||||
|
await loadConsultationOpinions(updatedRow.consultationId)
|
||||||
|
// 然后应用数据到表单
|
||||||
|
applyRowToForm(updatedRow)
|
||||||
|
} else {
|
||||||
|
currentRow.value = null
|
||||||
|
applyRowToForm(null)
|
||||||
|
opinionList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '加载数据失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载数据失败:', error)
|
||||||
|
ElMessage.error('加载数据失败')
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadData()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -390,13 +591,46 @@ const handleRefresh = () => {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.opinions-container {
|
||||||
|
width: 100%;
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #f9fafb;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opinion-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.physician-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opinion-content {
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opinion-footer {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-timeline {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="right-actions">
|
<div class="right-actions">
|
||||||
<el-button type="danger" @click="handleComplete" :disabled="!selectedRow || selectedRow.consultationStatus !== 30">结束</el-button>
|
<el-button type="danger" @click="handleComplete" :disabled="!selectedRow || selectedRow.consultationStatus !== 30">结束</el-button>
|
||||||
<el-button type="success" @click="handleSave">保存</el-button>
|
<el-button type="success" @click="handleSave" :disabled="selectedRow && selectedRow.consultationStatus > 0">保存</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -62,15 +62,19 @@
|
|||||||
取消提交
|
取消提交
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
<!-- 已确认状态:显示待签名按钮 -->
|
||||||
|
<template v-else-if="row.consultationStatus === 20">
|
||||||
|
<el-button type="success" size="small" @click="handleView(row)">
|
||||||
|
待签名
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
<!-- 已签名状态:显示结束按钮 -->
|
<!-- 已签名状态:显示结束按钮 -->
|
||||||
<template v-else-if="row.consultationStatus === 30">
|
<template v-else-if="row.consultationStatus === 30">
|
||||||
<!-- <el-button type="danger" size="small" @click="handleCompleteRow(row)">-->
|
|
||||||
<!-- 结束-->
|
|
||||||
<!-- </el-button>-->
|
|
||||||
<el-button
|
<el-button
|
||||||
type="danger"
|
type="danger"
|
||||||
size="small"
|
size="small"
|
||||||
@click="handleCompleteRow(row)" style="background-color: #f56c6c; border-color: #f56c6c;"
|
@click="handleCompleteRow(row)"
|
||||||
|
style="background-color: #f56c6c; border-color: #f56c6c;"
|
||||||
>
|
>
|
||||||
结束
|
结束
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -234,39 +238,37 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-row :gutter="20">
|
<!-- 🎯 新增:参与医生列表(表格形式) -->
|
||||||
<el-col :span="8">
|
<el-form-item label="参与医生签名:" v-if="participatingPhysicians.length > 0">
|
||||||
<el-form-item label="所属医生:">
|
<el-table
|
||||||
<el-input v-model="formData.attendingPhysician" placeholder="会诊后填写" disabled />
|
:data="participatingPhysicians"
|
||||||
</el-form-item>
|
border
|
||||||
</el-col>
|
stripe
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="代表科室:">
|
|
||||||
<el-input v-model="formData.representDepartment" placeholder="会诊后填写" disabled />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="签名医生:">
|
|
||||||
<el-input v-model="formData.signPhysician" placeholder="会诊后填写" disabled />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item label="签名时间:">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="formData.signTime"
|
|
||||||
type="datetime"
|
|
||||||
placeholder="年/月/日 --:--"
|
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
format="YYYY/MM/DD HH:mm"
|
max-height="300"
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
>
|
||||||
disabled
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
/>
|
<el-table-column prop="deptName" label="科室" width="120" align="center" />
|
||||||
|
<el-table-column prop="physicianName" label="医生" width="100" align="center" />
|
||||||
|
<el-table-column prop="confirmTime" label="确认时间" width="160" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ formatDateTime(row.confirmTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="signatureTime" label="签名时间" width="160" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ formatDateTime(row.signatureTime) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="状态" width="80" align="center">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag v-if="row.invitedStatus >= 3" type="success">已签名</el-tag>
|
||||||
|
<el-tag v-else-if="row.invitedStatus >= 1" type="warning">已确认</el-tag>
|
||||||
|
<el-tag v-else type="info">待确认</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -289,7 +291,7 @@
|
|||||||
清空
|
清空
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 科室医生树(带复选框) -->
|
<!-- 科室医生树(带复选框) -->
|
||||||
<div class="invite-section">
|
<div class="invite-section">
|
||||||
<div class="section-label">选择会诊科室和医生</div>
|
<div class="section-label">选择会诊科室和医生</div>
|
||||||
@@ -323,7 +325,7 @@
|
|||||||
<div v-show="expandedDepts.includes(dept.id)" class="physicians-list">
|
<div v-show="expandedDepts.includes(dept.id)" class="physicians-list">
|
||||||
<div
|
<div
|
||||||
v-for="physician in dept.children"
|
v-for="physician in dept.children"
|
||||||
:key="physician.id"
|
:key="physician.id"
|
||||||
class="physician-item"
|
class="physician-item"
|
||||||
>
|
>
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
@@ -332,11 +334,11 @@
|
|||||||
>
|
>
|
||||||
{{ physician.label }}
|
{{ physician.label }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!dept.children || dept.children.length === 0" class="no-physicians">
|
<div v-if="!dept.children || dept.children.length === 0" class="no-physicians">
|
||||||
该科室暂无医生
|
该科室暂无医生
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
@@ -432,6 +434,9 @@ const expandedDepts = ref([]);
|
|||||||
// 选中的医生列表(用于显示和提交)
|
// 选中的医生列表(用于显示和提交)
|
||||||
const selectedPhysiciansList = ref([]);
|
const selectedPhysiciansList = ref([]);
|
||||||
|
|
||||||
|
// 🎯 新增:参与医生列表(用于显示已确认/已签名的医生)
|
||||||
|
const participatingPhysicians = ref([]);
|
||||||
|
|
||||||
// 会诊列表
|
// 会诊列表
|
||||||
const consultationList = ref([]);
|
const consultationList = ref([]);
|
||||||
|
|
||||||
@@ -716,6 +721,14 @@ const handleRowClick = (row) => {
|
|||||||
isUrgent: row.consultationUrgency === '2', // 2=紧急
|
isUrgent: row.consultationUrgency === '2', // 2=紧急
|
||||||
consultationPurpose: row.consultationPurpose,
|
consultationPurpose: row.consultationPurpose,
|
||||||
createTime: row.consultationRequestDate || row.createTime, // 申请时间
|
createTime: row.consultationRequestDate || row.createTime, // 申请时间
|
||||||
|
|
||||||
|
// 🎯 填充会诊记录字段(如果会诊已完成或已签名)
|
||||||
|
invitedPhysiciansText: row.invitedPhysiciansText || '',
|
||||||
|
consultationOpinion: row.consultationOpinion || '',
|
||||||
|
attendingPhysician: row.attendingPhysician || '',
|
||||||
|
representDepartment: row.representDepartment || '',
|
||||||
|
signPhysician: row.signPhysician || '',
|
||||||
|
signTime: row.signTime || null,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('填充后的表单数据:', formData);
|
console.log('填充后的表单数据:', formData);
|
||||||
@@ -730,8 +743,22 @@ const handleRowClick = (row) => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
console.log('填充的医生列表:', selectedPhysiciansList.value);
|
console.log('填充的医生列表:', selectedPhysiciansList.value);
|
||||||
|
|
||||||
|
// 🎯 填充参与医生列表(显示确认和签名状态)
|
||||||
|
participatingPhysicians.value = row.invitedList.map(inv => ({
|
||||||
|
physicianId: inv.physicianId,
|
||||||
|
physicianName: inv.physicianName,
|
||||||
|
deptId: inv.deptId,
|
||||||
|
deptName: inv.deptName,
|
||||||
|
invitedStatus: inv.invitedStatus || 0,
|
||||||
|
confirmTime: inv.confirmTime || null,
|
||||||
|
signatureTime: inv.signatureTime || null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.log('参与医生列表:', participatingPhysicians.value);
|
||||||
} else {
|
} else {
|
||||||
selectedPhysiciansList.value = [];
|
selectedPhysiciansList.value = [];
|
||||||
|
participatingPhysicians.value = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -781,6 +808,7 @@ const handleNew = () => {
|
|||||||
|
|
||||||
// 清空选中状态
|
// 清空选中状态
|
||||||
selectedPhysiciansList.value = [];
|
selectedPhysiciansList.value = [];
|
||||||
|
participatingPhysicians.value = [];
|
||||||
|
|
||||||
// 加载主诊断
|
// 加载主诊断
|
||||||
loadMainDiagnosis();
|
loadMainDiagnosis();
|
||||||
@@ -1090,6 +1118,19 @@ defineExpose({
|
|||||||
fetchConsultationList,
|
fetchConsultationList,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 🎯 格式化日期时间
|
||||||
|
const formatDateTime = (dateTime) => {
|
||||||
|
if (!dateTime) return '-';
|
||||||
|
const date = new Date(dateTime);
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||||
|
return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
};
|
||||||
|
|
||||||
// 监听 activeTab 变化
|
// 监听 activeTab 变化
|
||||||
watch(
|
watch(
|
||||||
() => props.activeTab,
|
() => props.activeTab,
|
||||||
@@ -1302,11 +1343,11 @@ onMounted(() => {
|
|||||||
transition: transform 0.3s;
|
transition: transform 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dept-name {
|
.dept-name {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected-badge {
|
.selected-badge {
|
||||||
@@ -1333,26 +1374,26 @@ onMounted(() => {
|
|||||||
|
|
||||||
.physician-item {
|
.physician-item {
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
|
|
||||||
|
:deep(.el-checkbox) {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
:deep(.el-checkbox) {
|
.el-checkbox__label {
|
||||||
width: 100%;
|
font-size: 13px;
|
||||||
|
|
||||||
.el-checkbox__label {
|
|
||||||
font-size: 13px;
|
|
||||||
color: #606266;
|
color: #606266;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-checked .el-checkbox__label {
|
&.is-checked .el-checkbox__label {
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-physicians {
|
.no-physicians {
|
||||||
color: #909399;
|
color: #909399;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
package-lock.json
generated
23
package-lock.json
generated
@@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "his",
|
"name": "jkhl",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.13.2"
|
"axios": "^1.13.2",
|
||||||
|
"json-bigint": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/asynckit": {
|
"node_modules/asynckit": {
|
||||||
@@ -25,6 +26,15 @@
|
|||||||
"proxy-from-env": "^1.1.0"
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bignumber.js": {
|
||||||
|
"version": "9.3.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.3.1.tgz",
|
||||||
|
"integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/call-bind-apply-helpers": {
|
"node_modules/call-bind-apply-helpers": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||||
@@ -251,6 +261,15 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/json-bigint": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/json-bigint/-/json-bigint-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bignumber.js": "^9.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/math-intrinsics": {
|
"node_modules/math-intrinsics": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.13.2"
|
"axios": "^1.13.2",
|
||||||
|
"json-bigint": "^1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user