reportDao = $reportDao; $this->xz = $xzDao; } public function check($token,$status) { $user = $this->reportDao->getUser($token); $user_id = $user['id']; $save = $this->reportAuthentication($user_id, 'save', $user['institution_id'],2); $audit = $this->reportAuthentication($user_id, 'audit', $user['institution_id'],2); $confirm = $this->reportAuthentication($user_id, 'confirm', $user['institution_id'],2); if($status != 9) { if(!($save || $audit || $confirm)) { return '2'; } } return '1'; } public function getReportDetail($examId,$isRemote,$token,$ra_id) { if(empty($ra_id)){ //本地报告详情 $detail = $this->reportDao->getReportInfo($examId); $data = json_decode(json_encode($detail),true); if(!isset($data['report_id']) || $data['report_id'] == ''){ $report_info = [ 'id'=>UUIDUtils::uuid(), 'exam_id'=>$examId, 'createdAt'=>date('Y-m-d H:i:s',time()), 'type'=>1 ]; $this->reportDao->InsertReport($report_info); // $url = 'http://wechat.pacsonline.cn/wx_patient/api/unifyGetWxQrcode?reportId='.$report_info['id'].'&version=3'; // $this->curl_get($url); $detail['report_id'] = $report_info['id']; } }else{ //远程报告详情 $detail = $this->reportDao->getRemoteReportInfo($ra_id); } $institution = $this->reportDao->getInstitutionData(['id'=>$detail['institution_id']],['id','report_subtitle','report_title']); $detail['report_title'] = $institution['report_title']; $detail['report_subtitle'] = $institution['report_subtitle']; $time = date('Y-m-d H:i:s',time()); //过期时间 大于当前 则 还没过期 $where = "effective_date > '$time'"; $dcm = $this->reportDao->getDcmPathData($where,$detail['study_id']); $detail['dcm_path'] = $dcm['dcm_path'] ?? ''; $detail['dcm_type'] = $dcm['dcm_type'] ?? '1'; if($detail['dcm_type'] != 1) { $detail['dcm_path'] = $this->makeFileUrl($dcm['dcm_path'],$dcm['dcm_type']); } // 医生姓名 $detail['report_doctor_id'] = $detail['report_doctor_id'] ?? ''; $detail['review_doctor_id'] = $detail['review_doctor_id'] ?? ''; $detail['confirm_doctor_id'] = $detail['confirm_doctor_id'] ?? ''; $detail['local_institution_name'] = $detail['local_institution_name'] ?? ''; $detail['req_doctor_name'] = $detail['req_doctor_name'] ?? ''; $detail['remote_department'] = $detail['remote_department'] ?? ''; $detail['report_id'] = $detail['report_id'] ?? ''; $detail['report_doctor_name'] = $detail['report_doctor_name'] ?? ''; $detail['review_doctor_name'] = $detail['review_doctor_name'] ?? ''; $detail['confirm_doctor_name'] = $detail['confirm_doctor_name'] ?? ''; $detail['remote_application_id'] = $detail['remote_application_id'] ?? ''; $detail['report_use_autograph'] = $detail['report_use_autograph'] ?? '0'; $detail['review_use_autograph'] = $detail['review_use_autograph'] ?? '0'; $detail['confirm_use_autograph'] = $detail['confirm_use_autograph'] ?? '0'; $detail['report_autograph'] = ($detail['report_use_autograph'] == 1) ? (empty($detail['report_autograph']) ? '' : $this->makeFileUrl($detail['report_autograph'],$detail['report_autograph_type'])) : ''; $detail['review_autograph'] = ($detail['review_use_autograph'] == 1) ? (empty($detail['review_autograph']) ? '' : $this->makeFileUrl($detail['review_autograph'],$detail['review_autograph_type'])) : ''; $detail['confirm_autograph'] = ($detail['confirm_use_autograph'] == 1) ? (empty($detail['confirm_autograph']) ? '' : $this->makeFileUrl($detail['confirm_autograph'],$detail['confirm_autograph_type'])) : ''; if(!empty($detail['report_doctor_id'])){ $insName = $this->reportDao->getInstitution($detail['report_doctor_id']); $detail['institution'] = $insName['name']; $detail['introduce'] = $insName['introduce']; }else{ $detail['institution'] = ''; $detail['introduce'] = ''; } $detail['exam_id'] = $examId; $detail['is_remote'] = $isRemote; // 操作痕迹 if(empty($detail['report_id'])){ $trace = []; }else{ $trace = $this->reportDao->getTrace($detail['report_id']); } if(!isset($detail['exam_status'])){ $detail['exam_status'] = ''; } $detail['trace'] = $trace; // 当报告处于完成状态时 不在显示暂存的草稿 if($detail['exam_status'] ?? '') { if ($detail['exam_status'] == 9) { return $detail; } } if($detail['report_status'] ?? '') { if ($detail['report_status'] == 9) { return $detail; } } // 草稿存储 $userId = $this->reportDao->getUserId($token); $cacheToken = $this->getStageKey($detail['report_id'],$userId); $stage = $this->reportDao->getStage($cacheToken); if(!empty($stage)){ $detail['impression'] = $stage['impression']; $detail['description'] = $stage['description']; } return $detail; } public function getWjDetail($examId,$isRemote) { if($isRemote == 1){ //远程 $remote = 'not null'; }else{ $remote = 'null'; } $detail = $this->reportDao->getReportInfo($examId/**,$remote*/); // 医生姓名 if(empty($detail)){ $detail['report_doctor_id'] = ''; $detail['review_doctor_id'] = ''; $detail['confirm_doctor_id'] = ''; $detail['report_id'] = ''; $detail['report_doctor_name'] = ''; $detail['review_doctor_name'] = ''; $detail['confirm_doctor_name'] = ''; } if(!empty($detail['report_doctor_id'])){ $insName = $this->reportDao->getInstitution($detail['report_doctor_id']); $detail['institution'] = $insName['name']; $detail['introduce'] = $insName['introduce']; }else{ $detail['institution'] = ''; $detail['introduce'] = ''; } $detail['exam_id'] = $examId; $detail['is_remote'] = $isRemote; if(!isset($detail['exam_status'])){ $detail['exam_status'] = ''; } $detail['trace'] = ''; return $detail; } public function save_progress($id,$token,$content,$type) { $doctor = $this->reportDao->getUser($token); $bbs = [ 'id'=>UUIDUtils::uuid(), 'initiator'=>$doctor['id'], 'remote_application_id'=>$id, 'content'=>$doctor['realname'].$content, 'createdAt'=>date('Y-m-d H:i:s',time()), 'type'=>$type ]; $this->reportDao->saveBbs($bbs); } public function updateReport($examId, $data, $type, $reportType, $token , $ra_id = null ) { // Db::startTrans(); try{ // 判断报告权限 $exam = $this->reportDao->getExam($examId); $phone = $exam['phone'] ?? ''; $studyId = $exam['study_id']; $user = $this->reportDao->getUser($token); $user_id = $user['id']; $result = $this->reportAuthentication($user_id, $type, $exam['institution_id'],$reportType); if(!$result){ $this->throwError('权限未分配,请联系管理员',0005); } $rt = ($reportType == 1) ? 2 : 1; $report = $this->reportDao->getReport($examId,$rt,$ra_id); $report = json_decode(json_encode($report,true),true); $reportId = $report['id'] ?? null; // 书写报告时新增report表数据 if(empty($reportId)){ if($type == 'save'){ $insert_data = [ 'id' => UUIDUtils::uuid(), 'exam_id' => $examId, 'createdAt' => date('Y-m-d H:i:s'), 'report_result' => 1, 'type' => $rt, 'remote_application_id' => $ra_id ]; $insert_res = $this->reportDao->insertReport($insert_data); // $url = 'http://wechat.pacsonline.cn/wx_patient/api/unifyGetWxQrcode?reportId='.$insert_data['id'].'&version=3'; // $this->curl_get($url); if($insert_res == false){ // Db::rollback(); $this->throwError('insert_report_error',0004); } $reportId = $insert_data['id']; } }else{ switch ($type) { case 'save': //已写报告 禁止其他医生点击书写按钮 if ($user_id !== $report['report_doctor_id'] && !empty($report['report_doctor_id'])) { $this->throwError('该报告已被其他医师书写,请刷新当前有页面进行查看!',0712); } break; case 'audit': //已审报告 禁止其他医生点击审核按钮 if ($user_id !== $report['review_doctor_id'] && !empty($report['review_doctor_id'])) { $this->throwError('该报告已被其他医师审核,请刷新当前有页面进行查看!',0712); } break; } } if($user['institution_id'] == '43600001') { if($type == 'save' || $type == 'audit') { // 添加锁定状态 $middle = [ 'institution_id'=>$user['institution_id'], 'status'=>0, 'doctor_id'=>$user['id'], 'doctor_name'=>$user['realname'], 'exam_id'=>$examId, 'is_sync'=>0, 'report_id'=>$reportId ]; $middleInfo = $this->reportDao->getMiddle(['exam_id'=>$examId]); $middleWhere = []; if($middleInfo) { unset($middle['is_sync']); $middleWhere = ['exam_id'=>$examId]; } $this->reportDao->saveRmiddle($middle,$middleWhere); }elseif($type == 'confirm'){ $middleWhere = ['exam_id'=>$examId]; $middleInfo = $this->reportDao->getMiddle(['exam_id'=>$examId]); if($middleInfo) { $middle = [ 'status'=>1, 'is_sync'=>0 ]; $this->reportDao->saveRmiddle($middle,$middleWhere); }else{ $middle = [ 'institution_id'=>$user['institution_id'], 'status'=>1, 'doctor_id'=>$user['id'], 'doctor_name'=>$user['realname'], 'exam_id'=>$examId, 'is_sync'=>0, 'report_id'=>$reportId ]; $this->reportDao->saveRmiddle($middle); } } } // 修改基本信息 $notUpdateType = [ 'confirm' ]; // 不需要更改的类型 if(!in_array($type, $notUpdateType)){ switch ($data['sex']){ case 'M': case '男': $sex = 'M'; break; case 'F': case '女': $sex = 'F'; break; default: $sex = $data['sex']; break; } $update = [ 'name' => $data['name'], 'sex' => $sex, 'age' => $data['age'], 'exam_class' => $data['exam_class'], 'exam_project' => $data['exam_project'] ?? null, ]; if($rt == 1){ $update['phone'] = $data['phone']; $exam_res = $this->reportDao->updateExamMsg($examId, $exam['patient_id'], $update); if($exam_res == false){ // Db::rollback(); $this->throwError('update_msg_error',0003); } }else{ $update['phone'] = $data['phone']; $remote_res = $this->reportDao->updateRemote($ra_id, $update); if($remote_res == false){ // Db::rollback(); $this->throwError('update_msg_error',0003); } } } // 修改报告数据 $report_up = [ 'impression' => $data['impression'] ?? null, 'description' => $data['description'] ?? null, 'report_result' => $data['report_result'] ?? null ]; $sms = $this->reportDao->getInstitutionSms($user['institution_id']); switch ($reportType){ case '2': // 本地报告 $report_res = $this->updateReportData($examId, $report_up, $type, $exam['exam_status'], $user, $reportType); break; case '1': // 远程报告 $report_res = $this->updateReportData($examId, $report_up, $type, $exam['exam_status'], $user, $reportType , $ra_id); break; default : $report_res = false; break; } if($type == 'confirm'){ $this->reportDao->delCache($reportId.'_local'); if($sms == '1' && !empty($phone)){ $insName = $this->reportDao->getInstitutionName($user['institution_id']); // 发送确认短信 $sms = $this->sendSms($phone,$reportId,$examId,$studyId,$insName,$user['institution_id']); } $wechat_url = Config::get('wechat_url'); // 二维码生成 $url = $wechat_url.'/wx_patient/api/unifyGetWxQrcode?reportId='.$reportId.'&version=3'; $this->curl_get($url); if($reportType == 1 && !empty($ra_id)){ //远程确认区间 $money = $this->reportDao->getOrderMoney($ra_id); if($money != 0){ $current_money = $this->reportDao->getCurrentMoney($user['institution_id']); $max_money = $current_money + $money; $this->reportDao->updateInstititonMoney($user['institution_id'],$max_money); } //修改订单状态为已确认 $this->reportDao->updateOrder($ra_id,Config::get('ORDER_STATUS')['CONFIRM']); $wechat = New WechatService(); $order_id = $this->reportDao->getOrderId($ra_id); // 微信推送确认 $w = $wechat->pushWechatComplete($order_id); } //确认推送微信公众号 if(!empty($exam['id'])){ $data = $this->xz->getPushInfo($exam['id']); $pushType = 6; $cont = [ 'name'=>$exam['name'], 'exam_id'=>$exam['id'], 'modality'=>$exam['exam_class'], 'examDate'=>$exam['exam_datetime'], 'report_id'=>$reportId ]; $content = json_encode($cont,true); $openids = $this->xz->getOpenId($data); foreach ($openids as $k=>$v){ // 推送4.0公众号消息 $this->new_wechat_push($v,$pushType,$content); } } } if($report_res == false){ // Db::rollback(); $this->throwError('update_report_error',0006); } if(isset($reportId) && !empty($reportId)){ // 草稿 $key = $this->getStageKey($reportId, $user_id); $stage = $this->reportDao->getStage($key); if($stage){ $this->reportDao->delStage($key); } } // 成功 // Db::commit(); // if($type == 'confirm'){ // $this->getExamPush($examId); // } return true; } catch (Exception $exception){ $this->throwError($exception->getMessage(),0001); } } public function rejectAudit($id,$reason,$user) { $field = ['report_doctor_id','exam_id']; $write = $this->reportDao->getReportById($id,$field); //获取当前医生账号权限 $now_authority = $this->reportDao->getDoctorClass($user['id']); $now_authority = explode(',',$now_authority); if(!in_array('3',$now_authority)) { $this->throwError('do_not_have_permission',0005); } $update = ['report']; // 更改状态为审核驳回 $this->reportDao->updateExamStatus($write['exam_id'],12); $this->reportDao->updateReport($write['exam_id'],1,['review_doctor_id'=>null,'review_doctor_name'=>null,'review_datetime'=>null]); $data = [ 'id' => UUIDUtils::uuid(), 'title' => '您写的报告有最新消息,请注意查收', 'content' => $user['realname'].'医师驳回了您写得报告,驳回原因是:'.$reason, 'count' => '1', 'type' => '9', 'ctime' => date('Y-m-d H:i:s', time()), 'exam_id' => $write['exam_id'], 'doctor_id'=>$write['report_doctor_id'] ]; $this->reportDao->insertMessage($data); return true; } public function sendSms($phone,$reportId,$examId,$studyId,$institution,$insId) { $code = rand(0,9).rand(0,9).rand(0,9).rand(0,9); $id = UUIDUtils::uuid(); if(empty($phone)){ $send_message = 0; }else{ //发送短信 $note = [ 'long_url'=>'https://wc.pacsonline.cn/#/jump?id='.$id ]; $noteId = $this->reportDao->insertNote($note); $nid = base64_encode(str_pad(base_convert($noteId,10,36),6,'0',STR_PAD_LEFT)); if($insId == '43600001') { $send = send_message::sendEZShortMessage($phone,$code,$nid); }elseif($insId == '03060002'){ $send = send_message::sendReportShortMessage($phone,$institution); }else{ $send = send_message::sendExam2ShortPatient($phone,$code,$institution,$nid); } $data = json_decode(json_encode($send),true); if($data['Code'] == 'OK'){ $send_message = 1; }else{ $send_message = 0; } } // $share = [ // 'id'=>$id, // 'report_id'=>$reportId, // 'exam_id'=>$examId, // 'code'=>$code, // 'send_time'=>time(), // 'expires_time'=>time()+86400*7, // 'send_message'=>$send_message, // 'url'=>'', // 'phone'=>$phone, // 'study_id'=> $studyId // ]; $share = [ 'id'=>$id, 'examId'=>$examId, 'status'=>1, 'overdueTime'=>7, 'code'=>$code, 'short_url'=>'', 'phone'=>$phone, 'report_isset'=>1, 'study_id'=>$studyId, 'send_message'=>$send_message, ]; $this->reportDao->insertShare($share); } public function getExamPush($id) { try{ $xzData = $this->reportDao->getXzData($id); $report = $this->reportDao->getReport($id,1); $reportName = $this->reportDao->getDoctorName($report['report_doctor_id']); $reviewName = $this->reportDao->getDoctorName($report['review_doctor_id']); $studyUid = $this->reportDao->getUid($id); $accessionNum = $this->reportDao->getAccession($id); $info = [ 'report'=>[ 'department'=>$xzData['department'], 'clinicalDoctor'=>$xzData['clinicalDoctor'], 'symptom'=>$xzData['symptom'], 'reportDate'=>$report['report_datetime'], 'description'=>$report['description'], 'impression'=>$report['impression'], 'reportDoctor'=>$reportName, 'reviewDoctor'=>$reviewName, 'studyInstanceUId'=>$studyUid, 'modality'=>$xzData['modality'], 'accessionNumber'=>$accessionNum ], 'applicationFormNo'=>$xzData['applicationFormNo'], 'clinicId'=>$xzData['clinicId'], ]; $data = json_encode($info); $url = 'http://wjw.yidab.cn:801/pacs/pushExamReport.do'; // $url = 'http://wjw.yidab.cn:801/wjw-test/pacs/pushExamReport.do'; $return = $this->curlJsonPost($url,$data); return $return; }catch(\Exception $e){ return json_encode(['code'=>'1','message'=>$e->getMessage()]); } } public function reportAuthentication($user_id, $type, $institution_id = null,$type_report) { // 获取权限列表 $doctor_authority = [ 'clinical' => 1, // 临床医生 'report' => 2, // 报告医生 'audit' => 3, // 审核医生 'confirm' => 4, // 确认医生 'register' => 5, // 登记医生 'remote_apply' => 6, // 远程申请医生 'remote_report' => 7, // 远程报告医生 'remote_audit' => 8, // 远程审核医生 'local_reject' => 9, // 本地完成状态打回已写医生 'local_del' => 10, // 本地影像删除 ]; // 当前账号权限 $now_authority = $this->reportDao->getDoctorClass($user_id); if(empty($now_authority)){ return false; } $now_authority = explode(',', $now_authority); // 判断权限 switch ($type){ case 'save': if($type_report == '2'){ $require = $doctor_authority['report']; }else{ $require = $doctor_authority['remote_report']; } if(!in_array($require, $now_authority)){ return false; } break; case 'audit': if($type_report == '2'){ $require = $doctor_authority['audit']; }else{ $require = $doctor_authority['remote_audit']; } if(!in_array($require, $now_authority)){ return false; } break; case 'confirm': $require = $doctor_authority['confirm']; if(!in_array($require, $now_authority)){ return false; } break; case 'reject': $require = $doctor_authority['local_reject']; if(!in_array($require, $now_authority)){ return false; } break; case 'del': $require = $doctor_authority['local_del']; if(!in_array($require, $now_authority)){ return false; } break; default : return false; } // 成功 return true; } public function stageReport($exam_id, $token, $data, $isRemote,$report_id) { try{ if($isRemote == 2){ // 本地 $remote = 1; }else{ // 远程 1区间 $remote = 2; } if(!$report_id){ // 创建一条数据 $insert_data = [ 'id' => UUIDUtils::uuid(), 'exam_id' => $exam_id, 'createdAt' => date('Y-m-d H:i:s'), 'report_result' => 1, 'type' => $remote ]; if($remote == 2){ //远程进入 $applicationId = $this->reportDao->getApplicationId($exam_id); $insert_data['remote_application_id'] = $applicationId; } $res = $this->reportDao->insertReport($insert_data); // $url = 'http://wechat.pacsonline.cn/wx_patient/api/unifyGetWxQrcode?reportId='.$insert_data['id'].'&version=3'; // $this->curl_get($url); if($res == false){ $this->throwError('insert_report_error',0006); } $report_id = $insert_data['id']; } // 存储 $user_id = $this->reportDao->getUserId($token); $key = $this->getStageKey($report_id, $user_id); $this->reportDao->saveCache($key,$data,604800); // 成功 return $key; } catch (Exception $exception){ $this->throwError($exception->getMessage(),0001); } } public function getPrintData($reportId,$is_remote) { try{ $wechat = Config::get('wechat_url'); $url = $wechat.'/wx_patient/api/unifyGetWxQrcode?reportId='.$reportId.'&version=3'; $this->curl_get($url); $detail = $this->reportDao->getPrintInfo($reportId,$is_remote); $field = ['IS_USE_AUTOGRAPH AS is_use_autograph','AUTOGRAPH AS autograph','AUTOGRAPH_TYPE AS autograph_type']; if(empty($detail['report_doctor_id'])) { $detail['report_use_autograph'] = ''; $detail['report_autograph'] = ''; }else{ $report_autograph = $this->reportDao->getDoctorInfo($detail['report_doctor_id'],$field); $detail['report_use_autograph'] = $report_autograph['is_use_autograph'] ?? ''; $detail['report_autograph'] = empty($report_autograph['autograph'] ?? '') ? '' : $this->makeFileUrl($report_autograph['autograph'],$report_autograph['autograph_type']); $detail['report_autograph_type'] = $report_autograph['autograph_type']; } if(empty($detail['review_doctor_id'])) { $detail['review_use_autograph'] = ''; $detail['review_autograph'] = ''; }else{ $review_autograph = $this->reportDao->getDoctorInfo($detail['review_doctor_id'],$field); $detail['review_use_autograph'] = $review_autograph['is_use_autograph'] ?? ''; $detail['review_autograph'] = empty($review_autograph['autograph'] ?? '') ? '' : $this->makeFileUrl($review_autograph['autograph'],$review_autograph['autograph_type']); $detail['review_autograph_type'] = $review_autograph['autograph_type']; } if($detail['exam_class'] == 'DX' && ($detail['institution_id'] ?? '') == '73000003') { $detail['exam_class'] = 'DR'; } $detail['age'] = str_replace('W','周',str_replace('D','天',str_replace('M','月',str_replace('Y','岁',ltrim($detail['age'],'0'))))); return $detail; } catch (Exception $exception){ $this->throwError($exception->getMessage(),0001); } } public function makeChineseData($data) { switch ($data['sex']) { case 'F': $sex = '女'; break; case 'M': $sex = '男'; break; default: $sex = '未知'; } $arr = [ '医院名称'=>$data['institution_name'], '地址'=>'', '科室名称'=>'', '检查设备名称'=>'', '检查时间'=>$data['exam_datetime'], '审核时间'=>$data['review_datetime'], '姓名'=>$data['name'], '性别'=>$sex, '年龄'=>$data['age'], '检查号'=>$data['accession_num'], '病案号'=>'', '检查项目'=>$data['exam_project'], '检查方法'=>$data['exam_class'], '检查部位'=>$data['body_part'], '检查参数'=>'', '征象描述'=>$data['description'], '结论和建议'=>$data['impression'], ]; return $arr; } public function getQrCode($code,$examId) { $url = 'https://wechat.pacsonline.cn/wx_patient/api/unifyGetWxQrcode?examId='.$examId.'&version=3'; if(empty($code)) { $qrCode = $this->curl_get($url); }else{ $arr = json_decode($code,true); $time = strtotime($arr['expipy']); if(time() > $time) { $qrCode = $this->curl_get($url); }else{ $qrCode = $code; } } return json_decode($qrCode,true); } public function updateReportData($exam_id, $data, $type, $exam_status, $user, $report_type,$id = null) { try{ $status = ''; $doctorId = ''; if($id !== null){ $remote = $this->reportDao->getReportStatus($id); $status = $remote['report_status']; $doctorId = $remote['remote_doctor_id']; } // 判断类型 switch ($type){ case 'save': // 本地保存 if($report_type == 2){ $write = $this->reportDao->getExam($exam_id); if($write['write_report'] != 1) { //不等于1 则走正常流程 if($exam_status != 3 && $exam_status != 7 && $exam_status != 12){ $this->throwError('流程顺序错误,无法书写报告','0033'); } } }else{ // 远程 if($doctorId != $user['id']){ $this->throwError('非受邀医生无法书写报告','0034'); } if($status != 6 && $status != 7){ $this->throwError('流程顺序错误,无法书写报告','0033'); } $this->saveProgressLog($user,6,$id); } $update = [ 'impression' => $data['impression'], 'description' => $data['description'], 'report_result' => $data['report_result'], 'report_datetime' => date('Y-m-d H:i:s'), 'report_doctor_id'=> $user['id'], 'report_doctor_name' =>$user['realname'] ]; $exam_up_status = 7; $trace_type = 1; break; case 'audit': if($report_type == 2){ if($exam_status != 8 && $exam_status != 7){ $this->throwError('流程顺序错误,无法审核报告','0033'); } }else{ if($status != 8 && $status != 7){ $this->throwError('流程顺序错误,无法审核报告','0033'); } $this->saveProgressLog($user,7,$id); } $update = [ 'impression' => $data['impression'], 'description' => $data['description'], 'report_result' => $data['report_result'], 'review_datetime' => date('Y-m-d H:i:s'), 'review_doctor_id'=> $user['id'], 'review_doctor_name'=>$user['realname'] ]; $exam_up_status = 8; $trace_type = 2; break; // 本地审核 case 'confirm': if($report_type == 2){ if($exam_status != 8){ $this->throwError('流程顺序错误,无法确认报告','0033'); } }else{ if($status != 10){ $this->throwError('流程顺序错误,无法确认报告','0033'); } $this->saveProgressLog($user,9,$id); } if(!empty($id)){ $this->reportDao->readMessage($id); } $update = [ 'confirm_datetime' => date('Y-m-d H:i:s'), 'confirm_doctor_id'=> $user['id'], 'confirm_doctor_name'=>$user['realname'] ]; $exam_up_status = 9; $trace_type = 3; break; // 本地确认 default: return false; } // 判断远程还是本地 switch ($report_type){ case '2'; //本地 $result = $this->reportDao->updateReport($exam_id,1,$update); // 修改状态 $this->reportDao->updateExamStatus($exam_id,$exam_up_status); break; case '1': $result = $this->reportDao->updateRemoteReport($id,$update); // 修改远程状态 $this->reportDao->updateRemoteStauts($id,$exam_up_status); $this->reportDao->updateremoteExamStatus($exam_id,$exam_up_status); break; default : return false; } if(!$result){ return false; } if($report_type == '2'){ $rid = $this->reportDao->getReportId($exam_id,1); }else{ $rid = $this->reportDao->getRemoteReportId($id); } /*$detail = $this->reportDao->getReport($exam_id,$report_type); $cacheToken = $this->getStageKey($rid,$user_id,$detail['exam_status']); $stage = $this->reportDao->remoteStage($cacheToken);*/ // 添加报告痕迹 $trace = [ 'id' => UUIDUtils::uuid(), 'impression' => $update['impression'] ?? '', 'description' => $update['description'] ?? '', 'report_result' => $update['report_result'] ?? '', 'report_id' => $rid, 'createdAt' => date('Y-m-d H:i:s'), 'doctor_id' => $user['id'], 'type' => $trace_type ]; $result = $this->reportDao->insertReportRecord($trace); if(!$result){ return false; } // 成功 return true; } catch (DbException $exception){ $this->throwError($exception->getMessage(),0001); } } public function saveProgressLog($doctor,$step,$id) { $pay_log = [ 'id'=>UUIDUtils::uuid(), 'operator_id'=>$doctor['id'], 'operator_name'=>$doctor['realname'], 'current_step'=>$step, 'application_id'=>$id ]; $this->reportDao->savePregressLog($pay_log); } public function save_video_url($params) { $data = [ 'exam_id'=>$params['exam_id'], 'status'=>1 ]; $where = ['id'=>$params['id']]; $return = $this->reportDao->saveVideo($data,$where); return $return; } public function cancel_video($id) { $info = $this->reportDao->cancel_video($id); return $info; } public function getVideo($params) { $id = $params['exam_id'] ?? null; if(!$id) { $this->throwError('无效的id值','0064'); } $video = $this->reportDao->getVideo($id); foreach ($video as $k=>$v) { $video[$k]['video_url'] = $this->makeFileUrl($v['video_url'],$v['video_type'],'inline'); } return $video; } public function checkWrite($params,$doctor,$cache) { $data = ['id'=>$params['report_id'],'name'=>$doctor['realname'],'did'=>$doctor['id']]; if(empty($cache)) { $this->reportDao->setCache($params['report_id'].'_local',$data,7200); }else{ if($doctor['id'] !== $cache['did']) { //当前医生不属于第一个进入且存储的医生 $this->throwError($cache['name'],'0067'); } } return true; } // https://query.pacsonline.cn/query/url?&study_id='.$study.'&version=V1.2.0.0 public function getDcmZip($study,$email='',$come='',$examId='',$examClass='') { ignore_user_abort(true); // 后台运行,不受前端断开连接影响 set_time_limit(0); // ob_end_clean();//清除之前的缓冲内容,这是必需的,如果之前的缓存不为空的话,里面可能有http头或者其它内容,导致后面的内容不能及时的输出 header("Connection: close");//告诉浏览器,连接关闭了,这样浏览器就不用等待服务器的响应 header("HTTP/1.1 200 OK"); //可以发送200状态码,以这些请求是成功的,要不然可能浏览器会重试,特别是有代理的情况下 ob_start();//开始当前代码缓冲 if(empty($come)) { $result = [ 'code' => 0, 'msg' => '请求成功', 'data' => '文件生成中', 'error' => null, 'timestamp' => time(), 'random' => null, 'signature' => null, 'request_timestamp' => ZskkDefaultRequest::instance()->header()['zskk-timestamp'] ?? null ]; echo json_encode($result); } //下面输出http的一些头信息 $size = ob_get_length(); header("Content-Length: $size"); ob_end_flush();//输出当前缓冲 flush();//输出PHP缓冲 //在Yii2框架下,上面代码可能不会立即返回给客户端,所以需要加如下的代码,即可实现立即返回给客户端 //具体可查看此文章:http://www.lampnick.com/php/375 if (function_exists("fastcgi_finish_request")) { fastcgi_finish_request(); /* 响应完成, 关闭连接 */ } ignore_user_abort(true); // 后台运行,这个只是运行浏览器关闭,并不是直接就中止返回200状态。 try { set_time_limit(0); ini_set('memory_limit','1280M'); $study = str_replace('&node_type=1','',$study); $this->reportDao->insertDcmCompress(['status'=>1,'study_id'=>$study]); $path = $this->runRack($study,1); $typeData = $this->reportDao->getDcmPathData([],$study); $type = $typeData['dcm_type'] ?? 1; if(strrpos($path,'zip') !== false && file_exists($path)) { $type = $this->uploadZip($path,$study); } if(!empty($email) /* && $come == 'weChat' */) { if(strrpos($path,'zip') !== false) { $name = $this->reportDao->getPatientName($study); // 存在zip压缩文件 $this->sendEmail($email,$path,$name,$type); $this->reportDao->insertDcmCompress(['status'=>9,'study_id'=>$study]); log::record('邮件发送完毕'); $this->reportDao->updateEmailStatus($email,$study); } } if($come == 'ai') { if(strrpos($path,'zip') !== false) { // 存在zip压缩文件 $url = 'http://deeplearning.lib.sjtu.edu.cn/'; // $url = 'http://127.0.0.1:5000/'; $data = [ 'zip' => new \CURLFile(APP_PATH.'/'.$path), 'exam_id'=>$examId,'exam_class'=>$examClass]; $re = $this->curlPost($url,$data); if($re == false) { log::record("返回值为false"); return "返回值为false"; } $reData = json_decode($re,true); if(empty($reData[0] ?? null)) { log::record('ai接口返回错误,返回信息'.$re); return $re; } $reportData = [ 'id'=>UUIDUtils::uuid(), 'impression'=>$reData[0]['diagnosis'], 'description'=>$reData[0]['describe'], 'type'=>3, 'exam_id'=>$examId, 'report_doctor_name'=>'ai报告医生', 'review_doctor_name'=>'ai报告医生', 'confirm_doctor_name'=>'ai报告医生', 'report_datetime'=>date('Y-m-d H:i:s'), 'review_datetime'=>date('Y-m-d H:i:s'), 'confirm_datetime'=>date('Y-m-d H:i:s') ]; $aiData = $this->reportDao->getReport($examId,3); if($aiData) { //修改ai报告 $this->reportDao->updateReport($examId,3,$reportData); }else{ $this->reportDao->insertReport($reportData); } return $re; } } }catch (\think\Exception $e) { try { $this->reportDao->insertDcmCompress(['status'=>999,'study_id'=>$study,'msg'=>$e->getMessage(),'email'=>$email]); }catch (\think\Exception $exception) { $this->reportDao->insertDcmCompress(['status'=>998,'study_id'=>$study,'msg'=>mb_convert_encoding($e->getMessage(), 'UTF-8', 'GBK'),'email'=>$email]); } } } public function sendDcm($sendData,$study,$examId='',$examClass='') { $this->reportDao->saveDcmReportData($sendData,$examId,1,$this->ts_time()); $exam = $this->reportDao->getExam($examId); $url = 'http://deeplearning.lib.sjtu.edu.cn/'; // $url = 'http://127.0.0.1:5000/'; // $url = 'http://49.7.230.34:5000/'; $query = Config::get('query_url'); $data = [ 'down_url' => $query.'/query/down?&study_id='.$study.'&version=V1.2.0.0', // 'zip' => new \CURLFile(APP_PATH.'/'.$path), 'exam_id'=>$examId, 'exam_class'=>$examClass, 'exam_project'=>empty($exam['exam_project']) ? '' : $exam['exam_project'], 'is_chest'=>($exam['body_part'] == 'CHEST' || strpos($exam['body_part'],'胸') !== false) ? 1 : 0 ]; $this->reportDao->saveDcmReportData(json_encode($data),$examId,2,$this->ts_time()); $re = $this->curlPost($url,$data); $this->reportDao->saveDcmReportData('',$examId,3,$this->ts_time()); $this->reportDao->saveDcmReportData('',$examId,4,$this->ts_time()); return $re; } public function testGetDcmZip($study,$email='',$come='',$examId='',$examClass='') { $path = $this->runDirRack($study,$examId); if($come == 'ai') { if(strrpos($path,'zip') !== false) { // 存在zip压缩文件 $url = 'http://deeplearning.lib.sjtu.edu.cn/'; // $url = 'http://127.0.0.1:5000/'; $data = [ 'zip' => new \CURLFile(APP_PATH.'/'.$path), 'exam_id'=>$examId,'exam_class'=>$examClass]; $re = $this->curlPost($url,$data); if($re == false) { log::record("返回值为false"); return "返回值为false"; } $reData = json_decode($re,true); if(empty($reData[0] ?? null)) { log::record('ai接口返回错误,返回信息'.$re); return $re; } $reportData = [ 'id'=>UUIDUtils::uuid(), 'impression'=>$reData[0]['diagnosis'], 'description'=>$reData[0]['describe'], 'type'=>3, 'exam_id'=>$examId, 'report_doctor_name'=>'ai报告医生', 'review_doctor_name'=>'ai报告医生', 'confirm_doctor_name'=>'ai报告医生', 'report_datetime'=>date('Y-m-d H:i:s'), 'review_datetime'=>date('Y-m-d H:i:s'), 'confirm_datetime'=>date('Y-m-d H:i:s') ]; $aiData = $this->reportDao->getReport($examId,3); if($aiData) { //修改ai报告 $this->reportDao->updateReport($examId,3,$reportData); }else{ $this->reportDao->insertReport($reportData); } return $re; }else{ return $path; } } return '生成压缩文件失败,返回'.$path.',请联系开发人员'; } public function runDirRack($study,$examId) { $dcm = $this->getCache($study.'_zip'); if(!empty($dcm)) { Log::record('已生成过'.$dcm); return '生成中'; } ini_set('max_execution_time', 6000); $time = date('Y-m-d H:i:s',time()); //过期时间 大于当前 则 还没过期 $where = "effective_date > '$time'"; $dcm = $this->reportDao->getDcmPath($where,$study); if(!empty($dcm)) { log::record('存在历史dcm地址'.$dcm); return $dcm; } $this->setCache($study.'_zip',$study,600); log::record('不存在历史地址则继续'.$study); $query = Config::get('query_url'); //外网地址 需要network 走带宽 $url = $query."/query/down?network=1&study_id=$study&version=V1.2.0.0"; //内网地址 // $url = 'https://query.pacsonline.cn/query/down?&study_id='.$study.'&version=V1.2.0.0'; $data = $this->curl_get($url); $data = json_decode($data); if(empty($data)) { log::record('没有找到dcm信息'); return 'dcm信息没有找到'; } $date = time(); $create = ROOT_PATH . 'public' . DS . 'download'.DS.$date; log::record('压缩中'); $path = $this->zipDir($data,$create,$date,$study,$examId); log::record('压缩成功'); return $path; } public function zipDir($data,$create,$date,$study,$examId) { ini_set('max_execution_time', 6000); $fileList = []; foreach ($data as $k=>$v) { $v = (array)$v; $path = $this->downLoad($v['url'],$create.DS.$v['seriesuid'].DS.$k,$create.DS.$v['seriesuid']); $fileList[] = ['path'=>$path,'series'=>$v['seriesuid']]; } $zipPath = ROOT_PATH . 'public' . DS .'zip'; $filename = $zipPath.DS."$examId.zip"; if (!file_exists($zipPath)) { mkdir($zipPath, 0777,true); @chmod($zipPath, 0777); } $zip = new \ZipArchive(); $zip->open($filename,\ZipArchive::CREATE); //打开压缩包 foreach($fileList as $file){ $zip->addFile($file['path'],$file['series'].DS.basename($file['path'])); //向压缩包中添加文件 } $zip->close(); //关闭压缩包 $insert = [ 'dcm_path'=>'zip/'.$examId.".zip", 'study_id'=>$study, 'effective_date'=>date('Y-m-d H:i:s',time()+864000), //10天有效期 ]; $this->reportDao->insertDcmPath($insert); return 'zip/'.$examId.".zip"; } public function runRack($study,$come='') { if($come != 1) { $dcm = $this->getCache($study.'_zip'); if(!empty($dcm)) { Log::record('已生成过'.$dcm); return '生成中'; } } ini_set('max_execution_time', 6000); $time = date('Y-m-d H:i:s',time()); //过期时间 大于当前 则 还没过期 $where = "effective_date > '$time'"; $dcm = $this->reportDao->getDcmPath($where,$study); if(!empty($dcm)) { log::record('存在历史dcm地址'.$dcm); return $dcm; } $this->setCache($study.'_zip',$study,600); log::record('不存在历史地址则继续'.$study); $query = Config::get('query_url'); //外网地址 需要network 走带宽 // $url = "https://query.pacsonline.cn/query/url?network=1&study_id=$study&version=V1.2.0.0"; //内网地址 $url = $query.'/query/url?&study_id='.$study.'&version=V1.2.0.0'; $data = $this->curl_get($url); $data = json_decode($data); if(empty($data)) { log::record('没有找到dcm信息'); return ''; } $this->reportDao->insertDcmCompress(['status'=>2,'study_id'=>$study]); $date = time(); $create = ROOT_PATH . 'public' . DS . 'download'.DS.$date; log::record('压缩中'); $path = $this->zip($data,$create,$date,$study); log::record('压缩成功'); return $path; } public function zip($data,$create,$date,$study) { ini_set('max_execution_time', 6000); $fileList = []; $exam = $this->reportDao->getExamByStudy($study); $this->reportDao->insertDcmCompress(['status'=>3,'study_id'=>$study]); if($exam['institution_id'] == '06300009') { $patient_num = $exam['patient_num']; $name = $exam['name']; //工人医院需要解密 if (!file_exists($create)) { mkdir($create, 0777,true); @chmod($create, 0777); } $ts = system("python3.8 /data/code/ris_server/utils/down/main.py '$patient_num' '$study' '$name' $date"); if($ts) { $files = scandir($create); foreach ($files as $v) { if($v == '.' || $v == '..') { continue; } $fileList[] = $create.DS.$v; } } }else{ foreach ($data as $k=>$v) { $path = $this->downLoad($v,$create.DS.$k,$create); $fileList[] = $path; } $zipPath = ROOT_PATH . 'public' . DS .'zip'; $filename = $zipPath.DS."$date.zip"; if (!file_exists($zipPath)) { mkdir($zipPath, 0777,true); @chmod($zipPath, 0777); } $this->reportDao->insertDcmCompress(['status'=>4,'study_id'=>$study]); $zip = new \ZipArchive(); $zip->open($filename,\ZipArchive::CREATE); //打开压缩包 foreach($fileList as $file){ $zip->addFile($file,basename($file)); //向压缩包中添加文件 } $zip->close(); //关闭压缩包 $filesDcm = scandir($create); foreach ($filesDcm as $file) { if ($file != '.' && $file != '..') { $pathDcm = $create . '/' . $file; @unlink($pathDcm); } } @rmdir($create); } $this->reportDao->insertDcmCompress(['status'=>5,'study_id'=>$study]); $path_url = 'zip/'.$date.".zip"; $insert = [ 'dcm_path'=>$path_url, 'study_id'=>$study, 'effective_date'=>date('Y-m-d H:i:s',time()+864000), //10天有效期 ]; $this->reportDao->insertDcmPath($insert); $this->delCache($study.'_zip'); $this->reportDao->insertDcmCompress(['status'=>6,'study_id'=>$study]); return $path_url; } public function uploadZip($path_url,$study) { $this->reportDao->insertDcmCompress(['status'=>7,'study_id'=>$study]); $upload = new uploadToCloud(); $s = $upload->upload($path_url,$path_url,'3','2','2','2'); if(($s['@metadata']['statusCode'] ?? '') == '200') { $this->reportDao->insertDcmCompress(['status'=>8,'study_id'=>$study]); gc_collect_cycles(); $this->reportDao->updateDcmPath(['study_id'=>$study],['dcm_type'=>4]); unlink($path_url); return 4; } return '1'; } public function changeReport($param,$token) { $user = $this->reportDao->getUser($token); $result = $this->reportAuthentication($user['id'], 'reject', $user['institution_id'],2); if(!$result){ $this->throwError('权限未分配,请联系管理员',0005); } $id = $param['id']; $info = $this->reportDao->updateExamStatus($id,7); $this->reportDao->updateReport($id,1,['review_doctor_id'=>null]); $data = [ 'exam_id'=>$id, 'doctor_id'=>$user['id'], 'doctor_name'=>$user['realname'] ]; $this->reportDao->insertReject($data); return $info; } public function checkLock($params,$token) { return ''; $user = $this->getCache($token); $id = $params['id']; $info = $this->reportDao->checkLock($id); if($user['id'] == $info['doctor_id']) { return ''; }else{ return $info['doctor_name']; } } public function sendEmail($email,$dcmPath,$name,$type=1) { $mail = new PHPMailer(true); // Passing `true` enables exceptions try { //服务器配置 $mail->CharSet ="UTF-8"; //设定邮件编码 $mail->SMTPDebug = 0; // 调试模式输出 $mail->isSMTP(); // 使用SMTP $mail->Host = 'smtp.exmail.qq.com'; // SMTP服务器 $mail->SMTPAuth = true; // 允许 SMTP 认证 $mail->Username = 'company@pacsonline.cn'; // SMTP 用户名 即邮箱的用户名 $mail->Password = 'Zskk1234'; // SMTP 密码 部分邮箱是授权码(例如163邮箱) $mail->SMTPSecure = 'ssl'; // 允许 TLS 或者ssl协议 $mail->Port = 465; // $mail->SMTPOptions = [ // 'ssl' => [ // 'verify_peer' => false, // 'verify_peer_name' => false, // 'allow_self_signed' => true // ] // ]; $mail->SMTPOptions = array( 'ssl' => array( 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true ) ); // 服务器端口 25 或者465 具体要看邮箱服务器支持 $mail->setFrom('company@pacsonline.cn', '冠医云'); //发件人 $mail->addAddress($email, ''); // 收件人 //$mail->addAddress('ellen@example.com'); // 可添加多个收件人 $mail->addReplyTo('company@pacsonline.cn', '冠医云'); //回复的时候回复给哪个邮箱 建议和发件人一致 //$mail->addCC('cc@example.com'); //抄送 //$mail->addBCC('bcc@example.com'); //密送 $zipPath = ROOT_PATH . 'public'; // $maxsize = 45 * 1024 * 1024; $mail->Subject = $name.'影像'; // if(filesize($zipPath.'/'.$dcmPath) < $maxsize) // { // //发送附件 //// $mail->addAttachment($zipPath.'a.zip'); // 添加附件 // $mail->addAttachment($zipPath.'/'.$dcmPath, $name.'.zip'); // 发送附件并且重命名 // $mail->Body = "链接将于".date('Y-m-d',time()+10*24*3600)."失效,请即时下载"; // $mail->AltBody = "链接将于".date('Y-m-d',time()+10*24*3600)."失效,请即时下载"; // }else{ //发送链接地址 //Content $mail->isHTML(true); // 是否以HTML文档格式发送 发送后客户端可直接显示对应HTML内容 if($type == 4) { $dcmPath = $this->makeFileUrl($dcmPath,$type,'attachment','+3 days'); $dcmPath = ltrim($dcmPath,'/'); $mail->Body = "下载".$name."影像"."
链接将于".date('Y-m-d',time()+3*24*3600)."失效,请及时下载"; }else { $mail->Body = "下载".$name."影像"."
链接将于".date('Y-m-d',time()+3*24*3600)."失效,请及时下载"; } // $mail->AltBody = '如果邮件客户端不支持HTML则显示此内容'; // } $mail->send(); return '邮件发送成功'; } catch (Exception $e) { // return '邮件发送失败: '; return '邮件发送失败: '.$mail->ErrorInfo; } } public function getAiReport($param) { $id = $param['exam_id']; $data = $this->reportDao->getReport($id,3); return $data; } public function deleteAiReport($param) { $id = $param['exam_id']; $data = $this->reportDao->deleteAiReport($id,3); return $data; } }