apply_step2接口说明.md 11 KB

apply/step2 接口实现说明

接口信息

接口路径: POST /api/apply/step2

功能说明: 保存或更新远程申请的病例资料(第二步),完善患者临床信息


PHP项目核心逻辑分析

1. Controller 层 (ApplyController.php)

public function step2(ApplicationService $service)
{
    try{
        $params = $this->getParams();
        // 验证参数(id必填)
        ApplicationValidate::checkId($params);

        // 处理参数(将id改为exam_id)
        $param = $service->handle_save($params);

        // 保存申请单,状态设置为step3(3=完善病例资料保存继续)
        $return = $service->save_application($param, Config::get('remote_status')['step3']);

        return $this->success($return);
    }catch(\Exception $e){
        $this->throwError($e->getMessage(),0001);
    }
}

2. Service 层 (ApplicationService.php)

2.1 handle_save 方法

public function handle_save($params)
{
    $info = $params;
    $info['exam_id'] = $params['id'];  // 将id改为exam_id
    unset($info['id']);
    $info['createdAt'] = date('Y-m-d H:i:s', time());
    return $info;
}

2.2 save_application 方法(核心逻辑)

public function save_application($param, $status)
{
    $id = UUIDUtils::uuid();
    $application_id = $param['application_id'] ?? '';  // 获取申请单ID(编辑时传入)

    // 1. 准备更新数据
    $info = array();

    // 患者基本信息
    $info['name'] = $param['name'];
    $sex = $this->getSex($param['sex']);  // 性别转换
    $info['sex'] = $sex;
    $info['age'] = $param['age'];
    $info['phone'] = $param['phone'];
    $info['patient_num'] = $param['patient_num'];
    $info['accession_num'] = $param['accession_num'];
    $info['birthday'] = $param['birthday'];
    $info['card_num'] = $param['card_num'];

    // 检查信息
    $info['exam_datetime'] = $param['exam_datetime'];
    $info['exam_class'] = $param['exam_class'];
    $info['exam_project'] = $param['exam_project'];
    $info['exam_sub_class'] = $param['exam_sub_class'];
    $info['body_part'] = $param['body_part'];
    $info['body_part_text'] = $param['body_part_text'] ?? '';
    $info['exam_id'] = $param['exam_id'];
    $info['study_id'] = $param['study_id'];

    // 临床信息
    $info['illness_desc'] = $param['illness_desc'] ?? '';      // 患者主诉
    $info['phys_sign'] = $param['phys_sign'] ?? '';            // 体征
    $info['clin_symp'] = $param['clin_symp'] ?? '';            // 症状
    $info['anamnesis'] = $param['anamnesis'] ?? '';            // 疾病史
    $info['family_ill'] = $param['family_ill'] ?? '';          // 家族史
    $info['clin_diag'] = $param['clin_diag'] ?? '';            // 初步诊断
    $info['more'] = $param['more'] ?? '';                      // 补充说明
    $info['remote_department'] = $param['remote_department'] ?? '';  // 申请科室

    // 附件信息
    $info['attachment'] = $param['attachment'] ?? '';          // 补充资料
    $info['attachment_type'] = $param['attachment_type'] ?? 1; // 附件存储类型
    $info['remark'] = $param['remark'] ?? '';                  // 备注

    // 从exams表查询相关字段
    $node = $this->application->getExam($param['exam_id'], 'node_type');
    $info['node_type'] = $node['node_type'];

    $hopitalized = $this->application->getExam($param['exam_id'], 'hopitalized_no');
    $info['hopitalized_no'] = $hopitalized['hopitalized_no'];

    // 状态设置为3(完善病例资料保存继续)
    $info['report_status'] = $status;

    // 2. 更新exams表的手机号
    $this->application->updateExam($param['exam_id'], $param['phone']);

    // 3. 保存或更新remote_application
    if (!empty($application_id)) {
        // 存在则更新
        $return = $this->application->updateApplication($info, $application_id);
        $return_id = $application_id;
    } else {
        // 不存在则新建
        $info['id'] = $id;
        $return = $this->application->insertAplication($info);
        $return_id = $id;
    }

    // 4. 返回申请单ID和检查类别
    $r['id'] = $return_id;
    $r['class'] = $param['exam_class'];
    return $r;
}

请求参数

Step2RequestVO

@Data
public class ApplyStep2RequestVO {
    @NotBlank(message = "检查ID不能为空")
    private String id;  // exam_id

    private String applicationId;  // 申请单ID(编辑时传入)

    // 患者基本信息
    @NotBlank(message = "患者姓名不能为空")
    private String name;

    @NotBlank(message = "性别不能为空")
    private String sex;

    @NotBlank(message = "年龄不能为空")
    private String age;

    private String phone;
    private String patientNum;
    private String accessionNum;
    private String birthday;
    private String cardNum;

    // 检查信息
    private String examDatetime;

    @NotBlank(message = "检查类别不能为空")
    private String examClass;

    private String examProject;
    private String examSubClass;
    private String bodyPart;
    private String bodyPartText;
    private String studyId;

    // 临床信息
    private String illnessDesc;      // 患者主诉
    private String physSign;         // 体征
    private String clinSymp;         // 症状
    private String anamnesis;        // 疾病史
    private String familyIll;        // 家族史
    private String clinDiag;         // 初步诊断
    private String more;             // 补充说明
    private String remoteDepartment; // 申请科室

    // 附件信息
    private String attachment;       // 补充资料
    private Integer attachmentType;  // 附件存储类型:1=本地,2=移动云
    private String remark;           // 备注
}

响应数据

Step2ResponseDTO

@Data
public class ApplyStep2ResponseDTO {
    @Schema(description = "申请单ID")
    private String id;

    @Schema(description = "检查类别")
    private String examClass;
}

Java项目实现方案

1. Service 实现

@Override
@Transactional(rollbackFor = Exception.class)
public ApplyStep2ResponseDTO saveStep2(ApplyStep2RequestVO requestVO) {
    String examId = requestVO.getId();
    String applicationId = requestVO.getApplicationId();

    // 1. 性别转换
    String sex = StrUtils.formatSex(requestVO.getSex());

    // 2. 查询exams表获取node_type和hopitalized_no
    Exams exam = examsMapper.selectById(examId);
    if (exam == null) {
        throw new RuntimeException("检查不存在");
    }

    // 3. 准备remote_application数据
    RemoteApplication application = new RemoteApplication();

    // 患者基本信息
    application.setName(requestVO.getName());
    application.setSex(sex);
    application.setAge(requestVO.getAge());
    application.setPhone(requestVO.getPhone());
    application.setPatientNum(requestVO.getPatientNum());
    application.setAccessionNum(requestVO.getAccessionNum());
    application.setBirthday(requestVO.getBirthday());
    application.setCardNum(requestVO.getCardNum());

    // 检查信息
    application.setExamDatetime(requestVO.getExamDatetime());
    application.setExamClass(requestVO.getExamClass());
    application.setExamProject(requestVO.getExamProject());
    application.setExamSubClass(requestVO.getExamSubClass());
    application.setBodyPart(requestVO.getBodyPart());
    application.setBodyPartText(requestVO.getBodyPartText());
    application.setExamId(examId);
    application.setStudyId(requestVO.getStudyId());
    application.setNodeType(exam.getNodeType());
    application.setHopitalizedNo(exam.getHopitalizedNo());

    // 临床信息
    application.setIllnessDesc(requestVO.getIllnessDesc());
    application.setPhysSign(requestVO.getPhysSign());
    application.setClinSymp(requestVO.getClinSymp());
    application.setAnamnesis(requestVO.getAnamnesis());
    application.setFamilyIll(requestVO.getFamilyIll());
    application.setClinDiag(requestVO.getClinDiag());
    application.setMore(requestVO.getMore());
    application.setRemoteDepartment(requestVO.getRemoteDepartment());

    // 附件信息
    application.setAttachment(requestVO.getAttachment());
    application.setAttachmentType(requestVO.getAttachmentType() != null ? requestVO.getAttachmentType() : 1);
    application.setRemark(requestVO.getRemark());

    // 状态设置为3(完善病例资料保存继续)
    application.setReportStatus(3);

    // 4. 更新exams表的手机号
    Exams updateExam = new Exams();
    updateExam.setId(examId);
    updateExam.setPhone(requestVO.getPhone());
    examsMapper.updateById(updateExam);

    // 5. 保存或更新remote_application
    String returnId;
    if (StringUtils.isNotBlank(applicationId)) {
        // 编辑:更新现有申请单
        application.setId(applicationId);
        remoteApplicationMapper.updateById(application);
        returnId = applicationId;
        log.info("更新远程申请成功,applicationId={}", applicationId);
    } else {
        // 新建:创建申请单
        remoteApplicationMapper.insert(application);  // MyBatis-Plus自动生成UUID
        returnId = application.getId();
        log.info("创建远程申请成功,applicationId={}", returnId);
    }

    // 6. 返回结果
    ApplyStep2ResponseDTO response = new ApplyStep2ResponseDTO();
    response.setId(returnId);
    response.setExamClass(requestVO.getExamClass());
    return response;
}

2. Controller 实现

@PostMapping("/step2")
@Operation(summary = "保存病例资料", description = "远程申请第二步:保存或更新病例资料")
@SystemLogHandler("保存病例资料|保存")
public RestResult<?> saveStep2(@RequestBody @Valid ApplyStep2RequestVO requestVO) {
    try {
        ApplyStep2ResponseDTO response = remoteApplicationService.saveStep2(requestVO);
        return RestResult.ok("保存成功", response);
    } catch (RuntimeException e) {
        return RestResult.error(e.getMessage());
    } catch (Exception e) {
        return RestResult.error("保存失败:" + e.getMessage());
    }
}

状态说明

remote_application.report_status

状态值 说明 对应步骤
1 初始创建 step1
2 保存完善病例资料 step2(中间状态)
3 完善病例资料保存继续 step2(完成状态)
4 选择医院发起申请 step3
5 驳回申请 reject
6 接收申请 agree
7 写报告 save
8 审核报告 audit
9 最终完成报告 -
10 确认报告 confirm
11 撤回报告 -

核心业务逻辑

  1. 参数处理:将 id 字段转换为 exam_id
  2. 性别转换:统一转换为标准格式(M/F)
  3. 查询关联数据:从 exams 表获取 node_typehopitalized_no
  4. 更新exams表:同步更新患者手机号
  5. 保存或更新申请单
    • application_id:更新现有申请单
    • application_id:创建新申请单
  6. 状态设置report_status = 3(完善病例资料保存继续)
  7. 返回数据:返回 application_idexam_class

注意事项

  1. 字段完整性:step2保存了大量临床信息,这些信息在后续步骤中会被使用
  2. 幂等性:通过 application_id 判断是新建还是更新,支持多次提交
  3. 数据同步:需要同时更新 exams 表和 remote_application
  4. 状态流转:step2 完成后状态为3,为 step3(发起申请)做准备
  5. 附件处理:支持本地和移动云两种存储方式