接口路径: POST apply/step1
功能: 获取远程申请第一步的数据,用于初始化远程诊断申请表单
业务场景:
Route (route.php)
↓
ApplyController::step1()
↓
ApplicationService::get_step1_data($params, $token)
↓
ApplicationDao (wrapper层)
↓
ApplicationModel (SQL查询)
| 参数名 | 类型 | 说明 |
|---|---|---|
| id | string | 检查ID (exam_id) |
| 参数名 | 类型 | 说明 |
|---|---|---|
| ra_id | string | 远程申请ID (remote_application表的id),编辑时传入 |
参数说明:
id(检查ID),系统自动创建 remote_application 记录id + ra_id,系统返回已有的申请数据文件: controller/apply/ApplyController.php
public function step1(ApplicationService $service)
{
try {
// 1. 获取请求参数
$params = $this->getParams();
// 2. 参数验证(验证id是否存在)
ApplicationValidate::checkId($params);
// 3. 获取step1数据
$info = $service->get_step1_data($params, $this->getToken());
// 4. 返回结果
return $this->success($info);
} catch(\Exception $e) {
$this->throwError($e->getMessage(), 0001);
}
}
文件: servies/application/ApplicationService.php
public function get_step1_data($params, $token)
{
$id = $params['id']; // exam_id
// 情况1:编辑已有申请(传了ra_id)
if (isset($params['ra_id']) && !empty($params['ra_id'])) {
// 直接从 remote_application 表查询已有数据
$info = $this->application->getApplication($params['ra_id']);
return $info;
}
// 情况2:新建申请(没传ra_id)
else {
// 1. 定义需要查询的字段
$field = [
// exams表字段
'e.id',
'e.patient_num', // 病历号
'e.exam_datetime', // 检查时间
'e.exam_status', // 检查状态
'e.patient_id', // 患者ID
'e.study_id', // 检查UID
'e.exam_class', // 检查类型
'e.accession_num', // 检查号
'e.exam_project', // 检查项目
'e.name', // 姓名
'e.age', // 年龄
'e.sex', // 性别
'e.phone', // 手机号
'e.birthday', // 生日
'e.card_num', // 身份证号
'e.body_part', // 检查部位
'e.body_part_text', // 检查部位文本
'e.clin_symp', // 临床症状
'e.clin_diag', // 临床诊断
// register表字段
'r.exam_sub_class', // 检查子类型
'r.device_name as device', // 设备名称
'r.illness_desc', // 病情描述(患者主诉)
'r.phys_sign', // 体征
'r.anamnesis', // 既往史
'r.family_ill', // 家族史
'r.application_department as remote_department', // 开单科室
'r.ext as remark' // 备注
];
// 2. 查询检查数据(联查 exams + register)
$info = $this->application->getStep1Data($id, $field);
// 3. 获取当前用户信息
$user = $this->getUser($token);
// 4. 获取用户所在机构名称
$ins_name = $this->application->getInstitutionName($user['institution_id']);
// 5. 构造 remote_application 初始数据
$data = [
'id' => UUIDUtils::uuid(), // 申请ID(UUID)
'local_institution_id' => $user['institution_id'],
'local_institution_name' => $ins_name,
'req_date_time' => date('Y-m-d H:i:s', time()),
'name' => $info['name'],
'age' => $info['age'],
'sex' => $info['sex'],
'patient_num' => $info['patient_num'],
'accession_num' => $info['accession_num'],
'exam_id' => $info['id'],
'report_status' => 1, // 初始状态:1
'exam_class' => $info['exam_class'],
'phone' => $info['phone'],
'study_id' => $info['study_id']
];
// 6. 插入 remote_application 表(创建申请记录)
$this->application->insertAplication($data);
// 7. 将申请ID添加到返回数据中
$info['application_id'] = $data['id'];
return $info;
}
}
文件: model/application/ApplicationModel.php
public function getStep1Data($id, $field)
{
// 联查 exams 和 register 表
$info = ExamModel::alias('e')
->join(['register' => 'r'], 'r.exam_id = e.id', 'LEFT')
->where('e.id', $id)
->field($field)
->find();
return $info;
}
等价SQL:
SELECT
e.id,
e.patient_num,
e.exam_datetime,
e.exam_status,
e.patient_id,
e.study_id,
e.exam_class,
e.accession_num,
e.exam_project,
e.name,
e.age,
e.sex,
e.phone,
e.birthday,
e.card_num,
e.body_part,
e.body_part_text,
e.clin_symp,
e.clin_diag,
r.exam_sub_class,
r.device_name as device,
r.illness_desc,
r.phys_sign,
r.anamnesis,
r.family_ill,
r.application_department as remote_department,
r.ext as remark
FROM exams e
LEFT JOIN register r ON r.exam_id = e.id
WHERE e.id = :exam_id
涉及表:
exams - 检查表register - 登记表public function getApplication($id)
{
$info = $this->where('id', $id)->find();
$info['application_id'] = $id;
return $info;
}
等价SQL:
SELECT *
FROM remote_application
WHERE id = :ra_id
涉及表:
remote_application - 远程申请表public function insertAplication($info)
{
$data = $this->insert($info);
return $data;
}
等价SQL:
INSERT INTO remote_application (
id,
local_institution_id,
local_institution_name,
req_date_time,
name,
age,
sex,
patient_num,
accession_num,
exam_id,
report_status,
exam_class,
phone,
study_id
) VALUES (...)
public function getInstitutionName($id)
{
$name = InstitutionModel::where('id', $id)->value('name');
return $name;
}
等价SQL:
SELECT name
FROM institution
WHERE id = :institution_id
主要字段:
id - 检查ID(主键)patient_id - 患者IDpatient_num - 病历号exam_datetime - 检查时间exam_status - 检查状态study_id - 检查UIDexam_class - 检查类型accession_num - 检查号exam_project - 检查项目name - 姓名age - 年龄sex - 性别phone - 手机号birthday - 生日card_num - 身份证号body_part - 检查部位body_part_text - 检查部位文本clin_symp - 临床症状clin_diag - 临床诊断主要字段:
id - 登记ID(主键)exam_id - 检查ID(关联exams.id)exam_sub_class - 检查子类型device_name - 设备名称illness_desc - 病情描述(患者主诉)phys_sign - 体征anamnesis - 既往史family_ill - 家族史application_department - 开单科室ext - 备注主要字段:
id - 申请ID(主键,UUID)exam_id - 本地检查IDlocal_institution_id - 下级机构IDlocal_institution_name - 下级机构名称super_institution_id - 上级机构ID(后续步骤填写)super_institution_name - 上级机构名称(后续步骤填写)req_date_time - 申请时间report_status - 申请状态(1=初始,2=待支付,3=已支付...)name - 患者姓名age - 年龄sex - 性别phone - 手机号patient_num - 病历号accession_num - 检查号exam_class - 检查类型exam_project - 检查项目exam_sub_class - 检查子类型body_part - 检查部位body_part_text - 检查部位文本birthday - 生日card_num - 身份证号study_id - 检查UIDillness_desc - 病情描述phys_sign - 体征anamnesis - 既往史family_ill - 家族史device_name - 设备名称{
"code": 200,
"message": "成功",
"data": {
"id": "exam123456",
"application_id": "uuid-xxxx-xxxx-xxxx",
"patient_num": "P202512180001",
"exam_datetime": "2025-12-18 10:30:00",
"exam_status": 3,
"patient_id": "patient123",
"study_id": "1.2.840.113619...",
"exam_class": "CT",
"accession_num": "ACC20251218001",
"exam_project": "胸部CT平扫",
"name": "张三",
"age": "45",
"sex": "M",
"phone": "13800138000",
"birthday": "1979-05-20",
"card_num": "110101197905201234",
"body_part": "胸部",
"body_part_text": "胸部",
"clin_symp": "咳嗽、胸闷",
"clin_diag": "肺部感染?",
"exam_sub_class": "平扫",
"device": "西门子CT-01",
"illness_desc": "患者诉咳嗽2周,伴胸闷气短",
"phys_sign": "体温37.5℃,呼吸稍急促",
"anamnesis": "高血压病史5年",
"family_ill": "父亲有糖尿病",
"remote_department": "呼吸内科",
"remark": ""
}
}
{
"code": 200,
"message": "成功",
"data": {
"id": "uuid-xxxx-xxxx-xxxx",
"application_id": "uuid-xxxx-xxxx-xxxx",
"exam_id": "exam123456",
"local_institution_id": "13000003",
"local_institution_name": "某某医院",
"super_institution_id": "13000001",
"super_institution_name": "上级医院",
"req_date_time": "2025-12-18 10:30:00",
"report_status": 2,
"name": "张三",
"age": "45",
"sex": "M",
"phone": "13800138000",
"patient_num": "P202512180001",
"accession_num": "ACC20251218001",
"exam_class": "CT",
"exam_project": "胸部CT平扫",
"exam_sub_class": "平扫",
"body_part": "胸部",
"body_part_text": "胸部",
"birthday": "1979-05-20",
"card_num": "110101197905201234",
"study_id": "1.2.840.113619...",
"illness_desc": "患者诉咳嗽2周,伴胸闷气短",
"phys_sign": "体温37.5℃,呼吸稍急促",
"anamnesis": "高血压病史5年",
"family_ill": "父亲有糖尿病"
}
}
| 状态值 | 状态名称 | 说明 |
|---|---|---|
| 1 | 初始状态 | step1创建申请时的初始状态 |
| 2 | 待支付 | step2保存后,等待支付 |
| 3 | 已支付 | 支付完成,等待上级医生接诊 |
| ... | ... | 后续状态根据业务流程定义 |
新建申请:
id(检查ID)编辑申请:
id + ra_id| 字段类型 | 数据来源 |
|---|---|
| 患者基本信息 | exams表 |
| 检查信息 | exams表 + register表 |
| 申请信息 | 自动生成(机构、时间、状态) |
| 病情描述 | register表 |
@Data
@Schema(description = "远程申请Step1请求参数")
public class ApplyStep1RequestVO {
@NotBlank(message = "检查ID不能为空")
@Schema(description = "检查ID", required = true)
private String id;
@Schema(description = "远程申请ID(编辑时传入)")
private String raId;
}
@Data
@Schema(description = "远程申请Step1返回数据")
public class ApplyStep1ResponseDTO {
@Schema(description = "检查ID")
private String id;
@Schema(description = "申请ID")
private String applicationId;
@Schema(description = "病历号")
private String patientNum;
@Schema(description = "检查时间")
private String examDatetime;
@Schema(description = "检查状态")
private Integer examStatus;
@Schema(description = "患者ID")
private String patientId;
@Schema(description = "检查UID")
private String studyId;
@Schema(description = "检查类型")
private String examClass;
@Schema(description = "检查号")
private String accessionNum;
@Schema(description = "检查项目")
private String examProject;
@Schema(description = "姓名")
private String name;
@Schema(description = "年龄")
private String age;
@Schema(description = "性别")
private String sex;
@Schema(description = "手机号")
private String phone;
@Schema(description = "生日")
private String birthday;
@Schema(description = "身份证号")
private String cardNum;
@Schema(description = "检查部位")
private String bodyPart;
@Schema(description = "检查部位文本")
private String bodyPartText;
@Schema(description = "临床症状")
private String clinSymp;
@Schema(description = "临床诊断")
private String clinDiag;
@Schema(description = "检查子类型")
private String examSubClass;
@Schema(description = "设备名称")
private String device;
@Schema(description = "病情描述(患者主诉)")
private String illnessDesc;
@Schema(description = "体征")
private String physSign;
@Schema(description = "既往史")
private String anamnesis;
@Schema(description = "家族史")
private String familyIll;
@Schema(description = "开单科室")
private String remoteDepartment;
@Schema(description = "备注")
private String remark;
}
@Mapper
public interface RemoteApplicationMapper extends BaseMapper<RemoteApplication> {
/**
* 查询Step1数据(联查exams和register)
*/
ApplyStep1ResponseDTO getStep1Data(@Param("examId") String examId);
}
<select id="getStep1Data" resultType="com.zskk.pacsonline.modules.apply.dto.ApplyStep1ResponseDTO">
SELECT
e.id,
e.patient_num AS patientNum,
e.exam_datetime AS examDatetime,
e.exam_status AS examStatus,
e.patient_id AS patientId,
e.study_id AS studyId,
e.exam_class AS examClass,
e.accession_num AS accessionNum,
e.exam_project AS examProject,
e.name,
e.age,
e.sex,
e.phone,
e.birthday,
e.card_num AS cardNum,
e.body_part AS bodyPart,
e.body_part_text AS bodyPartText,
e.clin_symp AS clinSymp,
e.clin_diag AS clinDiag,
r.exam_sub_class AS examSubClass,
r.device_name AS device,
r.illness_desc AS illnessDesc,
r.phys_sign AS physSign,
r.anamnesis,
r.family_ill AS familyIll,
r.application_department AS remoteDepartment,
r.ext AS remark
FROM exams e
LEFT JOIN register r ON r.exam_id = e.id
WHERE e.id = #{examId}
</select>
@Service
@Slf4j
public class ApplyServiceImpl implements ApplyService {
@Resource
private RemoteApplicationMapper remoteApplicationMapper;
@Resource
private OrgMapper orgMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public ApplyStep1ResponseDTO getStep1Data(ApplyStep1RequestVO requestVO) {
String examId = requestVO.getId();
String raId = requestVO.getRaId();
// 情况1:编辑已有申请
if (StringUtils.isNotBlank(raId)) {
RemoteApplication application = remoteApplicationMapper.selectById(raId);
if (application == null) {
throw new RuntimeException("申请不存在");
}
ApplyStep1ResponseDTO dto = new ApplyStep1ResponseDTO();
BeanUtils.copyProperties(application, dto);
dto.setApplicationId(raId);
return dto;
}
// 情况2:新建申请
// 1. 查询检查数据
ApplyStep1ResponseDTO dto = remoteApplicationMapper.getStep1Data(examId);
if (dto == null) {
throw new RuntimeException("检查不存在");
}
// 2. 获取当前用户机构信息
String currentOrgId = getCurrentUserOrgId();
Org org = orgMapper.selectById(currentOrgId);
if (org == null) {
throw new RuntimeException("机构不存在");
}
// 3. 创建 remote_application 记录
RemoteApplication application = new RemoteApplication();
application.setExamId(examId);
application.setLocalInstitutionId(currentOrgId);
application.setLocalInstitutionName(org.getName());
application.setReqDateTime(new Date());
application.setName(dto.getName());
application.setAge(dto.getAge());
application.setSex(dto.getSex());
application.setPatientNum(dto.getPatientNum());
application.setAccessionNum(dto.getAccessionNum());
application.setReportStatus(1); // 初始状态
application.setExamClass(dto.getExamClass());
application.setPhone(dto.getPhone());
application.setStudyId(dto.getStudyId());
// MyBatis-Plus 自动生成 UUID
remoteApplicationMapper.insert(application);
// 4. 返回数据中包含 application_id
dto.setApplicationId(application.getId());
log.info("创建远程申请成功,examId={}, applicationId={}", examId, application.getId());
return dto;
}
/**
* 获取当前用户机构ID
*/
private String getCurrentUserOrgId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !(authentication.getPrincipal() instanceof LoginUser)) {
throw new RuntimeException("未找到登录用户信息");
}
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
return loginUser.getUser().getCurrentOrg();
}
}
@RestController
@RequestMapping("/api/apply")
@Tag(name = "远程申请管理", description = "远程诊断申请相关接口")
@Validated
public class ApplyController {
@Resource
private ApplyService applyService;
@Operation(
summary = "获取申请Step1数据",
description = "获取远程申请第一步的数据,用于初始化表单。" +
"新建申请时只传id,系统会自动创建remote_application记录;" +
"编辑申请时传id+raId,返回已有申请数据"
)
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "查询成功"),
@ApiResponse(responseCode = "400", description = "参数错误"),
@ApiResponse(responseCode = "500", description = "服务器内部错误")
})
@SystemLogHandler("获取申请Step1数据|查询")
@PostMapping("/step1")
public RestResult<?> getStep1Data(
@RequestBody @Valid ApplyStep1RequestVO requestVO) {
try {
ApplyStep1ResponseDTO dto = applyService.getStep1Data(requestVO);
return RestResult.ok("查询成功", dto);
} catch (RuntimeException e) {
return RestResult.error(e.getMessage());
} catch (Exception e) {
return RestResult.error("查询失败:" + e.getMessage());
}
}
}