95-门诊医生站开立会诊申请单界面PRD_2026-01-15,全部功能。
This commit is contained in:
42
consultation_invited.sql
Normal file
42
consultation_invited.sql
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
-- 会诊邀请对象表
|
||||||
|
CREATE TABLE hisdev.consultation_invited (
|
||||||
|
id BIGINT NOT NULL PRIMARY KEY,
|
||||||
|
consultation_request_id BIGINT NOT NULL,
|
||||||
|
invited_department_id BIGINT,
|
||||||
|
invited_department_name VARCHAR(100),
|
||||||
|
invited_physician_id BIGINT,
|
||||||
|
invited_physician_name VARCHAR(50),
|
||||||
|
invited_status SMALLINT DEFAULT 0,
|
||||||
|
confirm_time TIMESTAMP,
|
||||||
|
confirm_opinion TEXT,
|
||||||
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
create_by VARCHAR(64),
|
||||||
|
update_by VARCHAR(64),
|
||||||
|
tenant_id BIGINT,
|
||||||
|
is_deleted SMALLINT DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 添加注释
|
||||||
|
COMMENT ON TABLE hisdev.consultation_invited IS '会诊邀请对象表';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.id IS '主键ID';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.consultation_request_id IS '会诊申请ID(外键)';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.invited_department_id IS '邀请科室ID';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.invited_department_name IS '邀请科室名称';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.invited_physician_id IS '邀请医生ID';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.invited_physician_name IS '邀请医生姓名';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.invited_status IS '邀请状态(0-待确认,1-已确认,2-已拒绝)';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.confirm_time IS '确认时间';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.confirm_opinion IS '确认意见';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.create_time IS '创建时间';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.update_time IS '更新时间';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.create_by IS '创建人';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.update_by IS '更新人';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.tenant_id IS '租户ID';
|
||||||
|
COMMENT ON COLUMN hisdev.consultation_invited.is_deleted IS '删除标识(0-未删除,1-已删除)';
|
||||||
|
|
||||||
|
-- 创建索引
|
||||||
|
CREATE INDEX idx_consultation_request_id ON hisdev.consultation_invited(consultation_request_id);
|
||||||
|
CREATE INDEX idx_invited_physician_id ON hisdev.consultation_invited(invited_physician_id);
|
||||||
|
CREATE INDEX idx_tenant_id ON hisdev.consultation_invited(tenant_id);
|
||||||
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package com.openhis.web.consultation.appservice;
|
||||||
|
|
||||||
|
import com.openhis.web.consultation.dto.ConsultationActivityDto;
|
||||||
|
import com.openhis.web.consultation.dto.ConsultationRequestDto;
|
||||||
|
import com.openhis.web.consultation.dto.DepartmentTreeDto;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊管理AppService接口
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-01-29
|
||||||
|
*/
|
||||||
|
public interface IConsultationAppService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊列表
|
||||||
|
*
|
||||||
|
* @param encounterId 就诊ID(可选,如果为null则查询当前医生的所有会诊申请)
|
||||||
|
* @return 会诊列表
|
||||||
|
*/
|
||||||
|
List<ConsultationRequestDto> getConsultationList(Long encounterId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存会诊申请
|
||||||
|
*
|
||||||
|
* @param dto 会诊申请DTO
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
Boolean saveConsultation(ConsultationRequestDto dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交会诊申请
|
||||||
|
*
|
||||||
|
* @param consultationId 会诊申请单号
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
Boolean submitConsultation(String consultationId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 作废会诊申请
|
||||||
|
*
|
||||||
|
* @param consultationId 会诊申请单号
|
||||||
|
* @param cancelReason 作废原因
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
Boolean cancelConsultation(String consultationId, String cancelReason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束会诊申请
|
||||||
|
*
|
||||||
|
* @param consultationId 会诊申请单号
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
Boolean completeConsultation(String consultationId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取科室医生树
|
||||||
|
*
|
||||||
|
* @return 科室医生树
|
||||||
|
*/
|
||||||
|
List<DepartmentTreeDto> getDepartmentTree();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主诊断
|
||||||
|
*
|
||||||
|
* @param encounterId 就诊ID
|
||||||
|
* @return 主诊断信息
|
||||||
|
*/
|
||||||
|
Map<String, String> getMainDiagnosis(Long encounterId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取我的会诊邀请列表(被邀请的医生查看)
|
||||||
|
*
|
||||||
|
* @return 会诊邀请列表
|
||||||
|
*/
|
||||||
|
List<ConsultationRequestDto> getMyInvitations();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有会诊项目及价格
|
||||||
|
*
|
||||||
|
* @return 会诊项目列表
|
||||||
|
*/
|
||||||
|
List<ConsultationActivityDto> getConsultationActivities();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,967 @@
|
|||||||
|
package com.openhis.web.consultation.appservice.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.core.common.utils.SecurityUtils;
|
||||||
|
import com.openhis.administration.domain.Encounter;
|
||||||
|
import com.openhis.administration.domain.EncounterDiagnosis;
|
||||||
|
import com.openhis.administration.domain.Organization;
|
||||||
|
import com.openhis.administration.domain.Patient;
|
||||||
|
import com.openhis.administration.domain.Practitioner;
|
||||||
|
import com.openhis.administration.mapper.EncounterDiagnosisMapper;
|
||||||
|
import com.openhis.administration.mapper.EncounterMapper;
|
||||||
|
import com.openhis.administration.mapper.OrganizationMapper;
|
||||||
|
import com.openhis.administration.mapper.PatientMapper;
|
||||||
|
import com.openhis.administration.mapper.PractitionerMapper;
|
||||||
|
import com.openhis.clinical.domain.Condition;
|
||||||
|
import com.openhis.clinical.mapper.ConditionMapper;
|
||||||
|
import com.openhis.workflow.domain.ServiceRequest;
|
||||||
|
import com.openhis.workflow.service.IServiceRequestService;
|
||||||
|
import com.openhis.common.enums.RequestStatus;
|
||||||
|
import com.openhis.common.enums.GenerateSource;
|
||||||
|
import com.openhis.common.enums.ItemType;
|
||||||
|
import com.core.common.utils.AssignSeqUtil;
|
||||||
|
import com.openhis.common.enums.AssignSeqEnum;
|
||||||
|
import com.openhis.web.consultation.appservice.IConsultationAppService;
|
||||||
|
import com.openhis.web.consultation.dto.ConsultationActivityDto;
|
||||||
|
import com.openhis.web.consultation.dto.ConsultationRequestDto;
|
||||||
|
import com.openhis.web.consultation.dto.DepartmentTreeDto;
|
||||||
|
import com.openhis.web.consultation.dto.InvitedObjectDto;
|
||||||
|
import com.openhis.web.consultation.dto.PhysicianNodeDto;
|
||||||
|
import com.openhis.web.consultation.mapper.ConsultationRequestMapper;
|
||||||
|
import com.openhis.web.consultation.mapper.ConsultationInvitedMapper;
|
||||||
|
import com.openhis.web.consultation.domain.ConsultationRequest;
|
||||||
|
import com.openhis.web.consultation.domain.ConsultationInvited;
|
||||||
|
import com.openhis.web.consultation.enums.ConsultationStatusEnum;
|
||||||
|
import com.openhis.web.consultation.enums.InvitedStatusEnum;
|
||||||
|
import com.openhis.web.consultation.enums.ConsultationUrgencyEnum;
|
||||||
|
import com.openhis.workflow.domain.ActivityDefinition;
|
||||||
|
import com.openhis.workflow.mapper.ActivityDefinitionMapper;
|
||||||
|
import com.openhis.administration.domain.ChargeItemDefinition;
|
||||||
|
import com.openhis.administration.mapper.ChargeItemDefinitionMapper;
|
||||||
|
import com.openhis.administration.domain.ChargeItem;
|
||||||
|
import com.openhis.administration.service.IChargeItemService;
|
||||||
|
import com.openhis.common.enums.ChargeItemStatus;
|
||||||
|
import com.openhis.web.doctorstation.mapper.DoctorStationAdviceAppMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊管理AppService实现类
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-01-29
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class ConsultationAppServiceImpl implements IConsultationAppService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ConsultationRequestMapper consultationRequestMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ConsultationInvitedMapper consultationInvitedMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private EncounterMapper encounterMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PatientMapper patientMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ConditionMapper conditionMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private OrganizationMapper organizationMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PractitionerMapper practitionerMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private EncounterDiagnosisMapper encounterDiagnosisMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IServiceRequestService iServiceRequestService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AssignSeqUtil assignSeqUtil;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ActivityDefinitionMapper activityDefinitionMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ChargeItemDefinitionMapper chargeItemDefinitionMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IChargeItemService iChargeItemService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DoctorStationAdviceAppMapper doctorStationAdviceAppMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于生成唯一序列号的计数器
|
||||||
|
* 每秒重置,范围 0000-9999
|
||||||
|
*/
|
||||||
|
private static final AtomicInteger SEQUENCE = new AtomicInteger(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 记录上一次生成ID的时间(秒级)
|
||||||
|
*/
|
||||||
|
private static volatile long lastSecond = 0L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ConsultationRequestDto> getConsultationList(Long encounterId) {
|
||||||
|
// 查询会诊列表
|
||||||
|
LambdaQueryWrapper<ConsultationRequest> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
|
||||||
|
|
||||||
|
// 根据就诊ID,查询该患者的会诊申请
|
||||||
|
wrapper.eq(ConsultationRequest::getEncounterId, encounterId);
|
||||||
|
wrapper.orderByDesc(ConsultationRequest::getCreateTime);
|
||||||
|
|
||||||
|
List<ConsultationRequest> list = consultationRequestMapper.selectList(wrapper);
|
||||||
|
// 转换为DTO
|
||||||
|
return list.stream().map(this::convertToDto).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean saveConsultation(ConsultationRequestDto dto) {
|
||||||
|
try {
|
||||||
|
// 判断是新增还是更新
|
||||||
|
boolean isUpdate = (dto.getId() != null);
|
||||||
|
ConsultationRequest entity;
|
||||||
|
|
||||||
|
if (isUpdate) {
|
||||||
|
// 更新:查询现有记录
|
||||||
|
entity = consultationRequestMapper.selectById(dto.getId());
|
||||||
|
if (entity == null) {
|
||||||
|
throw new RuntimeException("会诊申请记录不存在,ID: " + dto.getId());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 新增:创建新记录
|
||||||
|
entity = new ConsultationRequest();
|
||||||
|
entity.setConsultationId(generateConsultationId());
|
||||||
|
entity.setTenantId(SecurityUtils.getLoginUser().getTenantId().longValue());
|
||||||
|
entity.setConsultationRequestDate(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制基本属性(现在字段名已统一,可以直接复制)
|
||||||
|
BeanUtils.copyProperties(dto, entity, "id", "consultationId", "invitedList", "submitFlag", "provisionalDiagnosis", "consultationRequestDate");
|
||||||
|
|
||||||
|
// 如果前端没有传递申请医生ID,使用当前登录用户
|
||||||
|
if (entity.getRequestingPhysicianId() == null) {
|
||||||
|
entity.setRequestingPhysicianId(SecurityUtils.getLoginUser().getPractitionerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置邀请对象文本(拼接所有医生名称)
|
||||||
|
if (dto.getInvitedList() != null && !dto.getInvitedList().isEmpty()) {
|
||||||
|
String invitedObjectText = dto.getInvitedList().stream()
|
||||||
|
.map(InvitedObjectDto::getPhysicianName)
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
entity.setInvitedObject(invitedObjectText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理门诊诊断:如果前端没有传递,自动从数据库获取
|
||||||
|
if (!StringUtils.hasText(dto.getProvisionalDiagnosis()) && dto.getEncounterId() != null) {
|
||||||
|
String diagnosis = getPatientDiagnosis(dto.getEncounterId());
|
||||||
|
if (StringUtils.hasText(diagnosis)) {
|
||||||
|
entity.setProvisionalDiagnosis(diagnosis);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entity.setProvisionalDiagnosis(dto.getProvisionalDiagnosis());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置会诊状态(使用枚举)
|
||||||
|
if (Boolean.TRUE.equals(dto.getSubmitFlag())) {
|
||||||
|
entity.setConsultationStatus(ConsultationStatusEnum.SUBMITTED.getCode());
|
||||||
|
entity.setConfirmingPhysician(SecurityUtils.getLoginUser().getUser().getNickName());
|
||||||
|
entity.setConfirmingPhysicianId(SecurityUtils.getLoginUser().getPractitionerId());
|
||||||
|
entity.setConfirmingDate(new Date());
|
||||||
|
} else {
|
||||||
|
entity.setConsultationStatus(ConsultationStatusEnum.NEW.getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存或更新主表
|
||||||
|
if (isUpdate) {
|
||||||
|
consultationRequestMapper.updateById(entity);
|
||||||
|
|
||||||
|
// 删除旧的邀请对象
|
||||||
|
LambdaQueryWrapper<ConsultationInvited> deleteWrapper = new LambdaQueryWrapper<>();
|
||||||
|
deleteWrapper.eq(ConsultationInvited::getConsultationRequestId, entity.getId());
|
||||||
|
consultationInvitedMapper.delete(deleteWrapper);
|
||||||
|
|
||||||
|
// 更新门诊医嘱表
|
||||||
|
if (entity.getOrderId() != null) {
|
||||||
|
updateConsultationServiceRequest(entity);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
consultationRequestMapper.insert(entity);
|
||||||
|
|
||||||
|
// 保存到门诊医嘱表
|
||||||
|
saveConsultationServiceRequest(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存邀请对象到关联表
|
||||||
|
if (dto.getInvitedList() != null && !dto.getInvitedList().isEmpty()) {
|
||||||
|
for (InvitedObjectDto invitedDto : dto.getInvitedList()) {
|
||||||
|
ConsultationInvited invited = new ConsultationInvited();
|
||||||
|
invited.setConsultationRequestId(entity.getId());
|
||||||
|
invited.setInvitedDepartmentId(invitedDto.getDeptId());
|
||||||
|
invited.setInvitedDepartmentName(invitedDto.getDeptName());
|
||||||
|
invited.setInvitedPhysicianId(invitedDto.getPhysicianId());
|
||||||
|
invited.setInvitedPhysicianName(invitedDto.getPhysicianName());
|
||||||
|
invited.setInvitedStatus(InvitedStatusEnum.PENDING.getCode());
|
||||||
|
invited.setTenantId(entity.getTenantId());
|
||||||
|
|
||||||
|
consultationInvitedMapper.insert(invited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("保存会诊申请失败", e);
|
||||||
|
throw new RuntimeException("保存会诊申请失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean submitConsultation(String consultationId) {
|
||||||
|
try {
|
||||||
|
if (!StringUtils.hasText(consultationId)) {
|
||||||
|
throw new IllegalArgumentException("会诊申请单号不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<ConsultationRequest> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(ConsultationRequest::getConsultationId, consultationId);
|
||||||
|
|
||||||
|
ConsultationRequest entity = consultationRequestMapper.selectOne(wrapper);
|
||||||
|
if (entity == null) {
|
||||||
|
throw new IllegalArgumentException("会诊申请不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有新开状态才能提交
|
||||||
|
if (!ConsultationStatusEnum.NEW.getCode().equals(entity.getConsultationStatus())) {
|
||||||
|
throw new IllegalArgumentException("只有新开状态的会诊申请才能提交");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新状态为已提交
|
||||||
|
entity.setConsultationStatus(ConsultationStatusEnum.SUBMITTED.getCode());
|
||||||
|
|
||||||
|
// 设置提交会诊的医生信息
|
||||||
|
entity.setConfirmingPhysician(SecurityUtils.getLoginUser().getUser().getNickName());
|
||||||
|
entity.setConfirmingPhysicianId(SecurityUtils.getLoginUser().getPractitionerId());
|
||||||
|
entity.setConfirmingDate(new Date());
|
||||||
|
|
||||||
|
consultationRequestMapper.updateById(entity);
|
||||||
|
|
||||||
|
// 新增:更新门诊医嘱表状态为已提交
|
||||||
|
updateServiceRequestStatus(entity.getOrderId(), RequestStatus.ACTIVE.getValue());
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("提交会诊申请失败", e);
|
||||||
|
throw new RuntimeException("提交会诊申请失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean cancelConsultation(String consultationId, String cancelReason) {
|
||||||
|
try {
|
||||||
|
if (!StringUtils.hasText(consultationId)) {
|
||||||
|
throw new IllegalArgumentException("会诊申请单号不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<ConsultationRequest> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(ConsultationRequest::getConsultationId, consultationId);
|
||||||
|
|
||||||
|
ConsultationRequest entity = consultationRequestMapper.selectOne(wrapper);
|
||||||
|
if (entity == null) {
|
||||||
|
throw new IllegalArgumentException("会诊申请不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是"取消提交"还是"作废"
|
||||||
|
if ("取消提交".equals(cancelReason) && ConsultationStatusEnum.SUBMITTED.getCode().equals(entity.getConsultationStatus())) {
|
||||||
|
// 取消提交:将状态从"已提交"改回"新开"
|
||||||
|
entity.setConsultationStatus(ConsultationStatusEnum.NEW.getCode());
|
||||||
|
entity.setConfirmingPhysician(null);
|
||||||
|
entity.setConfirmingPhysicianId(null);
|
||||||
|
entity.setConfirmingDate(null);
|
||||||
|
consultationRequestMapper.updateById(entity);
|
||||||
|
|
||||||
|
// 更新门诊医嘱表状态为新开
|
||||||
|
updateServiceRequestStatus(entity.getOrderId(), RequestStatus.DRAFT.getValue());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 作废:将状态改为"已取消"
|
||||||
|
entity.setConsultationStatus(ConsultationStatusEnum.CANCELLED.getCode());
|
||||||
|
entity.setCancelReason(cancelReason);
|
||||||
|
entity.setCancelNatureDate(new Date());
|
||||||
|
consultationRequestMapper.updateById(entity);
|
||||||
|
|
||||||
|
// 更新门诊医嘱表状态为已作废
|
||||||
|
updateServiceRequestStatus(entity.getOrderId(), RequestStatus.CANCELLED.getValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("操作失败", e);
|
||||||
|
throw new RuntimeException("操作失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Boolean completeConsultation(String consultationId) {
|
||||||
|
try {
|
||||||
|
if (!StringUtils.hasText(consultationId)) {
|
||||||
|
throw new IllegalArgumentException("会诊申请单号不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<ConsultationRequest> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(ConsultationRequest::getConsultationId, consultationId);
|
||||||
|
|
||||||
|
ConsultationRequest entity = consultationRequestMapper.selectOne(wrapper);
|
||||||
|
if (entity == null) {
|
||||||
|
throw new IllegalArgumentException("会诊申请不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新状态为已完成
|
||||||
|
entity.setConsultationStatus(ConsultationStatusEnum.COMPLETED.getCode());
|
||||||
|
consultationRequestMapper.updateById(entity);
|
||||||
|
|
||||||
|
// 🎯 新增:更新门诊医嘱表状态为已完成
|
||||||
|
updateServiceRequestStatus(entity.getOrderId(), RequestStatus.COMPLETED.getValue());
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("结束会诊申请失败", e);
|
||||||
|
throw new RuntimeException("结束会诊申请失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DepartmentTreeDto> getDepartmentTree() {
|
||||||
|
try {
|
||||||
|
// 查询所有科室
|
||||||
|
LambdaQueryWrapper<Organization> deptWrapper = new LambdaQueryWrapper<>();
|
||||||
|
deptWrapper.eq(Organization::getDeleteFlag, "0")
|
||||||
|
.orderByAsc(Organization::getName);
|
||||||
|
List<Organization> deptList = organizationMapper.selectList(deptWrapper);
|
||||||
|
|
||||||
|
|
||||||
|
// 查询所有医生
|
||||||
|
LambdaQueryWrapper<Practitioner> practitionerWrapper = new LambdaQueryWrapper<>();
|
||||||
|
practitionerWrapper.eq(Practitioner::getDeleteFlag, "0")
|
||||||
|
.orderByAsc(Practitioner::getName);
|
||||||
|
List<Practitioner> practitionerList = practitionerMapper.selectList(practitionerWrapper);
|
||||||
|
|
||||||
|
|
||||||
|
// 按科室分组医生
|
||||||
|
Map<Long, List<Practitioner>> practitionerMap = practitionerList.stream()
|
||||||
|
.filter(p -> p.getOrgId() != null)
|
||||||
|
.collect(Collectors.groupingBy(Practitioner::getOrgId));
|
||||||
|
|
||||||
|
// 构建树形结构
|
||||||
|
List<DepartmentTreeDto> treeList = new ArrayList<>();
|
||||||
|
for (Organization dept : deptList) {
|
||||||
|
DepartmentTreeDto treeDto = new DepartmentTreeDto();
|
||||||
|
treeDto.setId(dept.getId());
|
||||||
|
treeDto.setLabel(dept.getName());
|
||||||
|
|
||||||
|
// 添加该科室的医生
|
||||||
|
List<Practitioner> physicians = practitionerMap.get(dept.getId());
|
||||||
|
if (physicians != null && !physicians.isEmpty()) {
|
||||||
|
List<PhysicianNodeDto> children = physicians.stream()
|
||||||
|
.map(p -> {
|
||||||
|
PhysicianNodeDto node = new PhysicianNodeDto();
|
||||||
|
node.setId(p.getId());
|
||||||
|
node.setLabel(p.getName());
|
||||||
|
return node;
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
treeDto.setChildren(children);
|
||||||
|
} else {
|
||||||
|
treeDto.setChildren(new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
treeList.add(treeDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return treeList;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取科室医生树失败", e);
|
||||||
|
throw new RuntimeException("获取科室医生树失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getMainDiagnosis(Long encounterId) {
|
||||||
|
Map<String, String> result = new HashMap<>();
|
||||||
|
|
||||||
|
if (encounterId == null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String diagnosis = getPatientDiagnosis(encounterId);
|
||||||
|
if (StringUtils.hasText(diagnosis)) {
|
||||||
|
result.put("diagnosis", diagnosis);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取主诊断失败", e);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取患者诊断信息
|
||||||
|
*
|
||||||
|
* @param encounterId 就诊ID
|
||||||
|
* @return 诊断信息字符串
|
||||||
|
*/
|
||||||
|
private String getPatientDiagnosis(Long encounterId) {
|
||||||
|
try {
|
||||||
|
// 查询该就诊的所有诊断,优先查询主诊断
|
||||||
|
LambdaQueryWrapper<EncounterDiagnosis> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(EncounterDiagnosis::getEncounterId, encounterId)
|
||||||
|
.orderByDesc(EncounterDiagnosis::getMaindiseFlag) // 主诊断排在前面
|
||||||
|
.orderByAsc(EncounterDiagnosis::getDiagSrtNo) // 按诊断排序号排序
|
||||||
|
.orderByDesc(EncounterDiagnosis::getCreateTime); // 按创建时间倒序
|
||||||
|
|
||||||
|
List<EncounterDiagnosis> diagnosisList = encounterDiagnosisMapper.selectList(wrapper);
|
||||||
|
|
||||||
|
if (diagnosisList == null || diagnosisList.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 使用 LinkedHashSet 去重,保持顺序
|
||||||
|
LinkedHashSet<String> diagnosisSet = new LinkedHashSet<>();
|
||||||
|
int mainDiagnosisCount = 0;
|
||||||
|
|
||||||
|
for (EncounterDiagnosis ed : diagnosisList) {
|
||||||
|
// 优先使用 name 字段,如果没有则使用 diagnosisDesc
|
||||||
|
String diagName = StringUtils.hasText(ed.getName()) ? ed.getName() : ed.getDiagnosisDesc();
|
||||||
|
|
||||||
|
if (StringUtils.hasText(diagName)) {
|
||||||
|
// 构建诊断文本
|
||||||
|
StringBuilder itemBuilder = new StringBuilder();
|
||||||
|
itemBuilder.append(diagName);
|
||||||
|
|
||||||
|
// 如果有诊断描述且与名称不同,添加到括号中
|
||||||
|
if (StringUtils.hasText(ed.getDiagnosisDesc()) &&
|
||||||
|
!ed.getDiagnosisDesc().equals(diagName)) {
|
||||||
|
itemBuilder.append("(").append(ed.getDiagnosisDesc()).append(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标记主诊断
|
||||||
|
if (ed.getMaindiseFlag() != null && ed.getMaindiseFlag() == 1) {
|
||||||
|
itemBuilder.append("[主]");
|
||||||
|
mainDiagnosisCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加到集合(自动去重)
|
||||||
|
diagnosisSet.add(itemBuilder.toString());
|
||||||
|
|
||||||
|
// 限制最多显示 10 个诊断(包括主诊断)
|
||||||
|
if (diagnosisSet.size() >= 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拼接诊断信息
|
||||||
|
String result = String.join(";", diagnosisSet);
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取患者诊断信息失败,encounterId: {}", encounterId, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ConsultationRequestDto> getMyInvitations() {
|
||||||
|
try {
|
||||||
|
// 获取当前登录医生ID
|
||||||
|
Long currentPhysicianId = SecurityUtils.getLoginUser().getPractitionerId();
|
||||||
|
|
||||||
|
// 查询邀请我的会诊申请
|
||||||
|
LambdaQueryWrapper<ConsultationInvited> invitedWrapper = new LambdaQueryWrapper<>();
|
||||||
|
invitedWrapper.eq(ConsultationInvited::getInvitedPhysicianId, currentPhysicianId)
|
||||||
|
.orderByDesc(ConsultationInvited::getCreateTime);
|
||||||
|
|
||||||
|
List<ConsultationInvited> invitedList = consultationInvitedMapper.selectList(invitedWrapper);
|
||||||
|
|
||||||
|
if (invitedList.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取所有会诊申请ID
|
||||||
|
List<Long> requestIds = invitedList.stream()
|
||||||
|
.map(ConsultationInvited::getConsultationRequestId)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// 查询会诊申请详情
|
||||||
|
List<ConsultationRequest> requests = consultationRequestMapper.selectBatchIds(requestIds);
|
||||||
|
|
||||||
|
// 转换为DTO并添加邀请状态
|
||||||
|
Map<Long, ConsultationInvited> invitedMap = invitedList.stream()
|
||||||
|
.collect(Collectors.toMap(ConsultationInvited::getConsultationRequestId, v -> v, (v1, v2) -> v1));
|
||||||
|
|
||||||
|
return requests.stream().map(request -> {
|
||||||
|
ConsultationRequestDto dto = convertToDto(request);
|
||||||
|
// 添加我的邀请状态
|
||||||
|
ConsultationInvited myInvited = invitedMap.get(request.getId());
|
||||||
|
if (myInvited != null) {
|
||||||
|
dto.setMyInvitedStatus(myInvited.getInvitedStatus());
|
||||||
|
dto.setMyConfirmTime(myInvited.getConfirmTime());
|
||||||
|
}
|
||||||
|
return dto;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取我的会诊邀请失败", e);
|
||||||
|
throw new RuntimeException("获取我的会诊邀请失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换为DTO
|
||||||
|
*/
|
||||||
|
private ConsultationRequestDto convertToDto(ConsultationRequest entity) {
|
||||||
|
ConsultationRequestDto dto = new ConsultationRequestDto();
|
||||||
|
BeanUtils.copyProperties(entity, dto);
|
||||||
|
|
||||||
|
// 查询邀请对象列表
|
||||||
|
if (entity.getId() != null) {
|
||||||
|
LambdaQueryWrapper<ConsultationInvited> invitedWrapper = new LambdaQueryWrapper<>();
|
||||||
|
invitedWrapper.eq(ConsultationInvited::getConsultationRequestId, entity.getId());
|
||||||
|
List<ConsultationInvited> invitedList = consultationInvitedMapper.selectList(invitedWrapper);
|
||||||
|
|
||||||
|
if (invitedList != null && !invitedList.isEmpty()) {
|
||||||
|
List<InvitedObjectDto> invitedDtoList = invitedList.stream().map(invited -> {
|
||||||
|
InvitedObjectDto invitedDto = new InvitedObjectDto();
|
||||||
|
invitedDto.setDeptId(invited.getInvitedDepartmentId());
|
||||||
|
invitedDto.setDeptName(invited.getInvitedDepartmentName());
|
||||||
|
invitedDto.setPhysicianId(invited.getInvitedPhysicianId());
|
||||||
|
invitedDto.setPhysicianName(invited.getInvitedPhysicianName());
|
||||||
|
return invitedDto;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
dto.setInvitedList(invitedDtoList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果门诊诊断为空,尝试从数据库自动获取
|
||||||
|
if (!StringUtils.hasText(entity.getProvisionalDiagnosis()) && entity.getEncounterId() != null) {
|
||||||
|
String diagnosis = getPatientDiagnosis(entity.getEncounterId());
|
||||||
|
if (StringUtils.hasText(diagnosis)) {
|
||||||
|
dto.setProvisionalDiagnosis(diagnosis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成会诊申请单号(高性能版本)
|
||||||
|
* 格式:CS + 年月日时分秒 + 4位序列号
|
||||||
|
* 例如:CS202601301425300001
|
||||||
|
*
|
||||||
|
* 优化说明:
|
||||||
|
* 1. 使用 AtomicInteger 保证线程安全,性能远高于 synchronized
|
||||||
|
* 2. 每秒最多支持 10000 个并发请求(0000-9999)
|
||||||
|
* 3. 无需查询数据库,性能提升 100+ 倍
|
||||||
|
* 4. 秒级时间戳 + 自增序列号,确保唯一性
|
||||||
|
*/
|
||||||
|
private String generateConsultationId() {
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
long nowMillis = System.currentTimeMillis();
|
||||||
|
long currentSecond = nowMillis / 1000;
|
||||||
|
|
||||||
|
// 跨秒则重置序列号(双重检查 + 类锁)
|
||||||
|
if (currentSecond != lastSecond) {
|
||||||
|
synchronized (ConsultationAppServiceImpl.class) {
|
||||||
|
if (currentSecond != lastSecond) {
|
||||||
|
lastSecond = currentSecond;
|
||||||
|
SEQUENCE.set(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sequence = SEQUENCE.getAndIncrement();
|
||||||
|
|
||||||
|
// 本秒内序列号耗尽:精确等待到下一秒再重试(避免递归、避免固定100ms)
|
||||||
|
if (sequence >= 10000) {
|
||||||
|
// 可选“回退自增”让 SEQUENCE 不乱飙
|
||||||
|
// 回退这次自增(可选,但更“稳”,避免 SEQUENCE 无限增长)
|
||||||
|
// 注意:回退可能在极端并发下导致轻微争用,但比不回退更可控
|
||||||
|
SEQUENCE.decrementAndGet();
|
||||||
|
|
||||||
|
sleepUntilNextSecond(nowMillis);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
String dateTime = sdf.format(new Date());
|
||||||
|
|
||||||
|
String sequenceStr = String.format("%04d", sequence);
|
||||||
|
return "CS" + dateTime + sequenceStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 精确等到下一秒,等待更短、抖动更小,不在固定睡100ms
|
||||||
|
private void sleepUntilNextSecond(long nowMillis) {
|
||||||
|
long nextSecondMillis = (nowMillis / 1000 + 1) * 1000;
|
||||||
|
long sleepMillis = nextSecondMillis - nowMillis;
|
||||||
|
|
||||||
|
// 防御:理论上 sleepMillis 范围是 1~1000ms
|
||||||
|
if (sleepMillis <= 0) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(sleepMillis);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// 恢复中断标记:把“有人希望我停下来”的信号传递给上层
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new RuntimeException("生成会诊申请单号失败:线程被中断", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// private String generateConsultationId() {
|
||||||
|
// java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
// long currentSecond = System.currentTimeMillis() / 1000;
|
||||||
|
//
|
||||||
|
// // 如果是新的一秒,重置序列号
|
||||||
|
// // 跨秒检测:如果发现当前秒变了,说明进入下一秒
|
||||||
|
// // 重置序列号:把 SEQUENCE 重新设置为 0,保证新的一秒从 0000 开始
|
||||||
|
// // 双重锁检测:避免重复进入
|
||||||
|
// if (currentSecond != lastSecond) {
|
||||||
|
// synchronized (ConsultationAppServiceImpl.class) {
|
||||||
|
// if (currentSecond != lastSecond) {
|
||||||
|
// lastSecond = currentSecond;
|
||||||
|
// SEQUENCE.set(0);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 获取当前序列号并自增(线程安全)
|
||||||
|
// int sequence = SEQUENCE.getAndIncrement();
|
||||||
|
//
|
||||||
|
// // 如果同一秒内超过 10000 个请求,等待下一秒
|
||||||
|
// if (sequence >= 10000) {
|
||||||
|
// try {
|
||||||
|
// Thread.sleep(100); // 等待 100ms
|
||||||
|
// return generateConsultationId(); // 递归重试
|
||||||
|
// } catch (InterruptedException e) {
|
||||||
|
// Thread.currentThread().interrupt();
|
||||||
|
// throw new RuntimeException("生成会诊申请单号失败", e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 生成时间戳部分
|
||||||
|
// String dateTime = sdf.format(new Date());
|
||||||
|
//
|
||||||
|
// // 生成4位序列号(补零)
|
||||||
|
// String sequenceStr = String.format("%04d", sequence);
|
||||||
|
//
|
||||||
|
// return "CS" + dateTime + sequenceStr;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算年龄
|
||||||
|
*/
|
||||||
|
private Integer calculateAge(Date birthDate) {
|
||||||
|
if (birthDate == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
java.util.Calendar now = java.util.Calendar.getInstance();
|
||||||
|
java.util.Calendar birth = java.util.Calendar.getInstance();
|
||||||
|
birth.setTime(birthDate);
|
||||||
|
|
||||||
|
int age = now.get(java.util.Calendar.YEAR) - birth.get(java.util.Calendar.YEAR);
|
||||||
|
if (now.get(java.util.Calendar.DAY_OF_YEAR) < birth.get(java.util.Calendar.DAY_OF_YEAR)) {
|
||||||
|
age--;
|
||||||
|
}
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存会诊医嘱到门诊医嘱表(wor_service_request)
|
||||||
|
* 同时创建费用项(adm_charge_item)
|
||||||
|
*
|
||||||
|
* @param consultationRequest 会诊申请实体
|
||||||
|
*/
|
||||||
|
private void saveConsultationServiceRequest(ConsultationRequest consultationRequest) {
|
||||||
|
try {
|
||||||
|
ServiceRequest serviceRequest = new ServiceRequest();
|
||||||
|
|
||||||
|
// 生成医嘱编号
|
||||||
|
String busNo = assignSeqUtil.getSeqByDay(AssignSeqEnum.SERVICE_RES_NO.getPrefix(), 4);
|
||||||
|
serviceRequest.setBusNo(busNo);
|
||||||
|
|
||||||
|
// 基本信息
|
||||||
|
serviceRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue());
|
||||||
|
|
||||||
|
// 🎯 使用前端选择的会诊项目ID
|
||||||
|
Long activityDefinitionId = consultationRequest.getConsultationActivityId();
|
||||||
|
if (activityDefinitionId == null) {
|
||||||
|
// 如果前端没有传递,使用默认的"院内会诊"
|
||||||
|
activityDefinitionId = 1983417749497446402L;
|
||||||
|
log.warn("前端未传递会诊项目ID,使用默认的院内会诊: {}", activityDefinitionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🎯 设置医嘱类型为会诊(31=会诊类型)
|
||||||
|
// 医嘱类型分类:1-10=药品,22-30=诊疗,31=会诊,40+=其他
|
||||||
|
serviceRequest.setCategoryEnum(31); // 会诊类型
|
||||||
|
serviceRequest.setActivityId(activityDefinitionId); // 关联到会诊项目定义
|
||||||
|
|
||||||
|
serviceRequest.setPatientId(consultationRequest.getPatientId());
|
||||||
|
serviceRequest.setEncounterId(consultationRequest.getEncounterId());
|
||||||
|
serviceRequest.setRequesterId(consultationRequest.getRequestingPhysicianId());
|
||||||
|
|
||||||
|
// 🎯 设置执行科室(申请医生的科室)
|
||||||
|
serviceRequest.setOrgId(consultationRequest.getDepartmentId());
|
||||||
|
|
||||||
|
// 🎯 设置执行次数为 1
|
||||||
|
serviceRequest.setQuantity(BigDecimal.ONE);
|
||||||
|
serviceRequest.setUnitCode("111"); // 单位:次
|
||||||
|
|
||||||
|
// 医嘱状态:新开
|
||||||
|
serviceRequest.setStatusEnum(RequestStatus.DRAFT.getValue());
|
||||||
|
|
||||||
|
// 医嘱内容:保存会诊申请的详细信息(JSON格式)
|
||||||
|
Map<String, Object> contentMap = new HashMap<>();
|
||||||
|
contentMap.put("consultationRequestId", consultationRequest.getId());
|
||||||
|
contentMap.put("consultationId", consultationRequest.getConsultationId());
|
||||||
|
contentMap.put("consultationType", consultationRequest.getConsultationActivityName());
|
||||||
|
contentMap.put("consultationActivityId", activityDefinitionId);
|
||||||
|
contentMap.put("patientName", consultationRequest.getPatientName());
|
||||||
|
contentMap.put("provisionalDiagnosis", consultationRequest.getProvisionalDiagnosis());
|
||||||
|
contentMap.put("consultationPurpose", consultationRequest.getConsultationPurpose());
|
||||||
|
contentMap.put("requestingPhysician", consultationRequest.getRequestingPhysician());
|
||||||
|
contentMap.put("department", consultationRequest.getDepartment());
|
||||||
|
contentMap.put("adviceName", consultationRequest.getConsultationActivityName()); // 添加项目名称
|
||||||
|
|
||||||
|
serviceRequest.setContentJson(JSON.toJSONString(contentMap));
|
||||||
|
|
||||||
|
// 时间信息
|
||||||
|
serviceRequest.setAuthoredTime(new Date());
|
||||||
|
|
||||||
|
// 审计字段
|
||||||
|
serviceRequest.setTenantId(SecurityUtils.getLoginUser().getTenantId().intValue());
|
||||||
|
serviceRequest.setCreateBy(SecurityUtils.getUsername());
|
||||||
|
serviceRequest.setCreateTime(new Date());
|
||||||
|
|
||||||
|
// 保存到数据库
|
||||||
|
iServiceRequestService.save(serviceRequest);
|
||||||
|
|
||||||
|
|
||||||
|
// 🎯 新增:创建费用项(ChargeItem)
|
||||||
|
// 查询会诊项目的价格定义
|
||||||
|
LambdaQueryWrapper<ChargeItemDefinition> priceWrapper = new LambdaQueryWrapper<>();
|
||||||
|
priceWrapper.eq(ChargeItemDefinition::getInstanceTable, "wor_activity_definition")
|
||||||
|
.eq(ChargeItemDefinition::getInstanceId, activityDefinitionId)
|
||||||
|
.eq(ChargeItemDefinition::getStatusEnum, 2) // 2=启用
|
||||||
|
.eq(ChargeItemDefinition::getDeleteFlag, "0")
|
||||||
|
.last("LIMIT 1");
|
||||||
|
|
||||||
|
ChargeItemDefinition chargeItemDef = chargeItemDefinitionMapper.selectOne(priceWrapper);
|
||||||
|
|
||||||
|
if (chargeItemDef != null) {
|
||||||
|
// 🎯 查询患者的费用性质(account_id)
|
||||||
|
// 从 adm_account 表获取患者的 account_id(费用性质)
|
||||||
|
Long accountId = doctorStationAdviceAppMapper.getEncounterContract(consultationRequest.getEncounterId())
|
||||||
|
.stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(contract -> contract.getAccountId())
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (accountId == null) {
|
||||||
|
log.warn("未找到患者的费用性质,encounterId: {}", consultationRequest.getEncounterId());
|
||||||
|
throw new RuntimeException("未找到患者的费用性质信息,无法创建费用项");
|
||||||
|
}
|
||||||
|
|
||||||
|
ChargeItem chargeItem = new ChargeItem();
|
||||||
|
chargeItem.setStatusEnum(ChargeItemStatus.DRAFT.getValue()); // 草稿状态
|
||||||
|
chargeItem.setBusNo(AssignSeqEnum.CHARGE_ITEM_NO.getPrefix().concat(busNo));
|
||||||
|
chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue());
|
||||||
|
chargeItem.setPatientId(consultationRequest.getPatientId());
|
||||||
|
chargeItem.setContextEnum(ItemType.ACTIVITY.getValue()); // 诊疗类型
|
||||||
|
chargeItem.setEncounterId(consultationRequest.getEncounterId());
|
||||||
|
|
||||||
|
// 🎯 设置费用性质(必填字段)
|
||||||
|
chargeItem.setAccountId(accountId);
|
||||||
|
|
||||||
|
// 费用定价信息
|
||||||
|
chargeItem.setDefinitionId(chargeItemDef.getId());
|
||||||
|
chargeItem.setUnitPrice(chargeItemDef.getPrice());
|
||||||
|
chargeItem.setQuantityValue(BigDecimal.ONE);
|
||||||
|
chargeItem.setQuantityUnit("111"); // 次
|
||||||
|
chargeItem.setTotalPrice(chargeItemDef.getPrice());
|
||||||
|
|
||||||
|
// 关联医嘱信息
|
||||||
|
chargeItem.setServiceTable("wor_service_request");
|
||||||
|
chargeItem.setServiceId(serviceRequest.getId());
|
||||||
|
chargeItem.setProductTable("wor_activity_definition");
|
||||||
|
chargeItem.setProductId(activityDefinitionId);
|
||||||
|
|
||||||
|
// 开立信息
|
||||||
|
chargeItem.setEntererId(consultationRequest.getRequestingPhysicianId());
|
||||||
|
chargeItem.setRequestingOrgId(consultationRequest.getDepartmentId());
|
||||||
|
chargeItem.setEnteredDate(new Date());
|
||||||
|
|
||||||
|
// 审计字段
|
||||||
|
chargeItem.setTenantId(SecurityUtils.getLoginUser().getTenantId());
|
||||||
|
chargeItem.setCreateBy(SecurityUtils.getUsername());
|
||||||
|
chargeItem.setCreateTime(new Date());
|
||||||
|
|
||||||
|
iChargeItemService.save(chargeItem);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.warn("未找到会诊项目的价格定义,activityId: {}", activityDefinitionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将医嘱ID保存到会诊申请表
|
||||||
|
consultationRequest.setOrderId(serviceRequest.getId());
|
||||||
|
consultationRequestMapper.updateById(consultationRequest);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("保存会诊医嘱失败", e);
|
||||||
|
throw new RuntimeException("保存会诊医嘱失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新会诊医嘱
|
||||||
|
*
|
||||||
|
* @param consultationRequest 会诊申请实体
|
||||||
|
*/
|
||||||
|
private void updateConsultationServiceRequest(ConsultationRequest consultationRequest) {
|
||||||
|
try {
|
||||||
|
if (consultationRequest.getOrderId() == null) {
|
||||||
|
log.warn("会诊申请没有关联的医嘱ID,跳过更新");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceRequest serviceRequest = iServiceRequestService.getById(consultationRequest.getOrderId());
|
||||||
|
if (serviceRequest == null) {
|
||||||
|
log.warn("未找到关联的医嘱记录,OrderId: {}", consultationRequest.getOrderId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新医嘱内容
|
||||||
|
serviceRequest.setContentJson(JSON.toJSONString(consultationRequest));
|
||||||
|
serviceRequest.setUpdateBy(SecurityUtils.getUsername());
|
||||||
|
serviceRequest.setUpdateTime(new Date());
|
||||||
|
|
||||||
|
iServiceRequestService.updateById(serviceRequest);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("更新会诊医嘱失败", e);
|
||||||
|
throw new RuntimeException("更新会诊医嘱失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新门诊医嘱状态
|
||||||
|
*
|
||||||
|
* @param orderId 医嘱ID
|
||||||
|
* @param status 新状态
|
||||||
|
*/
|
||||||
|
private void updateServiceRequestStatus(Long orderId, Integer status) {
|
||||||
|
try {
|
||||||
|
if (orderId == null) {
|
||||||
|
log.warn("医嘱ID为空,跳过状态更新");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceRequest serviceRequest = iServiceRequestService.getById(orderId);
|
||||||
|
if (serviceRequest == null) {
|
||||||
|
log.warn("未找到医嘱记录,OrderId: {}", orderId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceRequest.setStatusEnum(status);
|
||||||
|
serviceRequest.setUpdateBy(SecurityUtils.getUsername());
|
||||||
|
serviceRequest.setUpdateTime(new Date());
|
||||||
|
|
||||||
|
iServiceRequestService.updateById(serviceRequest);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("更新医嘱状态失败", e);
|
||||||
|
throw new RuntimeException("更新医嘱状态失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ConsultationActivityDto> getConsultationActivities() {
|
||||||
|
try {
|
||||||
|
// 查询所有会诊相关的诊疗活动
|
||||||
|
LambdaQueryWrapper<ActivityDefinition> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.like(ActivityDefinition::getName, "会诊")
|
||||||
|
.eq(ActivityDefinition::getDeleteFlag, "0")
|
||||||
|
.orderBy(true, true, ActivityDefinition::getSortOrder);
|
||||||
|
|
||||||
|
List<ActivityDefinition> activityList = activityDefinitionMapper.selectList(wrapper);
|
||||||
|
if (activityList.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换为DTO并查询价格
|
||||||
|
List<ConsultationActivityDto> resultList = new ArrayList<>();
|
||||||
|
for (ActivityDefinition activity : activityList) {
|
||||||
|
ConsultationActivityDto dto = new ConsultationActivityDto();
|
||||||
|
dto.setId(activity.getId());
|
||||||
|
dto.setName(activity.getName());
|
||||||
|
dto.setBusNo(activity.getBusNo());
|
||||||
|
dto.setTypeEnum(activity.getTypeEnum());
|
||||||
|
dto.setCategoryCode(activity.getCategoryCode());
|
||||||
|
dto.setUnitCode(activity.getPermittedUnitCode());
|
||||||
|
dto.setStatusEnum(activity.getStatusEnum());
|
||||||
|
|
||||||
|
// 查询价格
|
||||||
|
LambdaQueryWrapper<ChargeItemDefinition> priceWrapper = new LambdaQueryWrapper<>();
|
||||||
|
priceWrapper.eq(ChargeItemDefinition::getInstanceTable, "wor_activity_definition")
|
||||||
|
.eq(ChargeItemDefinition::getInstanceId, activity.getId())
|
||||||
|
.eq(ChargeItemDefinition::getStatusEnum, 2) // 2=启用
|
||||||
|
.eq(ChargeItemDefinition::getDeleteFlag, "0")
|
||||||
|
.last("LIMIT 1");
|
||||||
|
|
||||||
|
ChargeItemDefinition chargeItem = chargeItemDefinitionMapper.selectOne(priceWrapper);
|
||||||
|
if (chargeItem != null && chargeItem.getPrice() != null) {
|
||||||
|
dto.setPrice(chargeItem.getPrice());
|
||||||
|
} else {
|
||||||
|
dto.setPrice(java.math.BigDecimal.ZERO);
|
||||||
|
log.warn("会诊项目: {} 未找到价格定义", activity.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
resultList.add(dto);
|
||||||
|
}
|
||||||
|
return resultList;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("查询会诊项目列表失败", e);
|
||||||
|
throw new RuntimeException("查询会诊项目列表失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package com.openhis.web.consultation.controller;
|
||||||
|
|
||||||
|
import com.core.common.core.domain.R;
|
||||||
|
import com.openhis.web.consultation.appservice.IConsultationAppService;
|
||||||
|
import com.openhis.web.consultation.dto.ConsultationActivityDto;
|
||||||
|
import com.openhis.web.consultation.dto.ConsultationRequestDto;
|
||||||
|
import com.openhis.web.consultation.dto.DepartmentTreeDto;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import io.swagger.annotations.ApiParam;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊管理Controller
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-01-29
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Api(tags = "会诊管理")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/consultation")
|
||||||
|
public class ConsultationController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IConsultationAppService consultationAppService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取会诊列表")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public R<List<ConsultationRequestDto>> getConsultationList(
|
||||||
|
@ApiParam("就诊ID(可选,不传则查询当前医生的所有会诊申请)")
|
||||||
|
@RequestParam(required = false) Long encounterId) {
|
||||||
|
try {
|
||||||
|
List<ConsultationRequestDto> list = consultationAppService.getConsultationList(encounterId);
|
||||||
|
return R.ok(list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取会诊列表失败", e);
|
||||||
|
return R.fail("获取会诊列表失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存会诊申请
|
||||||
|
*/
|
||||||
|
@ApiOperation("保存会诊申请")
|
||||||
|
@PostMapping("/save")
|
||||||
|
public R<String> saveConsultation(@RequestBody ConsultationRequestDto dto) {
|
||||||
|
try {
|
||||||
|
Boolean result = consultationAppService.saveConsultation(dto);
|
||||||
|
return result ? R.ok("保存成功") : R.fail("保存失败");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("保存会诊申请失败", e);
|
||||||
|
return R.fail("保存会诊申请失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交会诊申请
|
||||||
|
*/
|
||||||
|
@ApiOperation("提交会诊申请")
|
||||||
|
@PostMapping("/submit")
|
||||||
|
public R<String> submitConsultation(
|
||||||
|
@ApiParam("会诊申请单号") @RequestParam String consultationId) {
|
||||||
|
try {
|
||||||
|
Boolean result = consultationAppService.submitConsultation(consultationId);
|
||||||
|
return result ? R.ok("提交成功") : R.fail("提交失败");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("提交会诊申请失败", e);
|
||||||
|
return R.fail("提交会诊申请失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 作废会诊申请
|
||||||
|
*/
|
||||||
|
@ApiOperation("作废会诊申请")
|
||||||
|
@PostMapping("/cancel")
|
||||||
|
public R<String> cancelConsultation(
|
||||||
|
@ApiParam("会诊申请单号") @RequestParam String consultationId,
|
||||||
|
@ApiParam("作废原因") @RequestParam(required = false) String cancelReason) {
|
||||||
|
try {
|
||||||
|
Boolean result = consultationAppService.cancelConsultation(consultationId, cancelReason);
|
||||||
|
return result ? R.ok("作废成功") : R.fail("作废失败");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("作废会诊申请失败", e);
|
||||||
|
return R.fail("作废会诊申请失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束会诊申请
|
||||||
|
*/
|
||||||
|
@ApiOperation("结束会诊申请")
|
||||||
|
@PostMapping("/complete")
|
||||||
|
public R<String> completeConsultation(
|
||||||
|
@ApiParam("会诊申请单号") @RequestParam String consultationId) {
|
||||||
|
try {
|
||||||
|
Boolean result = consultationAppService.completeConsultation(consultationId);
|
||||||
|
return result ? R.ok("结束成功") : R.fail("结束失败");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("结束会诊申请失败", e);
|
||||||
|
return R.fail("结束会诊申请失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取科室医生树
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取科室医生树")
|
||||||
|
@GetMapping("/departmentTree")
|
||||||
|
public R<List<DepartmentTreeDto>> getDepartmentTree() {
|
||||||
|
try {
|
||||||
|
List<DepartmentTreeDto> tree = consultationAppService.getDepartmentTree();
|
||||||
|
return R.ok(tree);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取科室医生树失败", e);
|
||||||
|
return R.fail("获取科室医生树失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主诊断
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取主诊断")
|
||||||
|
@GetMapping("/mainDiagnosis")
|
||||||
|
public R<Map<String, String>> getMainDiagnosis(
|
||||||
|
@ApiParam("就诊ID") @RequestParam Long encounterId) {
|
||||||
|
try {
|
||||||
|
Map<String, String> diagnosis = consultationAppService.getMainDiagnosis(encounterId);
|
||||||
|
return R.ok(diagnosis);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取主诊断失败", e);
|
||||||
|
return R.fail("获取主诊断失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取我的会诊邀请列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取我的会诊邀请列表")
|
||||||
|
@GetMapping("/myInvitations")
|
||||||
|
public R<List<ConsultationRequestDto>> getMyInvitations() {
|
||||||
|
try {
|
||||||
|
List<ConsultationRequestDto> list = consultationAppService.getMyInvitations();
|
||||||
|
return R.ok(list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取我的会诊邀请失败", e);
|
||||||
|
return R.fail("获取我的会诊邀请失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有会诊项目及价格
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取所有会诊项目及价格")
|
||||||
|
@GetMapping("/activities")
|
||||||
|
public R<List<ConsultationActivityDto>> getConsultationActivities() {
|
||||||
|
try {
|
||||||
|
List<ConsultationActivityDto> list = consultationAppService.getConsultationActivities();
|
||||||
|
return R.ok(list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取会诊项目列表失败", e);
|
||||||
|
return R.fail("获取会诊项目列表失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
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-01-30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("consultation_invited")
|
||||||
|
public class ConsultationInvited implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊申请ID(外键)
|
||||||
|
*/
|
||||||
|
@TableField("consultation_request_id")
|
||||||
|
private Long consultationRequestId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请科室ID
|
||||||
|
*/
|
||||||
|
@TableField("invited_department_id")
|
||||||
|
private Long invitedDepartmentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请科室名称
|
||||||
|
*/
|
||||||
|
@TableField("invited_department_name")
|
||||||
|
private String invitedDepartmentName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请医生ID
|
||||||
|
*/
|
||||||
|
@TableField("invited_physician_id")
|
||||||
|
private Long invitedPhysicianId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请医生姓名
|
||||||
|
*/
|
||||||
|
@TableField("invited_physician_name")
|
||||||
|
private String invitedPhysicianName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请状态(0-待确认,1-已确认,2-已拒绝)
|
||||||
|
*/
|
||||||
|
@TableField("invited_status")
|
||||||
|
private Integer invitedStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认时间
|
||||||
|
*/
|
||||||
|
@TableField("confirm_time")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date confirmTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认意见
|
||||||
|
*/
|
||||||
|
@TableField("confirm_opinion")
|
||||||
|
private String confirmOpinion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(value = "create_time", fill = FieldFill.INSERT)
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
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-01-29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("consultation_request")
|
||||||
|
public class ConsultationRequest implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊申请单号
|
||||||
|
*/
|
||||||
|
@TableField("consultation_id")
|
||||||
|
private String consultationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 患者ID
|
||||||
|
*/
|
||||||
|
@TableField("patient_id")
|
||||||
|
private Long patientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 就诊ID
|
||||||
|
*/
|
||||||
|
@TableField("encounter_id")
|
||||||
|
private Long encounterId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单ID(关联门诊医嘱表 wor_service_request.id)
|
||||||
|
*/
|
||||||
|
@TableField("order_id")
|
||||||
|
private Long orderId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 患者姓名
|
||||||
|
*/
|
||||||
|
@TableField("patient_name")
|
||||||
|
private String patientName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 患者病历号
|
||||||
|
*/
|
||||||
|
@TableField("patient_bus_no")
|
||||||
|
private String patientBusNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 患者就诊卡号
|
||||||
|
*/
|
||||||
|
@TableField("patient_identifier_no")
|
||||||
|
private String patientIdentifierNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 性别
|
||||||
|
*/
|
||||||
|
@TableField("gender_enum")
|
||||||
|
private Integer genderEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 年龄
|
||||||
|
*/
|
||||||
|
@TableField("age")
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请科室名称
|
||||||
|
*/
|
||||||
|
@TableField("department")
|
||||||
|
private String department;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请科室ID
|
||||||
|
*/
|
||||||
|
@TableField("department_id")
|
||||||
|
private Long departmentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请医生姓名
|
||||||
|
*/
|
||||||
|
@TableField("requesting_physician")
|
||||||
|
private String requestingPhysician;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请医生ID
|
||||||
|
*/
|
||||||
|
@TableField("requesting_physician_id")
|
||||||
|
private Long requestingPhysicianId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请时间
|
||||||
|
*/
|
||||||
|
@TableField("consultation_request_date")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date consultationRequestDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请对象显示文本
|
||||||
|
*/
|
||||||
|
@TableField("invited_object")
|
||||||
|
private String invitedObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊时间
|
||||||
|
*/
|
||||||
|
@TableField("consultation_date")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date consultationDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊目的
|
||||||
|
*/
|
||||||
|
@TableField("consultation_purpose")
|
||||||
|
private String consultationPurpose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 门诊诊断
|
||||||
|
*/
|
||||||
|
@TableField("provisional_diagnosis")
|
||||||
|
private String provisionalDiagnosis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊项目ID(关联wor_activity_definition表)
|
||||||
|
*/
|
||||||
|
@TableField("consultation_activity_id")
|
||||||
|
private Long consultationActivityId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊项目名称(如:院内会诊、远程会诊等)
|
||||||
|
*/
|
||||||
|
@TableField("consultation_activity_name")
|
||||||
|
private String consultationActivityName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊意见
|
||||||
|
*/
|
||||||
|
@TableField("consultation_opinion")
|
||||||
|
private String consultationOpinion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊状态(0-新开,10-已提交,20-已确认,30-已签名,40-已完成,50-已取消)
|
||||||
|
*/
|
||||||
|
@TableField("consultation_status")
|
||||||
|
private Integer consultationStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 紧急程度(一般/紧急)
|
||||||
|
*/
|
||||||
|
@TableField("consultation_urgency")
|
||||||
|
private String consultationUrgency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认医生
|
||||||
|
*/
|
||||||
|
@TableField("confirming_physician")
|
||||||
|
private String confirmingPhysician;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认医生ID
|
||||||
|
*/
|
||||||
|
@TableField("confirming_physician_id")
|
||||||
|
private Long confirmingPhysicianId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认时间
|
||||||
|
*/
|
||||||
|
@TableField("confirming_date")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date confirmingDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名
|
||||||
|
*/
|
||||||
|
@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("cancel_nature_date")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date cancelNatureDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 作废原因
|
||||||
|
*/
|
||||||
|
@TableField("cancel_reason")
|
||||||
|
private String cancelReason;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(value = "create_time", fill = FieldFill.INSERT)
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package com.openhis.web.consultation.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊项目DTO
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-02-02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ConsultationActivityDto implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目ID
|
||||||
|
* 使用 @JsonSerialize 注解将 Long 类型转换为 String,避免前端 JavaScript 精度丢失
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目编号
|
||||||
|
*/
|
||||||
|
private String busNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 价格
|
||||||
|
*/
|
||||||
|
private BigDecimal price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型枚举
|
||||||
|
*/
|
||||||
|
private Integer typeEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类编码
|
||||||
|
*/
|
||||||
|
private String categoryCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单位编码
|
||||||
|
*/
|
||||||
|
private String unitCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单位名称
|
||||||
|
*/
|
||||||
|
private String unitCodeText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*/
|
||||||
|
private Integer statusEnum;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
package com.openhis.web.consultation.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊申请DTO
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-01-29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ConsultationRequestDto implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键ID
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊申请单号
|
||||||
|
*/
|
||||||
|
private String consultationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 患者ID
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long patientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 患者姓名
|
||||||
|
*/
|
||||||
|
private String patientName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 患者性别
|
||||||
|
*/
|
||||||
|
private Integer genderEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 患者年龄
|
||||||
|
*/
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 病历号
|
||||||
|
*/
|
||||||
|
private String patientBusNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 就诊卡号
|
||||||
|
*/
|
||||||
|
private String patientIdentifierNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 就诊ID
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long encounterId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请科室ID
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long departmentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请科室名称
|
||||||
|
*/
|
||||||
|
private String department;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请医生ID
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long requestingPhysicianId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请医生姓名
|
||||||
|
*/
|
||||||
|
private String requestingPhysician;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请对象显示文本
|
||||||
|
*/
|
||||||
|
private String invitedObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请对象列表
|
||||||
|
*/
|
||||||
|
private List<InvitedObjectDto> invitedList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date consultationDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date consultationRequestDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊目的
|
||||||
|
*/
|
||||||
|
private String consultationPurpose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 门诊诊断
|
||||||
|
*/
|
||||||
|
private String provisionalDiagnosis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊项目ID(关联wor_activity_definition表)
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long consultationActivityId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊项目名称(如:院内会诊、远程会诊等)
|
||||||
|
*/
|
||||||
|
private String consultationActivityName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 紧急程度(1=普通,2=紧急)
|
||||||
|
*/
|
||||||
|
private String consultationUrgency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊状态
|
||||||
|
*/
|
||||||
|
private Integer consultationStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊意见
|
||||||
|
*/
|
||||||
|
private String consultationOpinion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参与会诊医师
|
||||||
|
*/
|
||||||
|
private String consultingPhysicians;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名医生ID
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long signingPhysicianId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名医生姓名
|
||||||
|
*/
|
||||||
|
private String signingPhysicianName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date signingTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否提交(保存时使用)
|
||||||
|
*/
|
||||||
|
private Boolean submitFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我的邀请状态(查询我的邀请时使用,0-待确认,1-已确认,2-已拒绝)
|
||||||
|
*/
|
||||||
|
private Integer myInvitedStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 我的确认时间(查询我的邀请时使用)
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date myConfirmTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.openhis.web.consultation.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 科室医生树DTO
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-01-29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DepartmentTreeDto implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 科室ID(序列化为字符串,避免JavaScript精度丢失)
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 科室名称
|
||||||
|
*/
|
||||||
|
private String label;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子节点(医生列表)
|
||||||
|
*/
|
||||||
|
private List<PhysicianNodeDto> children;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.openhis.web.consultation.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请对象DTO
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-01-29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class InvitedObjectDto implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 科室ID(序列化为字符串,避免JavaScript精度丢失)
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 科室名称
|
||||||
|
*/
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生ID(为空表示邀请整个科室)(序列化为字符串,避免JavaScript精度丢失)
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long physicianId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生姓名
|
||||||
|
*/
|
||||||
|
private String physicianName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.openhis.web.consultation.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生节点DTO
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-01-29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class PhysicianNodeDto implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生ID(序列化为字符串,避免JavaScript精度丢失)
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生姓名
|
||||||
|
*/
|
||||||
|
private String label;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package com.openhis.web.consultation.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊状态枚举
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-02-05
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum ConsultationStatusEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新开(草稿)
|
||||||
|
*/
|
||||||
|
NEW(0, "新开"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已提交
|
||||||
|
*/
|
||||||
|
SUBMITTED(10, "已提交"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已确认
|
||||||
|
*/
|
||||||
|
CONFIRMED(20, "已确认"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已签名
|
||||||
|
*/
|
||||||
|
SIGNED(30, "已签名"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已完成
|
||||||
|
*/
|
||||||
|
COMPLETED(40, "已完成"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已取消
|
||||||
|
*/
|
||||||
|
CANCELLED(50, "已取消");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态码
|
||||||
|
*/
|
||||||
|
private final Integer code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据状态码获取枚举
|
||||||
|
*/
|
||||||
|
public static ConsultationStatusEnum getByCode(Integer code) {
|
||||||
|
if (code == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (ConsultationStatusEnum status : values()) {
|
||||||
|
if (status.getCode().equals(code)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否可以编辑
|
||||||
|
*/
|
||||||
|
public boolean canEdit() {
|
||||||
|
return this == NEW || this == SUBMITTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否可以取消
|
||||||
|
*/
|
||||||
|
public boolean canCancel() {
|
||||||
|
return this == NEW || this == SUBMITTED || this == CONFIRMED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.openhis.web.consultation.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊紧急程度枚举
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-02-05
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum ConsultationUrgencyEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通
|
||||||
|
*/
|
||||||
|
NORMAL("1", "普通"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 紧急
|
||||||
|
*/
|
||||||
|
URGENT("2", "紧急");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型码
|
||||||
|
*/
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据类型码获取枚举
|
||||||
|
*/
|
||||||
|
public static ConsultationUrgencyEnum getByCode(String code) {
|
||||||
|
if (code == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (ConsultationUrgencyEnum urgency : values()) {
|
||||||
|
if (urgency.getCode().equals(code)) {
|
||||||
|
return urgency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.openhis.web.consultation.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邀请状态枚举
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-02-05
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum InvitedStatusEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 待确认
|
||||||
|
*/
|
||||||
|
PENDING(0, "待确认"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已确认
|
||||||
|
*/
|
||||||
|
CONFIRMED(1, "已确认"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已拒绝
|
||||||
|
*/
|
||||||
|
REJECTED(2, "已拒绝");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态码
|
||||||
|
*/
|
||||||
|
private final Integer code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态描述
|
||||||
|
*/
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据状态码获取枚举
|
||||||
|
*/
|
||||||
|
public static InvitedStatusEnum getByCode(Integer code) {
|
||||||
|
if (code == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (InvitedStatusEnum status : values()) {
|
||||||
|
if (status.getCode().equals(code)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.openhis.web.consultation.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.openhis.web.consultation.domain.ConsultationInvited;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊邀请对象Mapper接口
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-01-30
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ConsultationInvitedMapper extends BaseMapper<ConsultationInvited> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.openhis.web.consultation.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.openhis.web.consultation.domain.ConsultationRequest;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会诊申请Mapper接口
|
||||||
|
*
|
||||||
|
* @author system
|
||||||
|
* @date 2026-01-29
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ConsultationRequestMapper extends BaseMapper<ConsultationRequest> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -864,7 +864,17 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
serviceRequest.setQuantity(adviceSaveDto.getQuantity()); // 请求数量
|
serviceRequest.setQuantity(adviceSaveDto.getQuantity()); // 请求数量
|
||||||
serviceRequest.setUnitCode(adviceSaveDto.getUnitCode()); // 请求单位编码
|
serviceRequest.setUnitCode(adviceSaveDto.getUnitCode()); // 请求单位编码
|
||||||
|
|
||||||
serviceRequest.setCategoryEnum(adviceSaveDto.getCategoryEnum()); // 请求类型
|
// 🎯 判断是否为会诊医嘱:如果categoryEnum为31,则为会诊类型
|
||||||
|
Integer categoryEnum = adviceSaveDto.getCategoryEnum();
|
||||||
|
if (categoryEnum != null && categoryEnum == 31) {
|
||||||
|
// 会诊医嘱:category_enum设置为31
|
||||||
|
serviceRequest.setCategoryEnum(31);
|
||||||
|
log.info("保存会诊医嘱,category_enum=31");
|
||||||
|
} else {
|
||||||
|
// 普通诊疗医嘱
|
||||||
|
serviceRequest.setCategoryEnum(adviceSaveDto.getCategoryEnum());
|
||||||
|
}
|
||||||
|
|
||||||
serviceRequest.setActivityId(adviceSaveDto.getAdviceDefinitionId());// 诊疗定义id
|
serviceRequest.setActivityId(adviceSaveDto.getAdviceDefinitionId());// 诊疗定义id
|
||||||
serviceRequest.setPatientId(adviceSaveDto.getPatientId()); // 患者
|
serviceRequest.setPatientId(adviceSaveDto.getPatientId()); // 患者
|
||||||
serviceRequest.setRequesterId(adviceSaveDto.getPractitionerId()); // 开方医生
|
serviceRequest.setRequesterId(adviceSaveDto.getPractitionerId()); // 开方医生
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.openhis.web.consultation.mapper.ConsultationRequestMapper">
|
||||||
|
|
||||||
|
<!-- 通用查询映射结果 -->
|
||||||
|
<resultMap id="BaseResultMap" type="com.openhis.web.consultation.domain.ConsultationRequest">
|
||||||
|
<id column="id" property="id" />
|
||||||
|
<result column="consultation_id" property="consultationId" />
|
||||||
|
<result column="patient_id" property="patientId" />
|
||||||
|
<result column="encounter_id" property="encounterId" />
|
||||||
|
<result column="order_id" property="orderId" />
|
||||||
|
<result column="patient_name" property="patientName" />
|
||||||
|
<result column="patient_bus_no" property="patientBusNo" />
|
||||||
|
<result column="patient_identifier_no" property="patientIdentifierNo" />
|
||||||
|
<result column="gender_enum" property="genderEnum" />
|
||||||
|
<result column="age" property="age" />
|
||||||
|
<result column="department" property="department" />
|
||||||
|
<result column="department_id" property="departmentId" />
|
||||||
|
<result column="requesting_physician" property="requestingPhysician" />
|
||||||
|
<result column="requesting_physician_id" property="requestingPhysicianId" />
|
||||||
|
<result column="consultation_request_date" property="consultationRequestDate" />
|
||||||
|
<result column="invited_object" property="invitedObject" />
|
||||||
|
<result column="invited_department_id" property="invitedDepartmentId" />
|
||||||
|
<result column="invited_physician_id" property="invitedPhysicianId" />
|
||||||
|
<result column="consultation_date" property="consultationDate" />
|
||||||
|
<result column="consultation_purpose" property="consultationPurpose" />
|
||||||
|
<result column="provisional_diagnosis" property="provisionalDiagnosis" />
|
||||||
|
<result column="consultation_opinion" property="consultationOpinion" />
|
||||||
|
<result column="consultation_status" property="consultationStatus" />
|
||||||
|
<result column="consultation_urgency" property="consultationUrgency" />
|
||||||
|
<result column="confirming_physician" property="confirmingPhysician" />
|
||||||
|
<result column="confirming_physician_id" property="confirmingPhysicianId" />
|
||||||
|
<result column="confirming_date" property="confirmingDate" />
|
||||||
|
<result column="signature" property="signature" />
|
||||||
|
<result column="signature_physician_id" property="signaturePhysicianId" />
|
||||||
|
<result column="signature_date" property="signatureDate" />
|
||||||
|
<result column="cancel_nature_date" property="cancelNatureDate" />
|
||||||
|
<result column="cancel_reason" property="cancelReason" />
|
||||||
|
<result column="create_time" property="createTime" />
|
||||||
|
<result column="update_time" property="updateTime" />
|
||||||
|
<result column="create_by" property="createBy" />
|
||||||
|
<result column="update_by" property="updateBy" />
|
||||||
|
<result column="tenant_id" property="tenantId" />
|
||||||
|
<result column="is_deleted" property="isDeleted" />
|
||||||
|
<result column="remark" property="remark" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
|
|
||||||
@@ -465,7 +465,8 @@
|
|||||||
T2.part_percent AS part_percent,
|
T2.part_percent AS part_percent,
|
||||||
ccd.name AS condition_definition_name,
|
ccd.name AS condition_definition_name,
|
||||||
T1.sort_number AS sort_number,
|
T1.sort_number AS sort_number,
|
||||||
T1.based_on_id AS based_on_id
|
T1.based_on_id AS based_on_id,
|
||||||
|
T1.category_enum AS category_enum
|
||||||
FROM med_medication_request AS T1
|
FROM med_medication_request AS T1
|
||||||
LEFT JOIN med_medication_definition AS T2 ON T2.ID = T1.medication_id
|
LEFT JOIN med_medication_definition AS T2 ON T2.ID = T1.medication_id
|
||||||
AND T2.delete_flag = '0'
|
AND T2.delete_flag = '0'
|
||||||
@@ -516,7 +517,8 @@
|
|||||||
T2.part_percent AS part_percent,
|
T2.part_percent AS part_percent,
|
||||||
'' AS condition_definition_name,
|
'' AS condition_definition_name,
|
||||||
99 AS sort_number,
|
99 AS sort_number,
|
||||||
T1.based_on_id AS based_on_id
|
T1.based_on_id AS based_on_id,
|
||||||
|
T1.category_enum AS category_enum
|
||||||
FROM wor_device_request AS T1
|
FROM wor_device_request AS T1
|
||||||
LEFT JOIN adm_device_definition AS T2 ON T2.ID = T1.device_def_id
|
LEFT JOIN adm_device_definition AS T2 ON T2.ID = T1.device_def_id
|
||||||
AND T2.delete_flag = '0'
|
AND T2.delete_flag = '0'
|
||||||
@@ -564,7 +566,8 @@
|
|||||||
1 AS part_percent,
|
1 AS part_percent,
|
||||||
'' AS condition_definition_name,
|
'' AS condition_definition_name,
|
||||||
99 AS sort_number,
|
99 AS sort_number,
|
||||||
T1.based_on_id AS based_on_id
|
T1.based_on_id AS based_on_id,
|
||||||
|
T1.category_enum AS category_enum
|
||||||
FROM wor_service_request AS T1
|
FROM wor_service_request AS T1
|
||||||
LEFT JOIN wor_activity_definition AS T2
|
LEFT JOIN wor_activity_definition AS T2
|
||||||
ON T2.ID = T1.activity_id
|
ON T2.ID = T1.activity_id
|
||||||
|
|||||||
@@ -0,0 +1,402 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container consultation-confirmation">
|
||||||
|
<div class="page-header">
|
||||||
|
<span class="tab-title">会诊确认</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-bar no-print">
|
||||||
|
<el-button type="success" @click="handlePrint">打印</el-button>
|
||||||
|
<el-button @click="handleRefresh">刷新</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="!currentRow"
|
||||||
|
@click="handleConfirm"
|
||||||
|
>
|
||||||
|
{{ confirmButtonText }}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:disabled="!canSign"
|
||||||
|
@click="handleSign"
|
||||||
|
>
|
||||||
|
签名
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-section no-print">
|
||||||
|
<el-table
|
||||||
|
:data="tableData"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
highlight-current-row
|
||||||
|
@current-change="handleRowChange"
|
||||||
|
>
|
||||||
|
<el-table-column type="index" width="60" label="序号" align="center" />
|
||||||
|
<el-table-column label="紧急" width="70" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-checkbox v-model="scope.row.urgent" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="consultationId" label="申请单号" min-width="160" />
|
||||||
|
<el-table-column prop="patientName" label="病人姓名" min-width="100" />
|
||||||
|
<el-table-column prop="consultationTime" label="会诊时间" min-width="160" />
|
||||||
|
<el-table-column prop="invitee" 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="applyTime" label="申请时间" min-width="160" />
|
||||||
|
<el-table-column label="确认" width="70" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-checkbox v-model="scope.row.confirmed" disabled />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="签名" width="70" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-checkbox v-model="scope.row.signed" disabled />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-section">
|
||||||
|
<div class="section-title">会诊记录单</div>
|
||||||
|
<el-form :model="formData" label-width="110px">
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="病人姓名">
|
||||||
|
<el-input v-model="formData.patientName" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="性别">
|
||||||
|
<el-input v-model="formData.gender" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="年龄">
|
||||||
|
<el-input v-model="formData.age" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="就诊卡号">
|
||||||
|
<el-input v-model="formData.cardNo" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="申请单号">
|
||||||
|
<el-input v-model="formData.consultationId" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="申请科室">
|
||||||
|
<el-input v-model="formData.applyDept" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="会诊时间">
|
||||||
|
<el-input v-model="formData.consultationTime" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="紧急标志">
|
||||||
|
<el-input :model-value="formData.urgent ? '是' : '否'" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="会诊邀请对象">
|
||||||
|
<el-input v-model="formData.invitee" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="提交医生">
|
||||||
|
<el-input v-model="formData.applyDoctor" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="提交时间">
|
||||||
|
<el-input v-model="formData.applyTime" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-form-item label="病史及目的">
|
||||||
|
<el-input v-model="formData.history" type="textarea" :rows="3" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="会诊确认参加医师" required>
|
||||||
|
<el-input v-model="formData.confirmingPhysician" placeholder="请输入会诊确认参加医师" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="会诊意见" required>
|
||||||
|
<el-input v-model="formData.opinion" type="textarea" :rows="4" placeholder="请输入会诊意见" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="所属医生">
|
||||||
|
<el-input v-model="formData.confirmDoctor" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="代表科室">
|
||||||
|
<el-input v-model="formData.confirmDept" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="签名医生">
|
||||||
|
<el-input v-model="formData.signDoctor" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="签名时间">
|
||||||
|
<el-input v-model="formData.signTime" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="consultationConfirmation">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import useUserStore from '@/store/modules/user'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const buildMockRows = () => ([
|
||||||
|
{
|
||||||
|
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 formData = ref({
|
||||||
|
consultationId: '',
|
||||||
|
urgent: false,
|
||||||
|
patientName: '',
|
||||||
|
gender: '',
|
||||||
|
age: '',
|
||||||
|
cardNo: '',
|
||||||
|
consultationTime: '',
|
||||||
|
invitee: '',
|
||||||
|
applyDept: '',
|
||||||
|
applyDoctor: '',
|
||||||
|
applyTime: '',
|
||||||
|
history: '',
|
||||||
|
confirmingPhysician: '',
|
||||||
|
opinion: '',
|
||||||
|
confirmDoctor: '',
|
||||||
|
confirmDept: '',
|
||||||
|
signDoctor: '',
|
||||||
|
signTime: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const confirmButtonText = computed(() => {
|
||||||
|
if (!currentRow.value) {
|
||||||
|
return '确认'
|
||||||
|
}
|
||||||
|
return currentRow.value.confirmed ? '取消确认' : '确认'
|
||||||
|
})
|
||||||
|
|
||||||
|
const canSign = computed(() => {
|
||||||
|
return !!currentRow.value && currentRow.value.confirmed && !currentRow.value.signed
|
||||||
|
})
|
||||||
|
|
||||||
|
const formatDateTime = (date = new Date()) => {
|
||||||
|
const pad = (value) => String(value).padStart(2, '0')
|
||||||
|
const yyyy = date.getFullYear()
|
||||||
|
const mm = pad(date.getMonth() + 1)
|
||||||
|
const dd = pad(date.getDate())
|
||||||
|
const hh = pad(date.getHours())
|
||||||
|
const mi = pad(date.getMinutes())
|
||||||
|
const ss = pad(date.getSeconds())
|
||||||
|
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDoctorName = () => userStore.nickName || userStore.name || '当前医生'
|
||||||
|
const getDoctorDept = () => userStore.orgName || '当前科室'
|
||||||
|
|
||||||
|
const applyRowToForm = (row) => {
|
||||||
|
if (!row) {
|
||||||
|
Object.keys(formData.value).forEach((key) => {
|
||||||
|
formData.value[key] = key === 'urgent' ? false : ''
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formData.value.consultationId = row.consultationId
|
||||||
|
formData.value.urgent = row.urgent
|
||||||
|
formData.value.patientName = row.patientName
|
||||||
|
formData.value.gender = row.gender
|
||||||
|
formData.value.age = row.age
|
||||||
|
formData.value.cardNo = row.cardNo
|
||||||
|
formData.value.consultationTime = row.consultationTime
|
||||||
|
formData.value.invitee = row.invitee
|
||||||
|
formData.value.applyDept = row.applyDept
|
||||||
|
formData.value.applyDoctor = row.applyDoctor
|
||||||
|
formData.value.applyTime = row.applyTime
|
||||||
|
formData.value.history = row.history
|
||||||
|
formData.value.confirmingPhysician = row.confirmingPhysician
|
||||||
|
formData.value.opinion = row.opinion
|
||||||
|
formData.value.confirmDoctor = row.confirmDoctor || ''
|
||||||
|
formData.value.confirmDept = row.confirmDept || ''
|
||||||
|
formData.value.signDoctor = row.signDoctor || ''
|
||||||
|
formData.value.signTime = row.signTime || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRowChange = (row) => {
|
||||||
|
currentRow.value = row
|
||||||
|
applyRowToForm(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfirm = () => {
|
||||||
|
if (!currentRow.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!currentRow.value.confirmed) {
|
||||||
|
if (!formData.value.opinion.trim()) {
|
||||||
|
ElMessage.warning('请先填写会诊意见')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!formData.value.confirmingPhysician.trim()) {
|
||||||
|
ElMessage.warning('请先填写会诊确认参加医师')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
currentRow.value.confirmed = true
|
||||||
|
currentRow.value.confirmingPhysician = formData.value.confirmingPhysician
|
||||||
|
currentRow.value.opinion = formData.value.opinion
|
||||||
|
currentRow.value.confirmDoctor = getDoctorName()
|
||||||
|
currentRow.value.confirmDept = getDoctorDept()
|
||||||
|
formData.value.confirmDoctor = currentRow.value.confirmDoctor
|
||||||
|
formData.value.confirmDept = currentRow.value.confirmDept
|
||||||
|
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 = () => {
|
||||||
|
if (!currentRow.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!currentRow.value.confirmed) {
|
||||||
|
ElMessage.warning('请先确认会诊申请')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
currentRow.value.signed = true
|
||||||
|
currentRow.value.signDoctor = getDoctorName()
|
||||||
|
currentRow.value.signTime = formatDateTime()
|
||||||
|
formData.value.signDoctor = currentRow.value.signDoctor
|
||||||
|
formData.value.signTime = currentRow.value.signTime
|
||||||
|
ElMessage.success('签名完成')
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePrint = () => {
|
||||||
|
if (!currentRow.value) {
|
||||||
|
ElMessage.warning('请先选择会诊申请')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
window.print()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRefresh = () => {
|
||||||
|
tableData.value = buildMockRows()
|
||||||
|
currentRow.value = null
|
||||||
|
applyRowToForm(null)
|
||||||
|
ElMessage.success('已刷新')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.consultation-confirmation .page-header {
|
||||||
|
padding-bottom: 8px;
|
||||||
|
border-bottom: 1px solid #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.consultation-confirmation .tab-title {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #4a89dc;
|
||||||
|
border-bottom: 2px solid #4a89dc;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
margin: 16px 0;
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-section {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.no-print {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.consultation-confirmation {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { getCurrentInstance, nextTick, onMounted, ref, computed, watch } from 'vue';
|
import { getCurrentInstance, nextTick, onMounted, ref, computed, watch } from 'vue';
|
||||||
import { getAdviceBaseInfo, getDeviceList } from './api';
|
import { getAdviceBaseInfo, getDeviceList, getConsultationActivities } from './api';
|
||||||
import { throttle, debounce } from 'lodash-es';
|
import { throttle, debounce } from 'lodash-es';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
@@ -274,8 +274,50 @@ async function getList() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const isConsumables = queryParams.adviceTypes === '2' || queryParams.adviceTypes === 2;
|
const isConsumables = queryParams.adviceTypes === '2' || queryParams.adviceTypes === 2;
|
||||||
|
const isConsultation = queryParams.adviceTypes === '5' || queryParams.adviceTypes === 5;
|
||||||
|
|
||||||
if (isConsumables) {
|
if (isConsultation) {
|
||||||
|
// 会诊类型:调用会诊项目接口
|
||||||
|
const res = await getConsultationActivities();
|
||||||
|
if (res.data && Array.isArray(res.data)) {
|
||||||
|
const result = res.data.map((item) => ({
|
||||||
|
adviceName: item.name || item.activityName,
|
||||||
|
adviceType: 5, // 会诊类型
|
||||||
|
unitCode: '111', // 次
|
||||||
|
unitCode_dictText: '次',
|
||||||
|
minUnitCode: '111',
|
||||||
|
minUnitCode_dictText: '次',
|
||||||
|
volume: '',
|
||||||
|
partPercent: 1,
|
||||||
|
priceList: item.price ? [{ price: item.price }] : [],
|
||||||
|
inventoryList: [],
|
||||||
|
adviceDefinitionId: item.id || item.activityId,
|
||||||
|
chargeItemDefinitionId: item.id || item.activityId,
|
||||||
|
positionId: '',
|
||||||
|
positionName: '',
|
||||||
|
dose: 0,
|
||||||
|
doseUnitCode: '111',
|
||||||
|
doseUnitCode_dictText: '次',
|
||||||
|
injectFlag: 0,
|
||||||
|
injectFlag_enumText: '否',
|
||||||
|
skinTestFlag: 0,
|
||||||
|
skinTestFlag_enumText: '否',
|
||||||
|
categoryCode: 31, // 会诊的category_enum
|
||||||
|
unitPrice: item.price || 0,
|
||||||
|
...item,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 缓存结果
|
||||||
|
searchCache.set(cacheKey, {
|
||||||
|
data: result,
|
||||||
|
timestamp: Date.now()
|
||||||
|
});
|
||||||
|
|
||||||
|
adviceBaseList.value = result;
|
||||||
|
} else {
|
||||||
|
adviceBaseList.value = [];
|
||||||
|
}
|
||||||
|
} else if (isConsumables) {
|
||||||
const deviceQueryParams = {
|
const deviceQueryParams = {
|
||||||
pageNo: queryParams.pageNum || 1,
|
pageNo: queryParams.pageNum || 1,
|
||||||
pageSize: queryParams.pageSize || 1000,
|
pageSize: queryParams.pageSize || 1000,
|
||||||
|
|||||||
@@ -894,3 +894,90 @@ export function deleteInspectionApplication(id) {
|
|||||||
method: 'delete',
|
method: 'delete',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 会诊相关接口 ==========
|
||||||
|
/**
|
||||||
|
* 获取会诊列表
|
||||||
|
*/
|
||||||
|
export function getConsultationList(queryParams) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/list',
|
||||||
|
method: 'get',
|
||||||
|
params: queryParams,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存会诊申请
|
||||||
|
*/
|
||||||
|
export function saveConsultation(data) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/save',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交会诊申请
|
||||||
|
*/
|
||||||
|
export function submitConsultation(queryParams) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/submit',
|
||||||
|
method: 'post',
|
||||||
|
params: queryParams,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 作废会诊申请
|
||||||
|
*/
|
||||||
|
export function cancelConsultation(queryParams) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/cancel',
|
||||||
|
method: 'post',
|
||||||
|
params: queryParams,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束会诊申请
|
||||||
|
*/
|
||||||
|
export function completeConsultation(consultationId) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/complete',
|
||||||
|
method: 'post',
|
||||||
|
params: { consultationId },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取科室医生树
|
||||||
|
*/
|
||||||
|
export function getDepartmentTree() {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/departmentTree',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取主诊断
|
||||||
|
*/
|
||||||
|
export function getMainDiagnosis(params) {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/mainDiagnosis',
|
||||||
|
method: 'get',
|
||||||
|
params: params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会诊项目列表及价格
|
||||||
|
*/
|
||||||
|
export function getConsultationActivities() {
|
||||||
|
return request({
|
||||||
|
url: '/consultation/activities',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
1287
openhis-ui-vue3/src/views/doctorstation/components/consultation.vue
Normal file
1287
openhis-ui-vue3/src/views/doctorstation/components/consultation.vue
Normal file
File diff suppressed because it is too large
Load Diff
@@ -346,7 +346,7 @@
|
|||||||
expandOrder = [];
|
expandOrder = [];
|
||||||
// 当医嘱类型改变时,清空当前选择的项目名称,因为不同类型项目的数据结构可能不兼容
|
// 当医嘱类型改变时,清空当前选择的项目名称,因为不同类型项目的数据结构可能不兼容
|
||||||
prescriptionList[scope.$index].adviceName = undefined;
|
prescriptionList[scope.$index].adviceName = undefined;
|
||||||
adviceQueryParams.adviceType = value;
|
adviceQueryParams.adviceTypes = value; // 🎯 修复:改为 adviceTypes(复数)
|
||||||
|
|
||||||
// 根据选择的类型设置categoryCode,用于药品分类筛选
|
// 根据选择的类型设置categoryCode,用于药品分类筛选
|
||||||
if (value == 1) { // 西药
|
if (value == 1) { // 西药
|
||||||
@@ -357,6 +357,8 @@
|
|||||||
adviceQueryParams.categoryCode = ''; // 诊疗不需要categoryCode筛选
|
adviceQueryParams.categoryCode = ''; // 诊疗不需要categoryCode筛选
|
||||||
} else if (value == 4) { // 耗材
|
} else if (value == 4) { // 耗材
|
||||||
adviceQueryParams.categoryCode = ''; // 耗材不需要categoryCode筛选
|
adviceQueryParams.categoryCode = ''; // 耗材不需要categoryCode筛选
|
||||||
|
} else if (value == 5) { // 会诊
|
||||||
|
adviceQueryParams.categoryCode = ''; // 会诊不需要categoryCode筛选
|
||||||
} else {
|
} else {
|
||||||
adviceQueryParams.categoryCode = ''; // 全部类型
|
adviceQueryParams.categoryCode = ''; // 全部类型
|
||||||
}
|
}
|
||||||
@@ -438,6 +440,7 @@
|
|||||||
<el-tag v-if="scope.row.chargeStatus == 5" type="info">
|
<el-tag v-if="scope.row.chargeStatus == 5" type="info">
|
||||||
{{ scope.row.chargeStatus_enumText }}
|
{{ scope.row.chargeStatus_enumText }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.statusEnum == 5" type="danger">已作废</el-tag>
|
||||||
<el-tag v-else-if="scope.row.statusEnum == 2" type="success">已签发</el-tag>
|
<el-tag v-else-if="scope.row.statusEnum == 2" type="success">已签发</el-tag>
|
||||||
<el-tag v-else-if="!scope.row.requestId && scope.row.statusEnum == 1" type="warning">
|
<el-tag v-else-if="!scope.row.requestId && scope.row.statusEnum == 1" type="warning">
|
||||||
待保存
|
待保存
|
||||||
@@ -569,7 +572,7 @@ import {
|
|||||||
} from '../api';
|
} from '../api';
|
||||||
import { advicePrint, getAdjustPriceSwitchState } from '@/api/public';
|
import { advicePrint, getAdjustPriceSwitchState } from '@/api/public';
|
||||||
import adviceBaseList from '../adviceBaseList.vue';
|
import adviceBaseList from '../adviceBaseList.vue';
|
||||||
import { computed, getCurrentInstance, nextTick, ref, watch } from 'vue';
|
import { computed, getCurrentInstance, nextTick, ref, watch, onMounted, onBeforeUnmount } from 'vue';
|
||||||
import { calculateQuantityByDays } from '@/utils/his';
|
import { calculateQuantityByDays } from '@/utils/his';
|
||||||
import OrderGroupDrawer from './orderGroupDrawer';
|
import OrderGroupDrawer from './orderGroupDrawer';
|
||||||
import PrescriptionHistory from './prescriptionHistory';
|
import PrescriptionHistory from './prescriptionHistory';
|
||||||
@@ -591,7 +594,7 @@ const form = ref({
|
|||||||
});
|
});
|
||||||
const adviceQueryParams = ref({
|
const adviceQueryParams = ref({
|
||||||
searchKey: '',
|
searchKey: '',
|
||||||
adviceType: '',
|
adviceTypes: '', // 🎯 修复:改为 adviceTypes(复数)
|
||||||
categoryCode: '' // 用于筛选西药(2)和中成药(1)
|
categoryCode: '' // 用于筛选西药(2)和中成药(1)
|
||||||
});
|
});
|
||||||
const rowIndex = ref(-1);
|
const rowIndex = ref(-1);
|
||||||
@@ -664,7 +667,7 @@ const { method_code, unit_code, rate_code, distribution_category_code, drord_doc
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 删除硬编码的adviceTypeList,直接使用drord_doctor_type字典
|
// 删除硬编码的adviceTypeList,直接使用drord_doctor_type字典
|
||||||
// drord_doctor_type: 1=西药, 2=中成药, 3=诊疗, 4=耗材, 5=全部
|
// drord_doctor_type: 1=西药, 2=中成药, 3=诊疗, 4=耗材, 5=会诊, 6=全部
|
||||||
const adviceTypeList = ref([
|
const adviceTypeList = ref([
|
||||||
{
|
{
|
||||||
label: '西药',
|
label: '西药',
|
||||||
@@ -682,6 +685,10 @@ const adviceTypeList = ref([
|
|||||||
label: '耗材',
|
label: '耗材',
|
||||||
value: 4,
|
value: 4,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '会诊',
|
||||||
|
value: 5,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '全部',
|
label: '全部',
|
||||||
value: '',
|
value: '',
|
||||||
@@ -742,6 +749,8 @@ const allPrescriptionsData = ref({}); // 存储所有处方的数据,格式: {
|
|||||||
const allPrescriptionCheckStates = ref({}); // 存储每个处方的选中状态,格式: { prescriptionId: { checkedIndexes: [], checkAll: false } }
|
const allPrescriptionCheckStates = ref({}); // 存储每个处方的选中状态,格式: { prescriptionId: { checkedIndexes: [], checkAll: false } }
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
document.addEventListener('keydown', escKeyListener);
|
document.addEventListener('keydown', escKeyListener);
|
||||||
|
// 初始化时预加载组织数据,避免选择诊疗/会诊项目时显示"无数据"
|
||||||
|
getOrgList();
|
||||||
// 初始化时自动创建第一个西药处方
|
// 初始化时自动创建第一个西药处方
|
||||||
if (westernPrescriptions.value.length === 0) {
|
if (westernPrescriptions.value.length === 0) {
|
||||||
createNewPrescription();
|
createNewPrescription();
|
||||||
@@ -1144,7 +1153,7 @@ async function disposalPrint() {
|
|||||||
|
|
||||||
function handleTotalAmount() {
|
function handleTotalAmount() {
|
||||||
totalAmount.value = prescriptionList.value.reduce((accumulator, currentRow) => {
|
totalAmount.value = prescriptionList.value.reduce((accumulator, currentRow) => {
|
||||||
if (currentRow.chargeStatus != 8) {
|
if (currentRow.chargeStatus != 8 && currentRow.statusEnum != 5) {
|
||||||
return new Decimal(accumulator).add(currentRow.totalPrice || 0);
|
return new Decimal(accumulator).add(currentRow.totalPrice || 0);
|
||||||
} else {
|
} else {
|
||||||
// 跳过已退费项目,保持累加结果不变
|
// 跳过已退费项目,保持累加结果不变
|
||||||
@@ -1183,13 +1192,41 @@ function getListInfo(addNewRow) {
|
|||||||
// 关键:先等待处方列表数据获取完成
|
// 关键:先等待处方列表数据获取完成
|
||||||
isAdding.value = false;
|
isAdding.value = false;
|
||||||
const res = await getPrescriptionList(props.patientInfo.encounterId);
|
const res = await getPrescriptionList(props.patientInfo.encounterId);
|
||||||
|
|
||||||
prescriptionList.value = res.data.map((item) => {
|
prescriptionList.value = res.data.map((item) => {
|
||||||
return {
|
const contentJson = JSON.parse(item.contentJson);
|
||||||
...JSON.parse(item.contentJson),
|
|
||||||
|
// 🎯 判断是否为会诊医嘱:
|
||||||
|
// 方法1:检查 category_enum 字段(需要后端重新编译)
|
||||||
|
// 方法2:检查 contentJson 中是否包含会诊相关字段(临时方案)
|
||||||
|
const categoryEnum = contentJson?.categoryEnum || contentJson?.category_enum || item.category_enum;
|
||||||
|
const isConsultation = categoryEnum === 31 || categoryEnum === '31' ||
|
||||||
|
contentJson?.consultationType ||
|
||||||
|
contentJson?.consultationId ||
|
||||||
|
contentJson?.consultationRequestId;
|
||||||
|
|
||||||
|
let adviceType = item.adviceType;
|
||||||
|
let adviceType_dictText = item.adviceType_dictText || mapAdviceTypeLabel(item.adviceType);
|
||||||
|
|
||||||
|
// 如果是会诊类型,设置为会诊类型
|
||||||
|
if (isConsultation) {
|
||||||
|
adviceType = 5; // 前端会诊类型值为 5
|
||||||
|
adviceType_dictText = '会诊';
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
...contentJson,
|
||||||
...item,
|
...item,
|
||||||
doseQuantity: JSON.parse(item.contentJson)?.doseQuantity,
|
doseQuantity: contentJson?.doseQuantity,
|
||||||
doseUnitCode_dictText: JSON.parse(item.contentJson)?.doseUnitCode_dictText,
|
doseUnitCode_dictText: contentJson?.doseUnitCode_dictText,
|
||||||
|
// 🎯 修复:将 adviceType 和 adviceType_dictText 放在最后,确保不被 item 覆盖
|
||||||
|
adviceType: adviceType,
|
||||||
|
adviceType_dictText: adviceType_dictText,
|
||||||
|
// 🎯 修复:确保 orgId 被正确设置(从 positionId 映射)
|
||||||
|
orgId: item.positionId || item.orgId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
});
|
});
|
||||||
getGroupMarkers(); // 更新标记
|
getGroupMarkers(); // 更新标记
|
||||||
if (props.activeTab == 'prescription' && addNewRow) {
|
if (props.activeTab == 'prescription' && addNewRow) {
|
||||||
@@ -1283,7 +1320,7 @@ function handleAddPrescription(prescriptionId, showWarning = true) {
|
|||||||
// 重置查询参数
|
// 重置查询参数
|
||||||
adviceQueryParams.value = {
|
adviceQueryParams.value = {
|
||||||
searchKey: '',
|
searchKey: '',
|
||||||
adviceType: '',
|
adviceTypes: '', // 🎯 修复:改为 adviceTypes(复数)
|
||||||
categoryCode: ''
|
categoryCode: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1363,7 +1400,7 @@ function handleFocus(row, index) {
|
|||||||
let adviceType = row.adviceType || '';
|
let adviceType = row.adviceType || '';
|
||||||
|
|
||||||
// 根据医嘱类型设置筛选条件
|
// 根据医嘱类型设置筛选条件
|
||||||
// drord_doctor_type: 1=西药, 2=中成药, 3=诊疗, 4=耗材, 5=全部
|
// drord_doctor_type: 1=西药, 2=中成药, 3=诊疗, 4=耗材, 5=会诊
|
||||||
if (row.adviceType == 1) {
|
if (row.adviceType == 1) {
|
||||||
// 西药
|
// 西药
|
||||||
categoryCode = '2';
|
categoryCode = '2';
|
||||||
@@ -1380,6 +1417,10 @@ function handleFocus(row, index) {
|
|||||||
// 耗材:adviceType = 2(后端接口中耗材的adviceType是2)
|
// 耗材:adviceType = 2(后端接口中耗材的adviceType是2)
|
||||||
categoryCode = '';
|
categoryCode = '';
|
||||||
adviceType = 2; // 耗材类型
|
adviceType = 2; // 耗材类型
|
||||||
|
} else if (row.adviceType == 5) {
|
||||||
|
// 🎯 会诊:adviceType = 5
|
||||||
|
categoryCode = '';
|
||||||
|
adviceType = 5; // 会诊类型
|
||||||
} else {
|
} else {
|
||||||
// 全部(5)或其他:显示所有类型
|
// 全部(5)或其他:显示所有类型
|
||||||
categoryCode = '';
|
categoryCode = '';
|
||||||
@@ -1387,8 +1428,7 @@ function handleFocus(row, index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
adviceQueryParams.value = {
|
adviceQueryParams.value = {
|
||||||
adviceType: adviceType,
|
adviceTypes: adviceType ? adviceType.toString() : '1,2,3', // 🎯 修复:只保留 adviceTypes(复数)
|
||||||
adviceTypes: adviceType ? adviceType.toString() : '1,2,3', // 根据当前类型设置查询类型,避免显示其他类型的数据
|
|
||||||
categoryCode: categoryCode,
|
categoryCode: categoryCode,
|
||||||
searchKey: adviceQueryParams.value.searchKey || ''
|
searchKey: adviceQueryParams.value.searchKey || ''
|
||||||
};
|
};
|
||||||
@@ -1566,7 +1606,7 @@ function handleDelete() {
|
|||||||
handleEmrTreatment();
|
handleEmrTreatment();
|
||||||
updateExpandOrder([]);
|
updateExpandOrder([]);
|
||||||
isAdding.value = false;
|
isAdding.value = false;
|
||||||
adviceQueryParams.value.adviceType = undefined;
|
adviceQueryParams.value.adviceTypes = undefined; // 🎯 修复:改为 adviceTypes(复数)
|
||||||
if (sum == selectRows.length) {
|
if (sum == selectRows.length) {
|
||||||
proxy.$modal.msgSuccess('删除成功');
|
proxy.$modal.msgSuccess('删除成功');
|
||||||
return;
|
return;
|
||||||
@@ -1732,6 +1772,8 @@ function handleSave(prescriptionId) {
|
|||||||
saveAdviceType = 2; // 耗材:前端4 -> 后端2
|
saveAdviceType = 2; // 耗材:前端4 -> 后端2
|
||||||
} else if (item.adviceType == 2) {
|
} else if (item.adviceType == 2) {
|
||||||
saveAdviceType = 1; // 中成药:前端2 -> 后端1
|
saveAdviceType = 1; // 中成药:前端2 -> 后端1
|
||||||
|
} else if (item.adviceType == 5) {
|
||||||
|
saveAdviceType = 3; // 会诊:前端5 -> 后端3(诊疗类)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构造请求参数
|
// 构造请求参数
|
||||||
@@ -2105,6 +2147,10 @@ function handleSaveSign(row, index, prescriptionId) {
|
|||||||
else if (params.adviceType == 2) {
|
else if (params.adviceType == 2) {
|
||||||
params.adviceType = 1;
|
params.adviceType = 1;
|
||||||
}
|
}
|
||||||
|
// 前端5(会诊) -> 后端3 (诊疗类)
|
||||||
|
else if (params.adviceType == 5) {
|
||||||
|
params.adviceType = 3;
|
||||||
|
}
|
||||||
|
|
||||||
// 发送处理后的 params,而不是原始 row
|
// 发送处理后的 params,而不是原始 row
|
||||||
savePrescription({ adviceSaveList: [params] }).then((res) => {
|
savePrescription({ adviceSaveList: [params] }).then((res) => {
|
||||||
@@ -2122,7 +2168,7 @@ function handleSaveSign(row, index, prescriptionId) {
|
|||||||
isAdding.value = false;
|
isAdding.value = false;
|
||||||
// --- 修改结束 ---
|
// --- 修改结束 ---
|
||||||
}
|
}
|
||||||
adviceQueryParams.value.adviceType = undefined;
|
adviceQueryParams.value.adviceTypes = undefined; // 🎯 修复:改为 adviceTypes(复数)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -2211,6 +2257,8 @@ function handleSaveBatch(prescriptionId) {
|
|||||||
saveAdviceType = 2; // 耗材前端4 -> 后端2
|
saveAdviceType = 2; // 耗材前端4 -> 后端2
|
||||||
} else if (item.adviceType == 2) {
|
} else if (item.adviceType == 2) {
|
||||||
saveAdviceType = 1; // 中成药前端2 -> 后端1
|
saveAdviceType = 1; // 中成药前端2 -> 后端1
|
||||||
|
} else if (item.adviceType == 5) {
|
||||||
|
saveAdviceType = 3; // 会诊前端5 -> 后端3(诊疗类)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构造 contentJson (保持前端UI原始数据)
|
// 构造 contentJson (保持前端UI原始数据)
|
||||||
@@ -2385,11 +2433,22 @@ function setValue(row) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
getOrgList();
|
getOrgList();
|
||||||
|
// 会诊类型(adviceType == 5)和诊疗类型(adviceType == 3)的处理
|
||||||
|
if (row.adviceType == 5) {
|
||||||
|
// 会诊类型:设置默认值
|
||||||
|
prescriptionList.value[rowIndex.value].orgId = props.patientInfo.orgId; // 执行科室默认为申请医生的科室
|
||||||
|
prescriptionList.value[rowIndex.value].quantity = 1; // 执行次数默认1次
|
||||||
|
prescriptionList.value[rowIndex.value].unitPrice = row.priceList && row.priceList[0] ? row.priceList[0].price : (row.unitPrice || 0);
|
||||||
|
prescriptionList.value[rowIndex.value].totalPrice = prescriptionList.value[rowIndex.value].unitPrice;
|
||||||
|
prescriptionList.value[rowIndex.value].categoryEnum = 31; // 会诊的category_enum设置为31
|
||||||
|
} else {
|
||||||
|
// 诊疗类型(adviceType == 3)
|
||||||
prescriptionList.value[rowIndex.value].orgId = JSON.parse(JSON.stringify(row)).positionId;
|
prescriptionList.value[rowIndex.value].orgId = JSON.parse(JSON.stringify(row)).positionId;
|
||||||
prescriptionList.value[rowIndex.value].quantity = 1;
|
prescriptionList.value[rowIndex.value].quantity = 1;
|
||||||
prescriptionList.value[rowIndex.value].unitPrice = row.priceList[0].price;
|
prescriptionList.value[rowIndex.value].unitPrice = row.priceList[0].price;
|
||||||
prescriptionList.value[rowIndex.value].totalPrice = row.priceList[0].price;
|
prescriptionList.value[rowIndex.value].totalPrice = row.priceList[0].price;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选择组套
|
// 选择组套
|
||||||
|
|||||||
@@ -169,6 +169,9 @@
|
|||||||
<el-tab-pane label="报告查询" name="reportQuery">
|
<el-tab-pane label="报告查询" name="reportQuery">
|
||||||
<ReportQuery :patientInfo="patientInfo" ref="reportQueryRef" />
|
<ReportQuery :patientInfo="patientInfo" ref="reportQueryRef" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="会诊" name="consultation">
|
||||||
|
<Consultation :patientInfo="patientInfo" :activeTab="activeTab" ref="consultationRef" />
|
||||||
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<div class="overlay" :class="{ 'overlay-disabled': disabled }" v-if="disabled"></div>
|
<div class="overlay" :class="{ 'overlay-disabled': disabled }" v-if="disabled"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -203,6 +206,7 @@ import {
|
|||||||
import prescriptionlist from './components/prescription/prescriptionlist.vue';
|
import prescriptionlist from './components/prescription/prescriptionlist.vue';
|
||||||
import RefundListDialog from './components/prescription/refundListDialog.vue';
|
import RefundListDialog from './components/prescription/refundListDialog.vue';
|
||||||
import ReportQuery from './components/reportQuery.vue';
|
import ReportQuery from './components/reportQuery.vue';
|
||||||
|
import Consultation from './components/consultation.vue';
|
||||||
import PatientList from './components/patientList.vue';
|
import PatientList from './components/patientList.vue';
|
||||||
import Diagnosis from './components/diagnosis/diagnosis.vue';
|
import Diagnosis from './components/diagnosis/diagnosis.vue';
|
||||||
import PrescriptionInfo from './components/prescription/prescriptionInfo.vue';
|
import PrescriptionInfo from './components/prescription/prescriptionInfo.vue';
|
||||||
@@ -294,6 +298,7 @@ const inspectionRef = ref();
|
|||||||
const surgeryRef = ref();
|
const surgeryRef = ref();
|
||||||
const emrRef = ref();
|
const emrRef = ref();
|
||||||
const diagnosisRef = ref();
|
const diagnosisRef = ref();
|
||||||
|
const consultationRef = ref();
|
||||||
const waitCount = ref(0);
|
const waitCount = ref(0);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
@@ -486,6 +491,9 @@ function handleClick(tab) {
|
|||||||
case 'eprescription':
|
case 'eprescription':
|
||||||
eprescriptionRef.value.getList();
|
eprescriptionRef.value.getList();
|
||||||
break;
|
break;
|
||||||
|
case 'consultation':
|
||||||
|
consultationRef.value.fetchConsultationList();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// if (tab != 'emr') {
|
// if (tab != 'emr') {
|
||||||
// if (!saveStatus.value) {
|
// if (!saveStatus.value) {
|
||||||
@@ -586,6 +594,7 @@ function handleCardClick(item, index) {
|
|||||||
surgeryRef.value.getList();
|
surgeryRef.value.getList();
|
||||||
diagnosisRef.value.getList();
|
diagnosisRef.value.getList();
|
||||||
eprescriptionRef.value.getList();
|
eprescriptionRef.value.getList();
|
||||||
|
consultationRef.value.fetchConsultationList();
|
||||||
// emrRef.value.getDetail(item.encounterId);
|
// emrRef.value.getDetail(item.encounterId);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user