ZskkDefaultService.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. <?php
  2. namespace app\api\servies;
  3. use app\api\actions\ZskkCache;
  4. use app\api\dao\doctor\DoctorDao;
  5. use app\api\model\institution\InstitutionModel;
  6. use app\api\model\rota\RotaModel;
  7. use app\common\base\service\BaseService;
  8. use app\common\base\actions\IBaseAction;
  9. use app\common\base\actions\IBaseLog;
  10. use app\api\actions\ZskkDefaultAction;
  11. use app\api\actions\ZskkDefaultLog;
  12. use app\common\library\uploadToCloud;
  13. use think\Db;
  14. /**
  15. * 后台控制器基类
  16. * 接口方法权限 必传参数 接口返回 错误抛出 通用参数处理
  17. */
  18. class ZskkDefaultService extends BaseService implements IBaseAction, IBaseLog {
  19. use ZskkDefaultAction;
  20. use ZskkDefaultLog;
  21. use ZskkCache;
  22. protected $logName = "ZskkDefaultService";
  23. /**
  24. * 获取列表模糊搜索 where 条件
  25. * @param $params
  26. * @param $field
  27. * @return array|bool
  28. */
  29. public function getListFuzzyWhere($params, $field)
  30. {
  31. $where = false;
  32. if(isset($params['fuzzy_search']) && !empty($params['fuzzy_search'])){
  33. $where = '';
  34. $value = $params['fuzzy_search'];
  35. foreach ($field as $k=>$v){
  36. $where .= '`'. $v . '`' . ' LIKE '. ' \'%'. $value . '%\' ';
  37. // $where .= '`'. $v . '`' . ' = '. ' \''. $value . '\' ';
  38. if($k < count($field)-1){
  39. $where .= ' OR ';
  40. }
  41. }
  42. }
  43. return $where;
  44. }
  45. /**
  46. * 获取列表具体搜索 where 条件
  47. * @param $params
  48. * @param $field
  49. * @return array|bool
  50. */
  51. public function getListSpecificWhere($params, $field)
  52. {
  53. $where = false;
  54. if(isset($params['more_search']) && !empty($params['more_search'])){
  55. $more_search = $params['more_search'];
  56. $where = [];
  57. foreach ($more_search as $k=>$v){
  58. if(in_array($k, $field)){
  59. if($v['type'] == 'datetime'){
  60. if(empty($v['value'][0])){
  61. continue;
  62. }
  63. if($v['value'][0] == $v['value'][1]){
  64. $where[$k] = $v['value'][0];
  65. }else{
  66. $where[] = [$k,'between',[$v['value'][0], $v['value'][1]]];
  67. }
  68. }else{
  69. // 根据 type 获取具体的 where 条件
  70. $value = $this->formatSpecificWhere($v);
  71. if($value){
  72. $where[$k] = $value;
  73. }
  74. }
  75. }
  76. }
  77. }
  78. return $where;
  79. }
  80. //处理sex
  81. public function getSex($sexData)
  82. {
  83. $sex = '';
  84. switch ($sexData){
  85. case '男':
  86. $sex = 'M';
  87. break;
  88. case '女':
  89. $sex = 'F';
  90. break;
  91. case 'M':
  92. $sex = 'M';
  93. break;
  94. case 'F':
  95. $sex = 'F';
  96. break;
  97. default :
  98. $sex = $sexData;
  99. break;
  100. }
  101. return $sex;
  102. }
  103. /**
  104. * 格式化集体搜索 where 值
  105. * @param $value
  106. * @return array|bool
  107. * @author 马铁龙
  108. */
  109. public function formatSpecificWhere($value)
  110. {
  111. if(isset($value['type']) && !empty($value['type']) && isset($value['value']) && !empty($value['value'])){
  112. switch ($value['type']){
  113. case 'datetime':
  114. if(!isset($value['value'][0]) || empty($value['value'][0]) || !isset($value['value'][1]) || empty($value['value'][1])){
  115. return false;
  116. }
  117. return ['between',[$value['value'][0], $value['value'][1]]];
  118. case 'text' :
  119. if(!empty($value['value'])){
  120. return $value['value'];
  121. }
  122. return false;
  123. case 'in' :
  124. if(!empty($value['value'])){
  125. return ['in',explode(',', $value['value'])];
  126. }
  127. return false;
  128. case 'like':
  129. if(!empty($value['value'])){
  130. return [['like','%'.$value['value'].'%']];
  131. }
  132. return false;
  133. default:
  134. return false;
  135. }
  136. }
  137. return false;
  138. }
  139. public function getStageKey($report_id, $user_id)
  140. {
  141. return 'stage' . $report_id . $user_id;
  142. }
  143. public function curlJsonPost($url,$data)
  144. {
  145. $header = array(
  146. 'Authorization:'.'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJRCI6IjM0YmMxNjFmNWNjYmMyNzgyZGFkODkwYjYyNzE0Y2NiZjhhMzY0NzciLCJwYXRoIjoiXC9oaXNcL3YxXC90aWJldFwvbWVkaWNhbGNlbnRlcmFnZW50c1wvcHJlcGFyYXRpb25zIiwidXRjdGltZSI6IjIwMTktMDYtMjVUMDI6MjE6MjVaIn0.TZwTQxqvpXtBkE51fbzi2YYREO1LylH4EiQYWJ00i4o',
  147. 'Content-Type:'.'application/json;'
  148. );
  149. $ch = curl_init();
  150. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  151. curl_setopt($ch, CURLOPT_URL, $url);
  152. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  153. curl_setopt($ch, CURLOPT_HEADER, 0);
  154. curl_setopt($ch, CURLOPT_POST, 1);
  155. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  156. $data = curl_exec($ch);
  157. curl_close($ch);
  158. return $data;
  159. }
  160. public function curlJsonYbPost($url,$data)
  161. {
  162. $header = array(
  163. 'Authorization:'.'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJRCI6IjM0YmMxNjFmNWNjYmMyNzgyZGFkODkwYjYyNzE0Y2NiZjhhMzY0NzciLCJwYXRoIjoiXC9oaXNcL3YxXC90aWJldFwvbWVkaWNhbGNlbnRlcmFnZW50c1wvcHJlcGFyYXRpb25zIiwidXRjdGltZSI6IjIwMTktMDYtMjVUMDI6MjE6MjVaIn0.TZwTQxqvpXtBkE51fbzi2YYREO1LylH4EiQYWJ00i4o',
  164. 'Content-Type:'.'application/json;'
  165. );
  166. $ch = curl_init();
  167. curl_setopt($ch, CURLOPT_TIMEOUT, 1);
  168. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  169. curl_setopt($ch, CURLOPT_URL, $url);
  170. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  171. curl_setopt($ch, CURLOPT_HEADER, 0);
  172. curl_setopt($ch, CURLOPT_POST, 1);
  173. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  174. $data = curl_exec($ch);
  175. curl_close($ch);
  176. return $data;
  177. }
  178. function curlPost($url, $data) {
  179. //初使化init方法
  180. $ch = curl_init();
  181. //指定URL
  182. curl_setopt($ch, CURLOPT_URL, $url);
  183. //设定请求后返回结果
  184. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  185. //声明使用POST方式来进行发送
  186. curl_setopt($ch, CURLOPT_POST, 1);
  187. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
  188. //发送什么数据呢
  189. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  190. //忽略证书
  191. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  192. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  193. //忽略header头信息
  194. curl_setopt($ch, CURLOPT_HEADER, 0);
  195. //设置超时时间
  196. // curl_setopt($ch, CURLOPT_TIMEOUT, 10);
  197. //发送请求
  198. $output = curl_exec($ch);
  199. //关闭curl
  200. curl_close($ch);
  201. //返回数据
  202. return $output;
  203. }
  204. // public function curl_get($url){
  205. // //初始化
  206. // $curl = curl_init();
  207. // //设置抓取的url
  208. // curl_setopt($curl, CURLOPT_URL, $url);
  209. // //设置头文件的信息作为数据流输出
  210. // curl_setopt($curl, CURLOPT_HEADER, 0);
  211. // //设置获取的信息以文件流的形式返回,而不是直接输出。
  212. // curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  213. // // 重定向
  214. // curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
  215. // //执行命令
  216. // $data = curl_exec($curl);
  217. // //关闭URL请求
  218. // curl_close($curl);
  219. // return $data;
  220. // }
  221. function msectime() {
  222. list($msec, $sec) = explode(' ', microtime());
  223. $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
  224. return $msectime;
  225. }
  226. function request_by_curl($remote_server, $post_string,$header = array ('Content-Type: application/json;charset=utf-8')) {
  227. $ch = curl_init();
  228. curl_setopt($ch, CURLOPT_URL, $remote_server);
  229. curl_setopt($ch, CURLOPT_POST, 1);
  230. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
  231. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  232. curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
  233. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  234. // 线下环境不用开启curl证书验证, 未调通情况可尝试添加该代码
  235. // curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
  236. // curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
  237. $data = curl_exec($ch);
  238. curl_close($ch);
  239. return $data;
  240. }
  241. public function new_wechat_push($openid,$pushType,$content)
  242. {
  243. $c = urlencode($content);
  244. $url = "https://wechat.pacsonline.cn/wx_patient/api/sendMsg?openid=$openid&pushType=$pushType&content=$c";
  245. $data = $this->curl_get($url);
  246. return $data;
  247. }
  248. function curl_get($url){
  249. $header = array(
  250. 'Accept: application/json',
  251. );
  252. $curl = curl_init();
  253. //设置抓取的url
  254. curl_setopt($curl, CURLOPT_URL, $url);
  255. //设置头文件的信息作为数据流输出
  256. curl_setopt($curl, CURLOPT_HEADER, 0);
  257. // 超时设置,以秒为单位
  258. curl_setopt($curl, CURLOPT_TIMEOUT, 1000);
  259. // 超时设置,以毫秒为单位
  260. // curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
  261. // 设置请求头
  262. curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
  263. //设置获取的信息以文件流的形式返回,而不是直接输出。
  264. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  265. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  266. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  267. //执行命令
  268. $data = curl_exec($curl);
  269. return $data;
  270. // 显示错误信息
  271. // if (curl_error($curl)) {
  272. // print "Error: " . curl_error($curl);
  273. // } else {
  274. // // 打印返回的内容
  275. // curl_close($curl);
  276. // }
  277. }
  278. //计算总权重
  279. public function sum($arr)
  280. {
  281. $total = 0;
  282. foreach ($arr as $value) {
  283. $total += $value['weight'];
  284. }
  285. return $total;
  286. }
  287. // 处理队列
  288. public function handle_queue($institution)
  289. {
  290. //获取排队信息
  291. $queue = $this->getCache($institution.'_queue_'.date('Ymd'));
  292. //使用到了第几个
  293. $using = $this->getCache($institution.'_using_'.date('Ymd'));
  294. //医院每一轮的数量
  295. $allWeight = $this->getCache($institution.'_weight_'.date('Ymd'));
  296. if(empty($queue))
  297. {
  298. $insInfo = InstitutionModel::where('id',$institution)->find();
  299. if(empty($insInfo))
  300. {
  301. return "";
  302. }
  303. if($insInfo['is_auto_mode'] == '0')
  304. {
  305. // 没有开启自动分配
  306. return '';
  307. }
  308. $toady = date('Ymd');
  309. $rota = RotaModel::where('institution_id',$institution)->where('rota_datetime',$toady)->select()->toArray();
  310. if(empty($rota))
  311. {
  312. //没有今天的队列消息
  313. return '';
  314. }
  315. $using_num = 1;
  316. //获取医生列表
  317. $list = DB::table('doctors')->where('institution_id',$institution)->order('weight desc')->select();
  318. $arr = [];
  319. $use = [];
  320. foreach ($list as $k=>$v)
  321. {
  322. $arr[$v['id']] = $v['weight'];
  323. $use[$v['id']] = $v['weight'];
  324. }
  325. arsort($arr);
  326. arsort($use);
  327. // 获取权重总数
  328. $all = $this->sum($list);
  329. // 存储总权重
  330. $this->setCache($institution.'_weight_'.date('Ymd'),$all,86400);
  331. $data = [];
  332. for($i=1;$i<=$all;$i++)
  333. {
  334. if($i == 1)
  335. {
  336. //获取当前权重最大的一个医生
  337. $did = array_search(max($arr), $arr);
  338. $data[$i] = $did;
  339. //当前医生可使用-1
  340. $use[$did]--;
  341. }else{
  342. $second = [];
  343. //获取当前可使用权重最大的一个医生
  344. $did = array_search(max($use), $use);
  345. if($use[$did] == $arr[$did])
  346. {
  347. //当前医生权重已使用为最大权重 代表使用率为0 则分配给当前医生
  348. $data[$i] = $did;
  349. $use[$did] --;
  350. }else{
  351. $secondArray = $use;
  352. unset($second[$did]);
  353. $second = array_search(max($secondArray), $secondArray);
  354. if($use[$second] == $arr[$second])
  355. {
  356. //当前医生权重已使用为0 则分配给当前医生
  357. $data[$i] = $second;
  358. $use[$second] --;
  359. }else{
  360. if($use[$did] == $use[$second])
  361. {
  362. //存在多个未使用权重相同的情况
  363. $third = 0;
  364. $lastDoctor = $use[$second];
  365. foreach ($use as $k=>$v)
  366. {
  367. if($third == 0)
  368. {
  369. $lastDoctor = $k;
  370. $third = $v;
  371. }else{
  372. if($third == $v)
  373. {
  374. $lastDoctor = $k;
  375. }
  376. }
  377. }
  378. // 多个医生剩余权重使用数相同的情况 则分配给初始权重最低的那一个
  379. $data[$i] = $lastDoctor;
  380. $use[$lastDoctor]--;
  381. }else{
  382. $data[$i] = $did;
  383. $use[$did]--;
  384. }
  385. }
  386. }
  387. }
  388. }
  389. $using_num++;
  390. // 存储轮换使用的个数
  391. $this->setCache($institution.'_using_'.date('Ymd'),$using_num);
  392. // 存储医生队列的信息
  393. $this->setCache($institution.'_queue_'.date('Ymd'),$data,86400);
  394. //第一次进来
  395. return $data[$using_num];
  396. }else{
  397. $useing_num = $using+1;
  398. if ($useing_num == $allWeight)
  399. {
  400. // 满足一轮权重轮换
  401. $this->setCache($institution.'_using_'.date('Ymd'),0);
  402. }else{
  403. $this->setCache($institution.'_using_'.date('Ymd'),$useing_num);
  404. }
  405. return $queue[$useing_num];
  406. }
  407. }
  408. public function downLoad($url, $path,$create) {
  409. $pic_local = $path.'.dcm';
  410. if (!file_exists($create)) {
  411. mkdir($create, 0777,true);
  412. @chmod($create, 0777);
  413. }
  414. ob_start(); //打开输出
  415. readfile($url); //输出图片文件
  416. $img = ob_get_contents(); //得到浏览器输出
  417. ob_end_clean(); //清除输出并关闭
  418. file_put_contents($pic_local, $img);
  419. return $pic_local;
  420. }
  421. //获取毫秒级年月日时分秒
  422. public function ts_time($format = 'u', $utimestamp = null) {
  423. if (is_null($utimestamp)){
  424. $utimestamp = microtime(true);
  425. }
  426. $timestamp = floor($utimestamp);
  427. $milliseconds = round(($utimestamp - $timestamp) * 1000);
  428. return date('Y-m-d H:i:s.'.str_pad(preg_replace('`(?<!\\\\)u`', $milliseconds, $format),3,0), $timestamp);
  429. }
  430. public function makeFileUrl($file,$type,$fileType='attachment',$expires='+12 hours',$bucket='')
  431. {
  432. $data = $file;
  433. if($type == '2')
  434. {
  435. // 移动云普通文件
  436. if(!empty($file))
  437. {
  438. $upload = new uploadToCloud();
  439. $data = $upload->makeUrl($file,$fileType,$expires,$bucket);
  440. }
  441. }elseif ($type == '1')
  442. {
  443. // 普通ris文件
  444. if(!empty($file))
  445. {
  446. $data = $file;
  447. }
  448. }elseif ($type == '3')
  449. {
  450. // 远程诊断视频
  451. if(!empty($file))
  452. {
  453. $upload = new uploadToCloud();
  454. $data = $upload->makeCloudUrl($file,$fileType,2,$expires);
  455. }
  456. }elseif ($type == '4')
  457. {
  458. // dcm影像压缩包
  459. if(!empty($file))
  460. {
  461. $upload = new uploadToCloud();
  462. $data = $upload->makeCloudUrl($file,$fileType,3,$expires);
  463. }
  464. }
  465. return $data;
  466. }
  467. }