ReportService.php 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484
  1. <?php
  2. namespace app\api\servies\report;
  3. use app\api\actions\ZskkCache;
  4. use app\api\dao\xz\XzDao;
  5. use app\api\model\api\ApiModel;
  6. use app\api\request\ZskkDefaultRequest;
  7. use app\api\response\ZskkErrorResponse;
  8. use app\api\servies\wechat\WechatService;
  9. use app\api\servies\xz\XzService;
  10. use app\api\servies\ZskkDefaultService;
  11. use app\api\utils\UUIDUtils;
  12. use app\api\validate\report\ReportValidate;
  13. use app\api\dao\report\ReportDao;
  14. use app\api\servies\common\CommonService;
  15. use app\common\library\send_message;
  16. use app\common\library\uploadToCloud;
  17. use PHPMailer\PHPMailer\PHPMailer;
  18. use think\facade\Config;
  19. use think\facade\Log;
  20. use think\Db;
  21. use think\db\exception;
  22. /**
  23. * 后台控制器基类
  24. * 接口方法权限 必传参数 接口返回 错误抛出 通用参数处理
  25. */
  26. class ReportService extends ZskkDefaultService {
  27. protected $logName = "ExamService";
  28. private $reportDao = null;
  29. private $xz = null;
  30. public function __construct(ReportDao $reportDao,XzDao $xzDao) {
  31. parent::__construct();
  32. $this->reportDao = $reportDao;
  33. $this->xz = $xzDao;
  34. }
  35. public function check($token,$status)
  36. {
  37. $user = $this->reportDao->getUser($token);
  38. $user_id = $user['id'];
  39. $save = $this->reportAuthentication($user_id, 'save', $user['institution_id'],2);
  40. $audit = $this->reportAuthentication($user_id, 'audit', $user['institution_id'],2);
  41. $confirm = $this->reportAuthentication($user_id, 'confirm', $user['institution_id'],2);
  42. if($status != 9)
  43. {
  44. if(!($save || $audit || $confirm))
  45. {
  46. return '2';
  47. }
  48. }
  49. return '1';
  50. }
  51. public function getReportDetail($examId,$isRemote,$token,$ra_id)
  52. {
  53. if(empty($ra_id)){
  54. //本地报告详情
  55. $detail = $this->reportDao->getReportInfo($examId);
  56. $data = json_decode(json_encode($detail),true);
  57. if(!isset($data['report_id']) || $data['report_id'] == ''){
  58. $report_info = [
  59. 'id'=>UUIDUtils::uuid(),
  60. 'exam_id'=>$examId,
  61. 'createdAt'=>date('Y-m-d H:i:s',time()),
  62. 'type'=>1
  63. ];
  64. $this->reportDao->InsertReport($report_info);
  65. // $url = 'http://wechat.pacsonline.cn/wx_patient/api/unifyGetWxQrcode?reportId='.$report_info['id'].'&version=3';
  66. // $this->curl_get($url);
  67. $detail['report_id'] = $report_info['id'];
  68. }
  69. }else{
  70. //远程报告详情
  71. $detail = $this->reportDao->getRemoteReportInfo($ra_id);
  72. }
  73. $institution = $this->reportDao->getInstitutionData(['id'=>$detail['institution_id']],['id','report_subtitle','report_title']);
  74. $detail['report_title'] = $institution['report_title'];
  75. $detail['report_subtitle'] = $institution['report_subtitle'];
  76. $time = date('Y-m-d H:i:s',time());
  77. //过期时间 大于当前 则 还没过期
  78. $where = "effective_date > '$time'";
  79. $dcm = $this->reportDao->getDcmPathData($where,$detail['study_id']);
  80. $detail['dcm_path'] = $dcm['dcm_path'] ?? '';
  81. $detail['dcm_type'] = $dcm['dcm_type'] ?? '1';
  82. if($detail['dcm_type'] != 1)
  83. {
  84. $detail['dcm_path'] = $this->makeFileUrl($dcm['dcm_path'],$dcm['dcm_type']);
  85. }
  86. // 医生姓名
  87. $detail['report_doctor_id'] = $detail['report_doctor_id'] ?? '';
  88. $detail['review_doctor_id'] = $detail['review_doctor_id'] ?? '';
  89. $detail['confirm_doctor_id'] = $detail['confirm_doctor_id'] ?? '';
  90. $detail['local_institution_name'] = $detail['local_institution_name'] ?? '';
  91. $detail['req_doctor_name'] = $detail['req_doctor_name'] ?? '';
  92. $detail['remote_department'] = $detail['remote_department'] ?? '';
  93. $detail['report_id'] = $detail['report_id'] ?? '';
  94. $detail['report_doctor_name'] = $detail['report_doctor_name'] ?? '';
  95. $detail['review_doctor_name'] = $detail['review_doctor_name'] ?? '';
  96. $detail['confirm_doctor_name'] = $detail['confirm_doctor_name'] ?? '';
  97. $detail['remote_application_id'] = $detail['remote_application_id'] ?? '';
  98. $detail['report_use_autograph'] = $detail['report_use_autograph'] ?? '0';
  99. $detail['review_use_autograph'] = $detail['review_use_autograph'] ?? '0';
  100. $detail['confirm_use_autograph'] = $detail['confirm_use_autograph'] ?? '0';
  101. $detail['report_autograph'] = ($detail['report_use_autograph'] == 1) ? (empty($detail['report_autograph']) ? '' : $this->makeFileUrl($detail['report_autograph'],$detail['report_autograph_type'])) : '';
  102. $detail['review_autograph'] = ($detail['review_use_autograph'] == 1) ? (empty($detail['review_autograph']) ? '' : $this->makeFileUrl($detail['review_autograph'],$detail['review_autograph_type'])) : '';
  103. $detail['confirm_autograph'] = ($detail['confirm_use_autograph'] == 1) ? (empty($detail['confirm_autograph']) ? '' : $this->makeFileUrl($detail['confirm_autograph'],$detail['confirm_autograph_type'])) : '';
  104. if(!empty($detail['report_doctor_id'])){
  105. $insName = $this->reportDao->getInstitution($detail['report_doctor_id']);
  106. $detail['institution'] = $insName['name'];
  107. $detail['introduce'] = $insName['introduce'];
  108. }else{
  109. $detail['institution'] = '';
  110. $detail['introduce'] = '';
  111. }
  112. $detail['exam_id'] = $examId;
  113. $detail['is_remote'] = $isRemote;
  114. // 操作痕迹
  115. if(empty($detail['report_id'])){
  116. $trace = [];
  117. }else{
  118. $trace = $this->reportDao->getTrace($detail['report_id']);
  119. }
  120. if(!isset($detail['exam_status'])){
  121. $detail['exam_status'] = '';
  122. }
  123. $detail['trace'] = $trace;
  124. // 当报告处于完成状态时 不在显示暂存的草稿
  125. if($detail['exam_status'] ?? '') {
  126. if ($detail['exam_status'] == 9)
  127. {
  128. return $detail;
  129. }
  130. }
  131. if($detail['report_status'] ?? '')
  132. {
  133. if ($detail['report_status'] == 9)
  134. {
  135. return $detail;
  136. }
  137. }
  138. // 草稿存储
  139. $userId = $this->reportDao->getUserId($token);
  140. $cacheToken = $this->getStageKey($detail['report_id'],$userId);
  141. $stage = $this->reportDao->getStage($cacheToken);
  142. if(!empty($stage)){
  143. $detail['impression'] = $stage['impression'];
  144. $detail['description'] = $stage['description'];
  145. }
  146. return $detail;
  147. }
  148. public function getWjDetail($examId,$isRemote)
  149. {
  150. if($isRemote == 1){
  151. //远程
  152. $remote = 'not null';
  153. }else{
  154. $remote = 'null';
  155. }
  156. $detail = $this->reportDao->getReportInfo($examId/**,$remote*/);
  157. // 医生姓名
  158. if(empty($detail)){
  159. $detail['report_doctor_id'] = '';
  160. $detail['review_doctor_id'] = '';
  161. $detail['confirm_doctor_id'] = '';
  162. $detail['report_id'] = '';
  163. $detail['report_doctor_name'] = '';
  164. $detail['review_doctor_name'] = '';
  165. $detail['confirm_doctor_name'] = '';
  166. }
  167. if(!empty($detail['report_doctor_id'])){
  168. $insName = $this->reportDao->getInstitution($detail['report_doctor_id']);
  169. $detail['institution'] = $insName['name'];
  170. $detail['introduce'] = $insName['introduce'];
  171. }else{
  172. $detail['institution'] = '';
  173. $detail['introduce'] = '';
  174. }
  175. $detail['exam_id'] = $examId;
  176. $detail['is_remote'] = $isRemote;
  177. if(!isset($detail['exam_status'])){
  178. $detail['exam_status'] = '';
  179. }
  180. $detail['trace'] = '';
  181. return $detail;
  182. }
  183. public function save_progress($id,$token,$content,$type)
  184. {
  185. $doctor = $this->reportDao->getUser($token);
  186. $bbs = [
  187. 'id'=>UUIDUtils::uuid(),
  188. 'initiator'=>$doctor['id'],
  189. 'remote_application_id'=>$id,
  190. 'content'=>$doctor['realname'].$content,
  191. 'createdAt'=>date('Y-m-d H:i:s',time()),
  192. 'type'=>$type
  193. ];
  194. $this->reportDao->saveBbs($bbs);
  195. }
  196. public function updateReport($examId, $data, $type, $reportType, $token , $ra_id = null )
  197. {
  198. // Db::startTrans();
  199. try{
  200. // 判断报告权限
  201. $exam = $this->reportDao->getExam($examId);
  202. $phone = $exam['phone'] ?? '';
  203. $studyId = $exam['study_id'];
  204. $user = $this->reportDao->getUser($token);
  205. $user_id = $user['id'];
  206. $result = $this->reportAuthentication($user_id, $type, $exam['institution_id'],$reportType);
  207. if(!$result){
  208. $this->throwError('权限未分配,请联系管理员',0005);
  209. }
  210. $rt = ($reportType == 1) ? 2 : 1;
  211. $report = $this->reportDao->getReport($examId,$rt,$ra_id);
  212. $report = json_decode(json_encode($report,true),true);
  213. $reportId = $report['id'] ?? null;
  214. // 书写报告时新增report表数据
  215. if(empty($reportId)){
  216. if($type == 'save'){
  217. $insert_data = [
  218. 'id' => UUIDUtils::uuid(),
  219. 'exam_id' => $examId,
  220. 'createdAt' => date('Y-m-d H:i:s'),
  221. 'report_result' => 1,
  222. 'type' => $rt,
  223. 'remote_application_id' => $ra_id
  224. ];
  225. $insert_res = $this->reportDao->insertReport($insert_data);
  226. // $url = 'http://wechat.pacsonline.cn/wx_patient/api/unifyGetWxQrcode?reportId='.$insert_data['id'].'&version=3';
  227. // $this->curl_get($url);
  228. if($insert_res == false){
  229. // Db::rollback();
  230. $this->throwError('insert_report_error',0004);
  231. }
  232. $reportId = $insert_data['id'];
  233. }
  234. }else{
  235. switch ($type)
  236. {
  237. case 'save':
  238. //已写报告 禁止其他医生点击书写按钮
  239. if ($user_id !== $report['report_doctor_id'] && !empty($report['report_doctor_id']))
  240. {
  241. $this->throwError('该报告已被其他医师书写,请刷新当前有页面进行查看!',0712);
  242. }
  243. break;
  244. case 'audit':
  245. //已审报告 禁止其他医生点击审核按钮
  246. if ($user_id !== $report['review_doctor_id'] && !empty($report['review_doctor_id']))
  247. {
  248. $this->throwError('该报告已被其他医师审核,请刷新当前有页面进行查看!',0712);
  249. }
  250. break;
  251. }
  252. }
  253. if($user['institution_id'] == '43600001')
  254. {
  255. if($type == 'save' || $type == 'audit')
  256. {
  257. // 添加锁定状态
  258. $middle = [
  259. 'institution_id'=>$user['institution_id'],
  260. 'status'=>0,
  261. 'doctor_id'=>$user['id'],
  262. 'doctor_name'=>$user['realname'],
  263. 'exam_id'=>$examId,
  264. 'is_sync'=>0,
  265. 'report_id'=>$reportId
  266. ];
  267. $middleInfo = $this->reportDao->getMiddle(['exam_id'=>$examId]);
  268. $middleWhere = [];
  269. if($middleInfo)
  270. {
  271. unset($middle['is_sync']);
  272. $middleWhere = ['exam_id'=>$examId];
  273. }
  274. $this->reportDao->saveRmiddle($middle,$middleWhere);
  275. }elseif($type == 'confirm'){
  276. $middleWhere = ['exam_id'=>$examId];
  277. $middleInfo = $this->reportDao->getMiddle(['exam_id'=>$examId]);
  278. if($middleInfo)
  279. {
  280. $middle = [
  281. 'status'=>1,
  282. 'is_sync'=>0
  283. ];
  284. $this->reportDao->saveRmiddle($middle,$middleWhere);
  285. }else{
  286. $middle = [
  287. 'institution_id'=>$user['institution_id'],
  288. 'status'=>1,
  289. 'doctor_id'=>$user['id'],
  290. 'doctor_name'=>$user['realname'],
  291. 'exam_id'=>$examId,
  292. 'is_sync'=>0,
  293. 'report_id'=>$reportId
  294. ];
  295. $this->reportDao->saveRmiddle($middle);
  296. }
  297. }
  298. }
  299. // 修改基本信息
  300. $notUpdateType = [
  301. 'confirm'
  302. ];
  303. // 不需要更改的类型
  304. if(!in_array($type, $notUpdateType)){
  305. switch ($data['sex']){
  306. case 'M':
  307. case '男':
  308. $sex = 'M';
  309. break;
  310. case 'F':
  311. case '女':
  312. $sex = 'F';
  313. break;
  314. default:
  315. $sex = $data['sex'];
  316. break;
  317. }
  318. $update = [
  319. 'name' => $data['name'],
  320. 'sex' => $sex,
  321. 'age' => $data['age'],
  322. 'exam_class' => $data['exam_class'],
  323. 'exam_project' => $data['exam_project'] ?? null,
  324. ];
  325. if($rt == 1){
  326. $update['phone'] = $data['phone'];
  327. $exam_res = $this->reportDao->updateExamMsg($examId, $exam['patient_id'], $update);
  328. if($exam_res == false){
  329. // Db::rollback();
  330. $this->throwError('update_msg_error',0003);
  331. }
  332. }else{
  333. $update['phone'] = $data['phone'];
  334. $remote_res = $this->reportDao->updateRemote($ra_id, $update);
  335. if($remote_res == false){
  336. // Db::rollback();
  337. $this->throwError('update_msg_error',0003);
  338. }
  339. }
  340. }
  341. // 修改报告数据
  342. $report_up = [
  343. 'impression' => $data['impression'] ?? null,
  344. 'description' => $data['description'] ?? null,
  345. 'report_result' => $data['report_result'] ?? null
  346. ];
  347. $sms = $this->reportDao->getInstitutionSms($user['institution_id']);
  348. switch ($reportType){
  349. case '2':
  350. // 本地报告
  351. $report_res = $this->updateReportData($examId, $report_up, $type, $exam['exam_status'], $user, $reportType);
  352. break;
  353. case '1':
  354. // 远程报告
  355. $report_res = $this->updateReportData($examId, $report_up, $type, $exam['exam_status'], $user, $reportType , $ra_id);
  356. break;
  357. default :
  358. $report_res = false;
  359. break;
  360. }
  361. if($type == 'confirm'){
  362. $this->reportDao->delCache($reportId.'_local');
  363. if($sms == '1' && !empty($phone)){
  364. $insName = $this->reportDao->getInstitutionName($user['institution_id']);
  365. // 发送确认短信
  366. $sms = $this->sendSms($phone,$reportId,$examId,$studyId,$insName,$user['institution_id']);
  367. }
  368. $wechat_url = Config::get('wechat_url');
  369. // 二维码生成
  370. $url = $wechat_url.'/wx_patient/api/unifyGetWxQrcode?reportId='.$reportId.'&version=3';
  371. $this->curl_get($url);
  372. if($reportType == 1 && !empty($ra_id)){
  373. //远程确认区间
  374. $money = $this->reportDao->getOrderMoney($ra_id);
  375. if($money != 0){
  376. $current_money = $this->reportDao->getCurrentMoney($user['institution_id']);
  377. $max_money = $current_money + $money;
  378. $this->reportDao->updateInstititonMoney($user['institution_id'],$max_money);
  379. }
  380. //修改订单状态为已确认
  381. $this->reportDao->updateOrder($ra_id,Config::get('ORDER_STATUS')['CONFIRM']);
  382. $wechat = New WechatService();
  383. $order_id = $this->reportDao->getOrderId($ra_id);
  384. // 微信推送确认
  385. $w = $wechat->pushWechatComplete($order_id);
  386. }
  387. //确认推送微信公众号
  388. if(!empty($exam['id'])){
  389. $data = $this->xz->getPushInfo($exam['id']);
  390. $pushType = 6;
  391. $cont = [
  392. 'name'=>$exam['name'],
  393. 'exam_id'=>$exam['id'],
  394. 'modality'=>$exam['exam_class'],
  395. 'examDate'=>$exam['exam_datetime'],
  396. 'report_id'=>$reportId
  397. ];
  398. $content = json_encode($cont,true);
  399. $openids = $this->xz->getOpenId($data);
  400. foreach ($openids as $k=>$v){
  401. // 推送4.0公众号消息
  402. $this->new_wechat_push($v,$pushType,$content);
  403. }
  404. }
  405. }
  406. if($report_res == false){
  407. // Db::rollback();
  408. $this->throwError('update_report_error',0006);
  409. }
  410. if(isset($reportId) && !empty($reportId)){
  411. // 草稿
  412. $key = $this->getStageKey($reportId, $user_id);
  413. $stage = $this->reportDao->getStage($key);
  414. if($stage){
  415. $this->reportDao->delStage($key);
  416. }
  417. }
  418. // 成功
  419. // Db::commit();
  420. // if($type == 'confirm'){
  421. // $this->getExamPush($examId);
  422. // }
  423. return true;
  424. } catch (Exception $exception){
  425. $this->throwError($exception->getMessage(),0001);
  426. }
  427. }
  428. public function rejectAudit($id,$reason,$user)
  429. {
  430. $field = ['report_doctor_id','exam_id'];
  431. $write = $this->reportDao->getReportById($id,$field);
  432. //获取当前医生账号权限
  433. $now_authority = $this->reportDao->getDoctorClass($user['id']);
  434. $now_authority = explode(',',$now_authority);
  435. if(!in_array('3',$now_authority))
  436. {
  437. $this->throwError('do_not_have_permission',0005);
  438. }
  439. $update = ['report'];
  440. // 更改状态为审核驳回
  441. $this->reportDao->updateExamStatus($write['exam_id'],12);
  442. $this->reportDao->updateReport($write['exam_id'],1,['review_doctor_id'=>null,'review_doctor_name'=>null,'review_datetime'=>null]);
  443. $data = [
  444. 'id' => UUIDUtils::uuid(),
  445. 'title' => '您写的报告有最新消息,请注意查收',
  446. 'content' => $user['realname'].'医师驳回了您写得报告,驳回原因是:'.$reason,
  447. 'count' => '1',
  448. 'type' => '9',
  449. 'ctime' => date('Y-m-d H:i:s', time()),
  450. 'exam_id' => $write['exam_id'],
  451. 'doctor_id'=>$write['report_doctor_id']
  452. ];
  453. $this->reportDao->insertMessage($data);
  454. return true;
  455. }
  456. public function sendSms($phone,$reportId,$examId,$studyId,$institution,$insId)
  457. {
  458. $code = rand(0,9).rand(0,9).rand(0,9).rand(0,9);
  459. $id = UUIDUtils::uuid();
  460. if(empty($phone)){
  461. $send_message = 0;
  462. }else{
  463. //发送短信
  464. $note = [
  465. 'long_url'=>'https://wc.pacsonline.cn/#/jump?id='.$id
  466. ];
  467. $noteId = $this->reportDao->insertNote($note);
  468. $nid = base64_encode(str_pad(base_convert($noteId,10,36),6,'0',STR_PAD_LEFT));
  469. if($insId == '43600001')
  470. {
  471. $send = send_message::sendEZShortMessage($phone,$code,$nid);
  472. }elseif($insId == '03060002'){
  473. $send = send_message::sendReportShortMessage($phone,$institution);
  474. }else{
  475. $send = send_message::sendExam2ShortPatient($phone,$code,$institution,$nid);
  476. }
  477. $data = json_decode(json_encode($send),true);
  478. if($data['Code'] == 'OK'){
  479. $send_message = 1;
  480. }else{
  481. $send_message = 0;
  482. }
  483. }
  484. // $share = [
  485. // 'id'=>$id,
  486. // 'report_id'=>$reportId,
  487. // 'exam_id'=>$examId,
  488. // 'code'=>$code,
  489. // 'send_time'=>time(),
  490. // 'expires_time'=>time()+86400*7,
  491. // 'send_message'=>$send_message,
  492. // 'url'=>'',
  493. // 'phone'=>$phone,
  494. // 'study_id'=> $studyId
  495. // ];
  496. $share = [
  497. 'id'=>$id,
  498. 'examId'=>$examId,
  499. 'status'=>1,
  500. 'overdueTime'=>7,
  501. 'code'=>$code,
  502. 'short_url'=>'',
  503. 'phone'=>$phone,
  504. 'report_isset'=>1,
  505. 'study_id'=>$studyId,
  506. 'send_message'=>$send_message,
  507. ];
  508. $this->reportDao->insertShare($share);
  509. }
  510. public function getExamPush($id)
  511. {
  512. try{
  513. $xzData = $this->reportDao->getXzData($id);
  514. $report = $this->reportDao->getReport($id,1);
  515. $reportName = $this->reportDao->getDoctorName($report['report_doctor_id']);
  516. $reviewName = $this->reportDao->getDoctorName($report['review_doctor_id']);
  517. $studyUid = $this->reportDao->getUid($id);
  518. $accessionNum = $this->reportDao->getAccession($id);
  519. $info = [
  520. 'report'=>[
  521. 'department'=>$xzData['department'],
  522. 'clinicalDoctor'=>$xzData['clinicalDoctor'],
  523. 'symptom'=>$xzData['symptom'],
  524. 'reportDate'=>$report['report_datetime'],
  525. 'description'=>$report['description'],
  526. 'impression'=>$report['impression'],
  527. 'reportDoctor'=>$reportName,
  528. 'reviewDoctor'=>$reviewName,
  529. 'studyInstanceUId'=>$studyUid,
  530. 'modality'=>$xzData['modality'],
  531. 'accessionNumber'=>$accessionNum
  532. ],
  533. 'applicationFormNo'=>$xzData['applicationFormNo'],
  534. 'clinicId'=>$xzData['clinicId'],
  535. ];
  536. $data = json_encode($info);
  537. $url = 'http://wjw.yidab.cn:801/pacs/pushExamReport.do';
  538. // $url = 'http://wjw.yidab.cn:801/wjw-test/pacs/pushExamReport.do';
  539. $return = $this->curlJsonPost($url,$data);
  540. return $return;
  541. }catch(\Exception $e){
  542. return json_encode(['code'=>'1','message'=>$e->getMessage()]);
  543. }
  544. }
  545. public function reportAuthentication($user_id, $type, $institution_id = null,$type_report)
  546. {
  547. // 获取权限列表
  548. $doctor_authority = [
  549. 'clinical' => 1, // 临床医生
  550. 'report' => 2, // 报告医生
  551. 'audit' => 3, // 审核医生
  552. 'confirm' => 4, // 确认医生
  553. 'register' => 5, // 登记医生
  554. 'remote_apply' => 6, // 远程申请医生
  555. 'remote_report' => 7, // 远程报告医生
  556. 'remote_audit' => 8, // 远程审核医生
  557. 'local_reject' => 9, // 本地完成状态打回已写医生
  558. 'local_del' => 10, // 本地影像删除
  559. ];
  560. // 当前账号权限
  561. $now_authority = $this->reportDao->getDoctorClass($user_id);
  562. if(empty($now_authority)){
  563. return false;
  564. }
  565. $now_authority = explode(',', $now_authority);
  566. // 判断权限
  567. switch ($type){
  568. case 'save':
  569. if($type_report == '2'){
  570. $require = $doctor_authority['report'];
  571. }else{
  572. $require = $doctor_authority['remote_report'];
  573. }
  574. if(!in_array($require, $now_authority)){
  575. return false;
  576. }
  577. break;
  578. case 'audit':
  579. if($type_report == '2'){
  580. $require = $doctor_authority['audit'];
  581. }else{
  582. $require = $doctor_authority['remote_audit'];
  583. }
  584. if(!in_array($require, $now_authority)){
  585. return false;
  586. }
  587. break;
  588. case 'confirm':
  589. $require = $doctor_authority['confirm'];
  590. if(!in_array($require, $now_authority)){
  591. return false;
  592. }
  593. break;
  594. case 'reject':
  595. $require = $doctor_authority['local_reject'];
  596. if(!in_array($require, $now_authority)){
  597. return false;
  598. }
  599. break;
  600. case 'del':
  601. $require = $doctor_authority['local_del'];
  602. if(!in_array($require, $now_authority)){
  603. return false;
  604. }
  605. break;
  606. default :
  607. return false;
  608. }
  609. // 成功
  610. return true;
  611. }
  612. public function stageReport($exam_id, $token, $data, $isRemote,$report_id)
  613. {
  614. try{
  615. if($isRemote == 2){
  616. // 本地
  617. $remote = 1;
  618. }else{
  619. // 远程 1区间
  620. $remote = 2;
  621. }
  622. if(!$report_id){
  623. // 创建一条数据
  624. $insert_data = [
  625. 'id' => UUIDUtils::uuid(),
  626. 'exam_id' => $exam_id,
  627. 'createdAt' => date('Y-m-d H:i:s'),
  628. 'report_result' => 1,
  629. 'type' => $remote
  630. ];
  631. if($remote == 2){ //远程进入
  632. $applicationId = $this->reportDao->getApplicationId($exam_id);
  633. $insert_data['remote_application_id'] = $applicationId;
  634. }
  635. $res = $this->reportDao->insertReport($insert_data);
  636. // $url = 'http://wechat.pacsonline.cn/wx_patient/api/unifyGetWxQrcode?reportId='.$insert_data['id'].'&version=3';
  637. // $this->curl_get($url);
  638. if($res == false){
  639. $this->throwError('insert_report_error',0006);
  640. }
  641. $report_id = $insert_data['id'];
  642. }
  643. // 存储
  644. $user_id = $this->reportDao->getUserId($token);
  645. $key = $this->getStageKey($report_id, $user_id);
  646. $this->reportDao->saveCache($key,$data,604800);
  647. // 成功
  648. return $key;
  649. } catch (Exception $exception){
  650. $this->throwError($exception->getMessage(),0001);
  651. }
  652. }
  653. public function getPrintData($reportId,$is_remote)
  654. {
  655. try{
  656. $wechat = Config::get('wechat_url');
  657. $url = $wechat.'/wx_patient/api/unifyGetWxQrcode?reportId='.$reportId.'&version=3';
  658. $this->curl_get($url);
  659. $detail = $this->reportDao->getPrintInfo($reportId,$is_remote);
  660. $field = ['IS_USE_AUTOGRAPH AS is_use_autograph','AUTOGRAPH AS autograph','AUTOGRAPH_TYPE AS autograph_type'];
  661. if(empty($detail['report_doctor_id']))
  662. {
  663. $detail['report_use_autograph'] = '';
  664. $detail['report_autograph'] = '';
  665. }else{
  666. $report_autograph = $this->reportDao->getDoctorInfo($detail['report_doctor_id'],$field);
  667. $detail['report_use_autograph'] = $report_autograph['is_use_autograph'] ?? '';
  668. $detail['report_autograph'] = empty($report_autograph['autograph'] ?? '') ? '' : $this->makeFileUrl($report_autograph['autograph'],$report_autograph['autograph_type']);
  669. $detail['report_autograph_type'] = $report_autograph['autograph_type'];
  670. }
  671. if(empty($detail['review_doctor_id']))
  672. {
  673. $detail['review_use_autograph'] = '';
  674. $detail['review_autograph'] = '';
  675. }else{
  676. $review_autograph = $this->reportDao->getDoctorInfo($detail['review_doctor_id'],$field);
  677. $detail['review_use_autograph'] = $review_autograph['is_use_autograph'] ?? '';
  678. $detail['review_autograph'] = empty($review_autograph['autograph'] ?? '') ? '' : $this->makeFileUrl($review_autograph['autograph'],$review_autograph['autograph_type']);
  679. $detail['review_autograph_type'] = $review_autograph['autograph_type'];
  680. }
  681. if($detail['exam_class'] == 'DX' && ($detail['institution_id'] ?? '') == '73000003')
  682. {
  683. $detail['exam_class'] = 'DR';
  684. }
  685. $detail['age'] = str_replace('W','周',str_replace('D','天',str_replace('M','月',str_replace('Y','岁',ltrim($detail['age'],'0')))));
  686. return $detail;
  687. } catch (Exception $exception){
  688. $this->throwError($exception->getMessage(),0001);
  689. }
  690. }
  691. public function makeChineseData($data)
  692. {
  693. switch ($data['sex'])
  694. {
  695. case 'F':
  696. $sex = '女';
  697. break;
  698. case 'M':
  699. $sex = '男';
  700. break;
  701. default:
  702. $sex = '未知';
  703. }
  704. $arr = [
  705. '医院名称'=>$data['institution_name'],
  706. '地址'=>'',
  707. '科室名称'=>'',
  708. '检查设备名称'=>'',
  709. '检查时间'=>$data['exam_datetime'],
  710. '审核时间'=>$data['review_datetime'],
  711. '姓名'=>$data['name'],
  712. '性别'=>$sex,
  713. '年龄'=>$data['age'],
  714. '检查号'=>$data['accession_num'],
  715. '病案号'=>'',
  716. '检查项目'=>$data['exam_project'],
  717. '检查方法'=>$data['exam_class'],
  718. '检查部位'=>$data['body_part'],
  719. '检查参数'=>'',
  720. '征象描述'=>$data['description'],
  721. '结论和建议'=>$data['impression'],
  722. ];
  723. return $arr;
  724. }
  725. public function getQrCode($code,$examId)
  726. {
  727. $url = 'https://wechat.pacsonline.cn/wx_patient/api/unifyGetWxQrcode?examId='.$examId.'&version=3';
  728. if(empty($code))
  729. {
  730. $qrCode = $this->curl_get($url);
  731. }else{
  732. $arr = json_decode($code,true);
  733. $time = strtotime($arr['expipy']);
  734. if(time() > $time)
  735. {
  736. $qrCode = $this->curl_get($url);
  737. }else{
  738. $qrCode = $code;
  739. }
  740. }
  741. return json_decode($qrCode,true);
  742. }
  743. public function updateReportData($exam_id, $data, $type, $exam_status, $user, $report_type,$id = null)
  744. {
  745. try{
  746. $status = '';
  747. $doctorId = '';
  748. if($id !== null){
  749. $remote = $this->reportDao->getReportStatus($id);
  750. $status = $remote['report_status'];
  751. $doctorId = $remote['remote_doctor_id'];
  752. }
  753. // 判断类型
  754. switch ($type){
  755. case 'save': // 本地保存
  756. if($report_type == 2){
  757. $write = $this->reportDao->getExam($exam_id);
  758. if($write['write_report'] != 1)
  759. {
  760. //不等于1 则走正常流程
  761. if($exam_status != 3 && $exam_status != 7 && $exam_status != 12){
  762. $this->throwError('流程顺序错误,无法书写报告','0033');
  763. }
  764. }
  765. }else{
  766. // 远程
  767. if($doctorId != $user['id']){
  768. $this->throwError('非受邀医生无法书写报告','0034');
  769. }
  770. if($status != 6 && $status != 7){
  771. $this->throwError('流程顺序错误,无法书写报告','0033');
  772. }
  773. $this->saveProgressLog($user,6,$id);
  774. }
  775. $update = [
  776. 'impression' => $data['impression'],
  777. 'description' => $data['description'],
  778. 'report_result' => $data['report_result'],
  779. 'report_datetime' => date('Y-m-d H:i:s'),
  780. 'report_doctor_id'=> $user['id'],
  781. 'report_doctor_name' =>$user['realname']
  782. ];
  783. $exam_up_status = 7;
  784. $trace_type = 1;
  785. break;
  786. case 'audit':
  787. if($report_type == 2){
  788. if($exam_status != 8 && $exam_status != 7){
  789. $this->throwError('流程顺序错误,无法审核报告','0033');
  790. }
  791. }else{
  792. if($status != 8 && $status != 7){
  793. $this->throwError('流程顺序错误,无法审核报告','0033');
  794. }
  795. $this->saveProgressLog($user,7,$id);
  796. }
  797. $update = [
  798. 'impression' => $data['impression'],
  799. 'description' => $data['description'],
  800. 'report_result' => $data['report_result'],
  801. 'review_datetime' => date('Y-m-d H:i:s'),
  802. 'review_doctor_id'=> $user['id'],
  803. 'review_doctor_name'=>$user['realname']
  804. ];
  805. $exam_up_status = 8;
  806. $trace_type = 2;
  807. break; // 本地审核
  808. case 'confirm':
  809. if($report_type == 2){
  810. if($exam_status != 8){
  811. $this->throwError('流程顺序错误,无法确认报告','0033');
  812. }
  813. }else{
  814. if($status != 10){
  815. $this->throwError('流程顺序错误,无法确认报告','0033');
  816. }
  817. $this->saveProgressLog($user,9,$id);
  818. }
  819. if(!empty($id)){
  820. $this->reportDao->readMessage($id);
  821. }
  822. $update = [
  823. 'confirm_datetime' => date('Y-m-d H:i:s'),
  824. 'confirm_doctor_id'=> $user['id'],
  825. 'confirm_doctor_name'=>$user['realname']
  826. ];
  827. $exam_up_status = 9;
  828. $trace_type = 3;
  829. break; // 本地确认
  830. default:
  831. return false;
  832. }
  833. // 判断远程还是本地
  834. switch ($report_type){
  835. case '2'; //本地
  836. $result = $this->reportDao->updateReport($exam_id,1,$update);
  837. // 修改状态
  838. $this->reportDao->updateExamStatus($exam_id,$exam_up_status);
  839. break;
  840. case '1':
  841. $result = $this->reportDao->updateRemoteReport($id,$update);
  842. // 修改远程状态
  843. $this->reportDao->updateRemoteStauts($id,$exam_up_status);
  844. $this->reportDao->updateremoteExamStatus($exam_id,$exam_up_status);
  845. break;
  846. default :
  847. return false;
  848. }
  849. if(!$result){
  850. return false;
  851. }
  852. if($report_type == '2'){
  853. $rid = $this->reportDao->getReportId($exam_id,1);
  854. }else{
  855. $rid = $this->reportDao->getRemoteReportId($id);
  856. }
  857. /*$detail = $this->reportDao->getReport($exam_id,$report_type);
  858. $cacheToken = $this->getStageKey($rid,$user_id,$detail['exam_status']);
  859. $stage = $this->reportDao->remoteStage($cacheToken);*/
  860. // 添加报告痕迹
  861. $trace = [
  862. 'id' => UUIDUtils::uuid(),
  863. 'impression' => $update['impression'] ?? '',
  864. 'description' => $update['description'] ?? '',
  865. 'report_result' => $update['report_result'] ?? '',
  866. 'report_id' => $rid,
  867. 'createdAt' => date('Y-m-d H:i:s'),
  868. 'doctor_id' => $user['id'],
  869. 'type' => $trace_type
  870. ];
  871. $result = $this->reportDao->insertReportRecord($trace);
  872. if(!$result){
  873. return false;
  874. }
  875. // 成功
  876. return true;
  877. } catch (DbException $exception){
  878. $this->throwError($exception->getMessage(),0001);
  879. }
  880. }
  881. public function saveProgressLog($doctor,$step,$id)
  882. {
  883. $pay_log = [
  884. 'id'=>UUIDUtils::uuid(),
  885. 'operator_id'=>$doctor['id'],
  886. 'operator_name'=>$doctor['realname'],
  887. 'current_step'=>$step,
  888. 'application_id'=>$id
  889. ];
  890. $this->reportDao->savePregressLog($pay_log);
  891. }
  892. public function save_video_url($params)
  893. {
  894. $data = [
  895. 'exam_id'=>$params['exam_id'],
  896. 'status'=>1
  897. ];
  898. $where = ['id'=>$params['id']];
  899. $return = $this->reportDao->saveVideo($data,$where);
  900. return $return;
  901. }
  902. public function cancel_video($id)
  903. {
  904. $info = $this->reportDao->cancel_video($id);
  905. return $info;
  906. }
  907. public function getVideo($params)
  908. {
  909. $id = $params['exam_id'] ?? null;
  910. if(!$id)
  911. {
  912. $this->throwError('无效的id值','0064');
  913. }
  914. $video = $this->reportDao->getVideo($id);
  915. foreach ($video as $k=>$v)
  916. {
  917. $video[$k]['video_url'] = $this->makeFileUrl($v['video_url'],$v['video_type'],'inline');
  918. }
  919. return $video;
  920. }
  921. public function checkWrite($params,$doctor,$cache)
  922. {
  923. $data = ['id'=>$params['report_id'],'name'=>$doctor['realname'],'did'=>$doctor['id']];
  924. if(empty($cache))
  925. {
  926. $this->reportDao->setCache($params['report_id'].'_local',$data,7200);
  927. }else{
  928. if($doctor['id'] !== $cache['did'])
  929. {
  930. //当前医生不属于第一个进入且存储的医生
  931. $this->throwError($cache['name'],'0067');
  932. }
  933. }
  934. return true;
  935. }
  936. // https://query.pacsonline.cn/query/url?&study_id='.$study.'&version=V1.2.0.0
  937. public function getDcmZip($study,$email='',$come='',$examId='',$examClass='')
  938. {
  939. ignore_user_abort(true); // 后台运行,不受前端断开连接影响
  940. set_time_limit(0); //
  941. ob_end_clean();//清除之前的缓冲内容,这是必需的,如果之前的缓存不为空的话,里面可能有http头或者其它内容,导致后面的内容不能及时的输出
  942. header("Connection: close");//告诉浏览器,连接关闭了,这样浏览器就不用等待服务器的响应
  943. header("HTTP/1.1 200 OK"); //可以发送200状态码,以这些请求是成功的,要不然可能浏览器会重试,特别是有代理的情况下
  944. ob_start();//开始当前代码缓冲
  945. if(empty($come))
  946. {
  947. $result = [
  948. 'code' => 0,
  949. 'msg' => '请求成功',
  950. 'data' => '文件生成中',
  951. 'error' => null,
  952. 'timestamp' => time(),
  953. 'random' => null,
  954. 'signature' => null,
  955. 'request_timestamp' => ZskkDefaultRequest::instance()->header()['zskk-timestamp'] ?? null
  956. ];
  957. echo json_encode($result);
  958. }
  959. //下面输出http的一些头信息
  960. $size = ob_get_length();
  961. header("Content-Length: $size");
  962. ob_end_flush();//输出当前缓冲
  963. flush();//输出PHP缓冲
  964. //在Yii2框架下,上面代码可能不会立即返回给客户端,所以需要加如下的代码,即可实现立即返回给客户端
  965. //具体可查看此文章:http://www.lampnick.com/php/375
  966. if (function_exists("fastcgi_finish_request")) {
  967. fastcgi_finish_request(); /* 响应完成, 关闭连接 */
  968. }
  969. ignore_user_abort(true); // 后台运行,这个只是运行浏览器关闭,并不是直接就中止返回200状态。
  970. try {
  971. set_time_limit(0);
  972. ini_set('memory_limit','1280M');
  973. $study = str_replace('&node_type=1','',$study);
  974. $this->reportDao->insertDcmCompress(['status'=>1,'study_id'=>$study]);
  975. $path = $this->runRack($study,1);
  976. $typeData = $this->reportDao->getDcmPathData([],$study);
  977. $type = $typeData['dcm_type'] ?? 1;
  978. if(strrpos($path,'zip') !== false && file_exists($path))
  979. {
  980. $type = $this->uploadZip($path,$study);
  981. }
  982. if(!empty($email) /* && $come == 'weChat' */)
  983. {
  984. if(strrpos($path,'zip') !== false)
  985. {
  986. $name = $this->reportDao->getPatientName($study);
  987. // 存在zip压缩文件
  988. $this->sendEmail($email,$path,$name,$type);
  989. $this->reportDao->insertDcmCompress(['status'=>9,'study_id'=>$study]);
  990. log::record('邮件发送完毕');
  991. $this->reportDao->updateEmailStatus($email,$study);
  992. }
  993. }
  994. if($come == 'ai')
  995. {
  996. if(strrpos($path,'zip') !== false)
  997. {
  998. // 存在zip压缩文件
  999. $url = 'http://deeplearning.lib.sjtu.edu.cn/';
  1000. // $url = 'http://127.0.0.1:5000/';
  1001. $data = [
  1002. 'zip' => new \CURLFile(APP_PATH.'/'.$path),
  1003. 'exam_id'=>$examId,'exam_class'=>$examClass];
  1004. $re = $this->curlPost($url,$data);
  1005. if($re == false)
  1006. {
  1007. log::record("返回值为false");
  1008. return "返回值为false";
  1009. }
  1010. $reData = json_decode($re,true);
  1011. if(empty($reData[0] ?? null))
  1012. {
  1013. log::record('ai接口返回错误,返回信息'.$re);
  1014. return $re;
  1015. }
  1016. $reportData = [
  1017. 'id'=>UUIDUtils::uuid(),
  1018. 'impression'=>$reData[0]['diagnosis'],
  1019. 'description'=>$reData[0]['describe'],
  1020. 'type'=>3,
  1021. 'exam_id'=>$examId,
  1022. 'report_doctor_name'=>'ai报告医生',
  1023. 'review_doctor_name'=>'ai报告医生',
  1024. 'confirm_doctor_name'=>'ai报告医生',
  1025. 'report_datetime'=>date('Y-m-d H:i:s'),
  1026. 'review_datetime'=>date('Y-m-d H:i:s'),
  1027. 'confirm_datetime'=>date('Y-m-d H:i:s')
  1028. ];
  1029. $aiData = $this->reportDao->getReport($examId,3);
  1030. if($aiData)
  1031. {
  1032. //修改ai报告
  1033. $this->reportDao->updateReport($examId,3,$reportData);
  1034. }else{
  1035. $this->reportDao->insertReport($reportData);
  1036. }
  1037. return $re;
  1038. }
  1039. }
  1040. }catch (\think\Exception $e)
  1041. {
  1042. try {
  1043. $this->reportDao->insertDcmCompress(['status'=>999,'study_id'=>$study,'msg'=>$e->getMessage(),'email'=>$email]);
  1044. }catch (\think\Exception $exception)
  1045. {
  1046. $this->reportDao->insertDcmCompress(['status'=>998,'study_id'=>$study,'msg'=>mb_convert_encoding($e->getMessage(), 'UTF-8', 'GBK'),'email'=>$email]);
  1047. }
  1048. }
  1049. }
  1050. public function sendDcm($sendData,$study,$examId='',$examClass='')
  1051. {
  1052. $this->reportDao->saveDcmReportData($sendData,$examId,1,$this->ts_time());
  1053. $exam = $this->reportDao->getExam($examId);
  1054. $url = 'http://deeplearning.lib.sjtu.edu.cn/';
  1055. // $url = 'http://127.0.0.1:5000/';
  1056. // $url = 'http://49.7.230.34:5000/';
  1057. $query = Config::get('query_url');
  1058. $data = [
  1059. 'down_url' => $query.'/query/down?&study_id='.$study.'&version=V1.2.0.0',
  1060. // 'zip' => new \CURLFile(APP_PATH.'/'.$path),
  1061. 'exam_id'=>$examId,
  1062. 'exam_class'=>$examClass,
  1063. 'exam_project'=>empty($exam['exam_project']) ? '' : $exam['exam_project'],
  1064. 'is_chest'=>($exam['body_part'] == 'CHEST' || strpos($exam['body_part'],'胸') !== false) ? 1 : 0
  1065. ];
  1066. $this->reportDao->saveDcmReportData(json_encode($data),$examId,2,$this->ts_time());
  1067. $re = $this->curlPost($url,$data);
  1068. $this->reportDao->saveDcmReportData('',$examId,3,$this->ts_time());
  1069. $this->reportDao->saveDcmReportData('',$examId,4,$this->ts_time());
  1070. return $re;
  1071. }
  1072. public function testGetDcmZip($study,$email='',$come='',$examId='',$examClass='')
  1073. {
  1074. $path = $this->runDirRack($study,$examId);
  1075. if($come == 'ai')
  1076. {
  1077. if(strrpos($path,'zip') !== false)
  1078. {
  1079. // 存在zip压缩文件
  1080. $url = 'http://deeplearning.lib.sjtu.edu.cn/';
  1081. // $url = 'http://127.0.0.1:5000/';
  1082. $data = [
  1083. 'zip' => new \CURLFile(APP_PATH.'/'.$path),
  1084. 'exam_id'=>$examId,'exam_class'=>$examClass];
  1085. $re = $this->curlPost($url,$data);
  1086. if($re == false)
  1087. {
  1088. log::record("返回值为false");
  1089. return "返回值为false";
  1090. }
  1091. $reData = json_decode($re,true);
  1092. if(empty($reData[0] ?? null))
  1093. {
  1094. log::record('ai接口返回错误,返回信息'.$re);
  1095. return $re;
  1096. }
  1097. $reportData = [
  1098. 'id'=>UUIDUtils::uuid(),
  1099. 'impression'=>$reData[0]['diagnosis'],
  1100. 'description'=>$reData[0]['describe'],
  1101. 'type'=>3,
  1102. 'exam_id'=>$examId,
  1103. 'report_doctor_name'=>'ai报告医生',
  1104. 'review_doctor_name'=>'ai报告医生',
  1105. 'confirm_doctor_name'=>'ai报告医生',
  1106. 'report_datetime'=>date('Y-m-d H:i:s'),
  1107. 'review_datetime'=>date('Y-m-d H:i:s'),
  1108. 'confirm_datetime'=>date('Y-m-d H:i:s')
  1109. ];
  1110. $aiData = $this->reportDao->getReport($examId,3);
  1111. if($aiData)
  1112. {
  1113. //修改ai报告
  1114. $this->reportDao->updateReport($examId,3,$reportData);
  1115. }else{
  1116. $this->reportDao->insertReport($reportData);
  1117. }
  1118. return $re;
  1119. }else{
  1120. return $path;
  1121. }
  1122. }
  1123. return '生成压缩文件失败,返回'.$path.',请联系开发人员';
  1124. }
  1125. public function runDirRack($study,$examId)
  1126. {
  1127. $dcm = $this->getCache($study.'_zip');
  1128. if(!empty($dcm))
  1129. {
  1130. Log::record('已生成过'.$dcm);
  1131. return '生成中';
  1132. }
  1133. ini_set('max_execution_time', 6000);
  1134. $time = date('Y-m-d H:i:s',time());
  1135. //过期时间 大于当前 则 还没过期
  1136. $where = "effective_date > '$time'";
  1137. $dcm = $this->reportDao->getDcmPath($where,$study);
  1138. if(!empty($dcm))
  1139. {
  1140. log::record('存在历史dcm地址'.$dcm);
  1141. return $dcm;
  1142. }
  1143. $this->setCache($study.'_zip',$study,600);
  1144. log::record('不存在历史地址则继续'.$study);
  1145. $query = Config::get('query_url');
  1146. //外网地址 需要network 走带宽
  1147. $url = $query."/query/down?network=1&study_id=$study&version=V1.2.0.0";
  1148. //内网地址
  1149. // $url = 'https://query.pacsonline.cn/query/down?&study_id='.$study.'&version=V1.2.0.0';
  1150. $data = $this->curl_get($url);
  1151. $data = json_decode($data);
  1152. if(empty($data))
  1153. {
  1154. log::record('没有找到dcm信息');
  1155. return 'dcm信息没有找到';
  1156. }
  1157. $date = time();
  1158. $create = ROOT_PATH . 'public' . DS . 'download'.DS.$date;
  1159. log::record('压缩中');
  1160. $path = $this->zipDir($data,$create,$date,$study,$examId);
  1161. log::record('压缩成功');
  1162. return $path;
  1163. }
  1164. public function zipDir($data,$create,$date,$study,$examId)
  1165. {
  1166. ini_set('max_execution_time', 6000);
  1167. $fileList = [];
  1168. foreach ($data as $k=>$v)
  1169. {
  1170. $v = (array)$v;
  1171. $path = $this->downLoad($v['url'],$create.DS.$v['seriesuid'].DS.$k,$create.DS.$v['seriesuid']);
  1172. $fileList[] = ['path'=>$path,'series'=>$v['seriesuid']];
  1173. }
  1174. $zipPath = ROOT_PATH . 'public' . DS .'zip';
  1175. $filename = $zipPath.DS."$examId.zip";
  1176. if (!file_exists($zipPath)) {
  1177. mkdir($zipPath, 0777,true);
  1178. @chmod($zipPath, 0777);
  1179. }
  1180. $zip = new \ZipArchive();
  1181. $zip->open($filename,\ZipArchive::CREATE); //打开压缩包
  1182. foreach($fileList as $file){
  1183. $zip->addFile($file['path'],$file['series'].DS.basename($file['path'])); //向压缩包中添加文件
  1184. }
  1185. $zip->close(); //关闭压缩包
  1186. $insert = [
  1187. 'dcm_path'=>'zip/'.$examId.".zip",
  1188. 'study_id'=>$study,
  1189. 'effective_date'=>date('Y-m-d H:i:s',time()+864000), //10天有效期
  1190. ];
  1191. $this->reportDao->insertDcmPath($insert);
  1192. return 'zip/'.$examId.".zip";
  1193. }
  1194. public function runRack($study,$come='')
  1195. {
  1196. if($come != 1)
  1197. {
  1198. $dcm = $this->getCache($study.'_zip');
  1199. if(!empty($dcm))
  1200. {
  1201. Log::record('已生成过'.$dcm);
  1202. return '生成中';
  1203. }
  1204. }
  1205. ini_set('max_execution_time', 6000);
  1206. $time = date('Y-m-d H:i:s',time());
  1207. //过期时间 大于当前 则 还没过期
  1208. $where = "effective_date > '$time'";
  1209. $dcm = $this->reportDao->getDcmPath($where,$study);
  1210. if(!empty($dcm))
  1211. {
  1212. log::record('存在历史dcm地址'.$dcm);
  1213. return $dcm;
  1214. }
  1215. $this->setCache($study.'_zip',$study,600);
  1216. log::record('不存在历史地址则继续'.$study);
  1217. $query = Config::get('query_url');
  1218. //外网地址 需要network 走带宽
  1219. // $url = "https://query.pacsonline.cn/query/url?network=1&study_id=$study&version=V1.2.0.0";
  1220. //内网地址
  1221. $url = $query.'/query/url?&study_id='.$study.'&version=V1.2.0.0';
  1222. $data = $this->curl_get($url);
  1223. $data = json_decode($data);
  1224. if(empty($data))
  1225. {
  1226. log::record('没有找到dcm信息');
  1227. return '';
  1228. }
  1229. $this->reportDao->insertDcmCompress(['status'=>2,'study_id'=>$study]);
  1230. $date = time();
  1231. $create = ROOT_PATH . 'public' . DS . 'download'.DS.$date;
  1232. log::record('压缩中');
  1233. $path = $this->zip($data,$create,$date,$study);
  1234. log::record('压缩成功');
  1235. return $path;
  1236. }
  1237. public function zip($data,$create,$date,$study)
  1238. {
  1239. ini_set('max_execution_time', 6000);
  1240. $fileList = [];
  1241. $exam = $this->reportDao->getExamByStudy($study);
  1242. $this->reportDao->insertDcmCompress(['status'=>3,'study_id'=>$study]);
  1243. if($exam['institution_id'] == '06300009')
  1244. {
  1245. $patient_num = $exam['patient_num'];
  1246. $name = $exam['name'];
  1247. //工人医院需要解密
  1248. if (!file_exists($create)) {
  1249. mkdir($create, 0777,true);
  1250. @chmod($create, 0777);
  1251. }
  1252. $ts = system("python3.8 /data/code/ris_server/utils/down/main.py '$patient_num' '$study' '$name' $date");
  1253. if($ts)
  1254. {
  1255. $files = scandir($create);
  1256. foreach ($files as $v)
  1257. {
  1258. if($v == '.' || $v == '..')
  1259. {
  1260. continue;
  1261. }
  1262. $fileList[] = $create.DS.$v;
  1263. }
  1264. }
  1265. }else{
  1266. foreach ($data as $k=>$v)
  1267. {
  1268. $path = $this->downLoad($v,$create.DS.$k,$create);
  1269. $fileList[] = $path;
  1270. }
  1271. $zipPath = ROOT_PATH . 'public' . DS .'zip';
  1272. $filename = $zipPath.DS."$date.zip";
  1273. if (!file_exists($zipPath)) {
  1274. mkdir($zipPath, 0777,true);
  1275. @chmod($zipPath, 0777);
  1276. }
  1277. $this->reportDao->insertDcmCompress(['status'=>4,'study_id'=>$study]);
  1278. $zip = new \ZipArchive();
  1279. $zip->open($filename,\ZipArchive::CREATE); //打开压缩包
  1280. foreach($fileList as $file){
  1281. $zip->addFile($file,basename($file)); //向压缩包中添加文件
  1282. }
  1283. $zip->close(); //关闭压缩包
  1284. $filesDcm = scandir($create);
  1285. foreach ($filesDcm as $file) {
  1286. if ($file != '.' && $file != '..') {
  1287. $pathDcm = $create . '/' . $file;
  1288. @unlink($pathDcm);
  1289. }
  1290. }
  1291. @rmdir($create);
  1292. }
  1293. $this->reportDao->insertDcmCompress(['status'=>5,'study_id'=>$study]);
  1294. $path_url = 'zip/'.$date.".zip";
  1295. $insert = [
  1296. 'dcm_path'=>$path_url,
  1297. 'study_id'=>$study,
  1298. 'effective_date'=>date('Y-m-d H:i:s',time()+864000), //10天有效期
  1299. ];
  1300. $this->reportDao->insertDcmPath($insert);
  1301. $this->delCache($study.'_zip');
  1302. $this->reportDao->insertDcmCompress(['status'=>6,'study_id'=>$study]);
  1303. return $path_url;
  1304. }
  1305. public function uploadZip($path_url,$study)
  1306. {
  1307. $this->reportDao->insertDcmCompress(['status'=>7,'study_id'=>$study]);
  1308. $upload = new uploadToCloud();
  1309. $s = $upload->upload($path_url,$path_url,'3','2','2','2');
  1310. if(($s['@metadata']['statusCode'] ?? '') == '200')
  1311. {
  1312. $this->reportDao->insertDcmCompress(['status'=>8,'study_id'=>$study]);
  1313. gc_collect_cycles();
  1314. $this->reportDao->updateDcmPath(['study_id'=>$study],['dcm_type'=>4]);
  1315. unlink($path_url);
  1316. return 4;
  1317. }
  1318. return '1';
  1319. }
  1320. public function changeReport($param,$token)
  1321. {
  1322. $user = $this->reportDao->getUser($token);
  1323. $result = $this->reportAuthentication($user['id'], 'reject', $user['institution_id'],2);
  1324. if(!$result){
  1325. $this->throwError('权限未分配,请联系管理员',0005);
  1326. }
  1327. $id = $param['id'];
  1328. $info = $this->reportDao->updateExamStatus($id,7);
  1329. $this->reportDao->updateReport($id,1,['review_doctor_id'=>null]);
  1330. $data = [
  1331. 'exam_id'=>$id,
  1332. 'doctor_id'=>$user['id'],
  1333. 'doctor_name'=>$user['realname']
  1334. ];
  1335. $this->reportDao->insertReject($data);
  1336. return $info;
  1337. }
  1338. public function checkLock($params,$token)
  1339. {
  1340. return '';
  1341. $user = $this->getCache($token);
  1342. $id = $params['id'];
  1343. $info = $this->reportDao->checkLock($id);
  1344. if($user['id'] == $info['doctor_id'])
  1345. {
  1346. return '';
  1347. }else{
  1348. return $info['doctor_name'];
  1349. }
  1350. }
  1351. public function sendEmail($email,$dcmPath,$name,$type=1)
  1352. {
  1353. $mail = new PHPMailer(true); // Passing `true` enables exceptions
  1354. try {
  1355. //服务器配置
  1356. $mail->CharSet ="UTF-8"; //设定邮件编码
  1357. $mail->SMTPDebug = 0; // 调试模式输出
  1358. $mail->isSMTP(); // 使用SMTP
  1359. $mail->Host = 'smtp.exmail.qq.com'; // SMTP服务器
  1360. $mail->SMTPAuth = true; // 允许 SMTP 认证
  1361. $mail->Username = 'company@pacsonline.cn'; // SMTP 用户名 即邮箱的用户名
  1362. $mail->Password = 'Zskk1234'; // SMTP 密码 部分邮箱是授权码(例如163邮箱)
  1363. $mail->SMTPSecure = 'ssl'; // 允许 TLS 或者ssl协议
  1364. $mail->Port = 465;
  1365. // $mail->SMTPOptions = [
  1366. // 'ssl' => [
  1367. // 'verify_peer' => false,
  1368. // 'verify_peer_name' => false,
  1369. // 'allow_self_signed' => true
  1370. // ]
  1371. // ];
  1372. $mail->SMTPOptions = array(
  1373. 'ssl' => array(
  1374. 'verify_peer' => false,
  1375. 'verify_peer_name' => false,
  1376. 'allow_self_signed' => true
  1377. )
  1378. );
  1379. // 服务器端口 25 或者465 具体要看邮箱服务器支持
  1380. $mail->setFrom('company@pacsonline.cn', '冠医云'); //发件人
  1381. $mail->addAddress($email, ''); // 收件人
  1382. //$mail->addAddress('ellen@example.com'); // 可添加多个收件人
  1383. $mail->addReplyTo('company@pacsonline.cn', '冠医云'); //回复的时候回复给哪个邮箱 建议和发件人一致
  1384. //$mail->addCC('cc@example.com'); //抄送
  1385. //$mail->addBCC('bcc@example.com'); //密送
  1386. $zipPath = ROOT_PATH . 'public';
  1387. // $maxsize = 45 * 1024 * 1024;
  1388. $mail->Subject = $name.'影像';
  1389. // if(filesize($zipPath.'/'.$dcmPath) < $maxsize)
  1390. // {
  1391. // //发送附件
  1392. //// $mail->addAttachment($zipPath.'a.zip'); // 添加附件
  1393. // $mail->addAttachment($zipPath.'/'.$dcmPath, $name.'.zip'); // 发送附件并且重命名
  1394. // $mail->Body = "链接将于".date('Y-m-d',time()+10*24*3600)."失效,请即时下载";
  1395. // $mail->AltBody = "链接将于".date('Y-m-d',time()+10*24*3600)."失效,请即时下载";
  1396. // }else{
  1397. //发送链接地址
  1398. //Content
  1399. $mail->isHTML(true); // 是否以HTML文档格式发送 发送后客户端可直接显示对应HTML内容
  1400. if($type == 4)
  1401. {
  1402. $dcmPath = $this->makeFileUrl($dcmPath,$type,'attachment','+3 days');
  1403. $dcmPath = ltrim($dcmPath,'/');
  1404. $mail->Body = "<a href='https://tempjn2.eos.jinan-4.cmecloud.cn/$dcmPath'>下载".$name."影像</a>"."<br>链接将于".date('Y-m-d',time()+3*24*3600)."失效,请及时下载";
  1405. }else
  1406. {
  1407. $mail->Body = "<a href='https://risserver3.pacsonline.cn/$dcmPath'>下载".$name."影像</a>"."<br>链接将于".date('Y-m-d',time()+3*24*3600)."失效,请及时下载";
  1408. }
  1409. // $mail->AltBody = '如果邮件客户端不支持HTML则显示此内容';
  1410. // }
  1411. $mail->send();
  1412. return '邮件发送成功';
  1413. } catch (Exception $e) {
  1414. // return '邮件发送失败: ';
  1415. return '邮件发送失败: '.$mail->ErrorInfo;
  1416. }
  1417. }
  1418. public function getAiReport($param)
  1419. {
  1420. $id = $param['exam_id'];
  1421. $data = $this->reportDao->getReport($id,3);
  1422. return $data;
  1423. }
  1424. public function deleteAiReport($param)
  1425. {
  1426. $id = $param['exam_id'];
  1427. $data = $this->reportDao->deleteAiReport($id,3);
  1428. return $data;
  1429. }
  1430. }