common.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: 流年 <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. // 应用公共文件
  12. mb_internal_encoding("UTF-8"); //解决汉字长度与字符长度不一致问题 验证length问题 开mb_string扩展
  13. /**
  14. * 校验手机格式
  15. * @param $phone
  16. * @return int
  17. */
  18. function check_mobile($phone){
  19. return preg_match("/1\d{10}$/",$phone);
  20. }
  21. /**
  22. * [check_email 校验邮箱格式]
  23. */
  24. function check_email($email){
  25. $pattern = "/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/i";
  26. return preg_match($pattern,$email);
  27. }
  28. /**
  29. * 字符串截取,支持中文和其他编码
  30. * @static
  31. * @access public
  32. * @param string $str 需要转换的字符串
  33. * @param string $start 开始位置
  34. * @param string $length 截取长度
  35. * @param string $charset 编码格式
  36. * @param string $suffix 截断显示字符
  37. * @return string
  38. */
  39. function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=false) {
  40. if(function_exists("mb_substr"))
  41. $slice = mb_substr($str, $start, $length, $charset);
  42. elseif(function_exists('iconv_substr')) {
  43. $slice = iconv_substr($str,$start,$length,$charset);
  44. if(false === $slice) {
  45. $slice = '';
  46. }
  47. }else{
  48. $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
  49. $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
  50. $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
  51. $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
  52. preg_match_all($re[$charset], $str, $match);
  53. $slice = join("",array_slice($match[0], $start, $length));
  54. }
  55. return $suffix ? $slice.'...' : $slice;
  56. }
  57. /**
  58. * 系统加密方法
  59. * @param string $data 要加密的字符串
  60. * @param string $key 加密密钥
  61. * @param int $expire 过期时间 单位 秒
  62. * @return string
  63. */
  64. function think_encrypt($data, $key = '', $expire = 0) {
  65. $key = md5(empty($key) ? config('app.encryption_key') : $key);
  66. $data = base64_encode($data);
  67. $x = 0;
  68. $len = strlen($data);
  69. $l = strlen($key);
  70. $char = '';
  71. for ($i = 0; $i < $len; $i++) {
  72. if ($x == $l) $x = 0;
  73. $char .= substr($key, $x, 1);
  74. $x++;
  75. }
  76. $str = sprintf('%010d', $expire ? $expire + time():0);
  77. for ($i = 0; $i < $len; $i++) {
  78. $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1)))%256);
  79. }
  80. return str_replace(array('+','/','='),array('-','_',''),base64_encode($str));
  81. }
  82. /**
  83. * 系统解密方法
  84. * @param string $data 要解密的字符串 (必须是think_encrypt方法加密的字符串)
  85. * @param string $key 加密密钥
  86. * @return string
  87. */
  88. function think_decrypt($data, $key = ''){
  89. $key = md5(empty($key) ? config('app.encryption_key') : $key);
  90. $data = str_replace(array('-','_'),array('+','/'),$data);
  91. $mod4 = strlen($data) % 4;
  92. if ($mod4) {
  93. $data .= substr('====', $mod4);
  94. }
  95. $data = base64_decode($data);
  96. $expire = substr($data,0,10);
  97. $data = substr($data,10);
  98. if($expire > 0 && $expire < time()) {
  99. return '';
  100. }
  101. $x = 0;
  102. $len = strlen($data);
  103. $l = strlen($key);
  104. $char = $str = '';
  105. for ($i = 0; $i < $len; $i++) {
  106. if ($x == $l) $x = 0;
  107. $char .= substr($key, $x, 1);
  108. $x++;
  109. }
  110. for ($i = 0; $i < $len; $i++) {
  111. if (ord(substr($data, $i, 1))<ord(substr($char, $i, 1))) {
  112. $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
  113. }else{
  114. $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
  115. }
  116. }
  117. return base64_decode($str);
  118. }
  119. /**
  120. * 根据省份证号获取生日和性别
  121. * @param $idcard
  122. * @return array
  123. */
  124. function get_birthday_sex_by_idcard($idcard){
  125. if(mb_strlen($idcard) != 18){
  126. return ['birthday'=>null,'gender'=>0];
  127. }
  128. $birthday = msubstr($idcard, 6, 8);
  129. $birthday = date('Y-m-d',strtotime($birthday));
  130. $gender = msubstr($idcard,16,1)%2;
  131. $gender = $gender?1:2;
  132. return ['birthday'=>$birthday,'gender'=>$gender];
  133. }
  134. /**
  135. * ajax 请求正确返回
  136. * @param string $msg
  137. * @param array $data
  138. * @return json
  139. */
  140. function ajax_return_ok($data = array(),$msg = ''){
  141. $result['code'] = 0;
  142. $result['data'] = $data;
  143. $result['message'] = $msg ;
  144. header('Content-Type:application/json; charset=utf-8');
  145. if(version_compare(PHP_VERSION,'5.4.0','<')){
  146. exit(json_encode($result));
  147. }else{
  148. exit(json_encode($result,JSON_UNESCAPED_UNICODE)); //显示中文
  149. }
  150. }
  151. /**
  152. * ajax 请求错误返回
  153. * @param string $msg
  154. * @param string $code
  155. * @return json
  156. */
  157. function ajax_return_error($msg = null,$code = 1){
  158. if ($msg == null){
  159. $msgDefault = config ( 'e_msg_default' );
  160. $result['msg'] = $msgDefault [$code];
  161. }else{
  162. $result['msg'] = $msg ;
  163. }
  164. $result['status'] = 0;
  165. $result['code'] = $code;
  166. header('Content-Type:application/json; charset=utf-8');
  167. if(version_compare(PHP_VERSION,'5.4.0','<')){
  168. exit(json_encode($result));
  169. }else{
  170. exit(json_encode($result,JSON_UNESCAPED_UNICODE)); //显示中文
  171. }
  172. }
  173. /**
  174. * AES 128 ecb 加密 与java加密保持一致
  175. * @param $data 加密字符串
  176. * @param $key 加密key
  177. * @return string 加密串
  178. */
  179. function aes_encrypt($data) {
  180. $key = config('app.encryption_key');
  181. $data = openssl_encrypt($data, 'aes-128-ecb', $key, OPENSSL_RAW_DATA);
  182. return base64_encode($data);
  183. }
  184. /**
  185. * AES 128 ecb 解密 与java加密保持一致
  186. * @param $data 解密字符串
  187. * @param $key 加密key
  188. * @return string 解密串
  189. */
  190. function aes_decrypt($data) {
  191. $key = config('app.encryption_key');
  192. $encrypted = base64_decode($data);
  193. return openssl_decrypt($encrypted, 'aes-128-ecb', $key, OPENSSL_RAW_DATA);
  194. }
  195. /**
  196. * 下划线转驼峰
  197. * @param $str
  198. * @return string|string[]|null
  199. */
  200. function line_to_hump($str){
  201. return preg_replace_callback('/(_[a-z])/', function ($match) {
  202. return ucfirst(trim($match[0], '_'));
  203. }, $str);
  204. }
  205. /**
  206. * 驼峰转下划线
  207. * @param $str
  208. * @return string|string[]|null
  209. */
  210. function hump_to_line($str){
  211. return preg_replace_callback('/([A-Z])/', function ($match) {
  212. return '_' . lcfirst($match[0]);
  213. }, $str);
  214. }
  215. /**
  216. * 多维数组键值下划线转换为驼峰
  217. * @param $arr
  218. * @return array
  219. */
  220. function array_change_line_to_hump($arr){
  221. $tem = [];
  222. foreach ($arr as $k=>$v){
  223. if(is_array($v)){
  224. $tem[line_to_hump($k)] = array_change_line_to_hump($v);
  225. }else{
  226. $tem[line_to_hump($k)] = $v;
  227. }
  228. }
  229. return $tem;
  230. }
  231. /**
  232. * 多维数组取某一字段
  233. * @param array $arr
  234. * @param string $field 要删除字段
  235. * @param string $child
  236. * @return array
  237. */
  238. function array_delete_char($arr,$field,$child = 'depAndJobDtos'){
  239. $tem = [];
  240. foreach ($arr as $k=>$v){
  241. unset($v[$field]);
  242. if(!empty($v[$child])){
  243. $v[$child] = array_delete_char($v[$child],$field);
  244. }
  245. $tem[$k] = $v;
  246. }
  247. return $tem;
  248. }
  249. /**
  250. * 把返回的数据集转换成Tree 主要组织部门岗位人员树使用
  251. * @param array $list 要转换的数据集
  252. * @param string $pid parent标记字段
  253. * @param string $child 子孙键名
  254. * @param int $root 父级值
  255. * @return array
  256. */
  257. function list_to_tree($list, $pid = 'pid', $child = '_child', $root = 0)
  258. {
  259. $tree = [];
  260. foreach($list as $k => $v){
  261. if($v[$pid] == $root){
  262. $children = list_to_tree($list, $pid, $child, $v['id']);
  263. if(!empty($v[$child])){
  264. $children = array_merge($children,$v[$child]);
  265. }
  266. $v[$child] = $children;
  267. $tree[] = $v;
  268. }
  269. }
  270. return $tree;
  271. }
  272. /**
  273. * 获取编号
  274. * @param $prefix
  275. * @return string
  276. */
  277. function get_unique_id($prefix=''){
  278. return $prefix.date('Ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
  279. }
  280. // 获取9位随机数
  281. function get_rand_num(){
  282. return mt_rand(100000000,999999999);
  283. }
  284. /**
  285. * flowjson排序
  286. * @param $flowJson
  287. * @param string $nodeid
  288. * @param array $result
  289. * @return array
  290. */
  291. function sort_flow_json($flowJson,$nodeid='',&$result=[]){
  292. foreach ($flowJson as $k=>$v){
  293. if((!$nodeid && $v['type'] == 1) || $nodeid && $v['id'] == $nodeid){
  294. $result[] = $v;
  295. if(count($result) != count($flowJson)){
  296. sort_flow_json($flowJson,$v['nextId'],$result);
  297. break;
  298. }
  299. }
  300. }
  301. return $result;
  302. }
  303. /**
  304. * 获取合同编号
  305. * @param int $type 0=普通合同 1=追加合同
  306. * @param int $applyId 追加合同id
  307. */
  308. function get_contact_sn($pre,$type=0,$applyId=0){
  309. return get_unique_id($pre);
  310. }
  311. /**
  312. *
  313. * @param $start
  314. * @param $end
  315. * @param $type
  316. * @return float|int
  317. */
  318. function calculate_leave($start,$end,$type){
  319. $starts = explode(' ',$start);
  320. $ends = explode(' ',$end);
  321. $start = date('Ymd',strtotime($starts[0]));
  322. $stxt = $starts[count($starts) - 1]; // 去最后一个元素,以防日期与上下午之间存在多个空格,其中一端有这错误
  323. $end = date('Ymd',strtotime($ends[0]));
  324. $etxt = $ends[count($ends) - 1];
  325. if($start > $end){
  326. return 0;
  327. }
  328. $bxday = \think\Db::name('holiday')
  329. ->where('holiday',0)
  330. ->where('day','>=',date('Y-m-d',strtotime($starts[0])))
  331. ->where('day','<=',date('Y-m-d',strtotime($ends[0])))
  332. ->column('day');
  333. $bxday = $bxday?$bxday:[];
  334. $holiday = \think\Db::name('holiday')
  335. ->where('holiday',1)
  336. ->where('day','>=',date('Y-m-d',strtotime($starts[0])))
  337. ->where('day','<=',date('Y-m-d',strtotime($ends[0])))
  338. ->column('day');
  339. $holiday = $holiday?$holiday:[];
  340. $days = 0;
  341. $cday = (strtotime($end) - strtotime($start))/86400 + 1;
  342. for ($i=1;$i<=$cday;$i++){
  343. if($type == 1){ // 减去节假日
  344. $cur = strtotime($start) + ($i-1)*86400;
  345. $w = date('w',$cur);
  346. $itxt = date('Y-m-d',$cur);
  347. if($i == 1&&$stxt == '下午'){ // 开始日期
  348. $days += 0.5;
  349. } else if($i == $cday && $etxt == '上午'){
  350. $days += 0.5;
  351. }else{
  352. $days++;
  353. }
  354. /*if(($w == 6 || $w == 0) && in_array($itxt,$bxday)){ // 检查是否是补休日
  355. if($i == 1 && $stxt == '下午'){ // 开始日期
  356. $days += 0.5;
  357. }else if($i == $cday && $etxt == '上午'){
  358. $days += 0.5;
  359. }else{
  360. $days++;
  361. }
  362. } else if($w >0 && $w < 6 && !in_array($itxt,$holiday)){
  363. if($i == 1&&$stxt == '下午'){ // 开始日期
  364. $days += 0.5;
  365. } else if($i == $cday && $etxt == '上午'){
  366. $days += 0.5;
  367. }else{
  368. $days++;
  369. }
  370. }*/
  371. } else { // 不减节假日
  372. $days++;
  373. }
  374. }
  375. return $days;
  376. }
  377. /**
  378. * 计算社保比例金额
  379. * @param $money
  380. * @param $bl
  381. * @param $bl_type
  382. * @param $bl_extra
  383. * @param $free_bl
  384. * @return false|float
  385. */
  386. function calculate_money($money,$bl,$bl_type,$bl_extra,$free_bl){
  387. $gjjp = $money*$bl;
  388. if($bl_extra > 0){
  389. if($bl_type == 1){ // 比例
  390. $gjjp += $money*$bl_extra;
  391. } else { // 整数
  392. $gjjp += $bl_extra;
  393. }
  394. }
  395. $gjjp = $gjjp*(1 - $free_bl);
  396. return round($gjjp,2);
  397. }
  398. /**
  399. * 极光推送
  400. * @param array $userids
  401. * @param string $msg
  402. * @param array $extras
  403. */
  404. function send_jpush($userids,$msg='',$extras=array()){
  405. try { //不管推送成功与失败,不能影响正常业务流程
  406. $jpushconfig = config('app.jpush');
  407. $client = new \JPush\Client($jpushconfig['appkey'], $jpushconfig['mastersecret'],null);
  408. $push = $client->push();
  409. $push->setOptions(null,null,null, true);
  410. $push->setPlatform(array('ios', 'android'));
  411. foreach ($userids as $k=>$v){
  412. $userids[$k] = (string)$v;
  413. }
  414. $push->addAlias($userids);
  415. $push->androidNotification($msg, array(
  416. 'extras' => $extras
  417. ));
  418. $sound = 'default';
  419. $push->iosNotification($msg, array(
  420. 'sound' => $sound,
  421. 'badge' => '+1',
  422. 'extras' => $extras
  423. ));
  424. $ret = $push->send();
  425. trace($ret);
  426. } catch (Exception $e) {
  427. trace('push-error:',$e->getMessage());
  428. }
  429. }
  430. /**
  431. * 计算年龄/工龄
  432. * @param $date
  433. * @return false|mixed|string
  434. */
  435. function calculate_age($date){
  436. list($year,$month,$day) = explode("-",$date);
  437. $year_diff = date("Y") - $year;
  438. $month_diff = date("m") - $month;
  439. $day_diff = date("d") - $day;
  440. if($month_diff > 0){ // 生日已过
  441. return $year_diff;
  442. }else if($month_diff == 0){ // 生日已过
  443. if($day_diff >= 0){ //
  444. return $year_diff;
  445. }else{
  446. return $year_diff - 1;
  447. }
  448. }else{
  449. return $year_diff - 1;
  450. }
  451. }
  452. // 过滤以逗号分隔的内容,去掉空项
  453. function check_exp_imp($data){
  454. if(!$data){
  455. return '';
  456. }
  457. $vals = explode(',',$data);
  458. $nr = [];
  459. foreach ($vals as $v){
  460. if($v && !in_array($v,$nr)){
  461. $nr[] = $v;
  462. }
  463. }
  464. return empty($nr)?'':implode(',',$nr);
  465. }
  466. function curl_post($url, $data=[]) {
  467. try{
  468. $ch = curl_init ();
  469. $header = array ("Accept-Charset: utf-8",'Expect:' );
  470. curl_setopt ( $ch, CURLOPT_URL, $url );
  471. curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
  472. curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
  473. curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
  474. curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header );
  475. curl_setopt ( $ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)' );
  476. curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 );
  477. curl_setopt ( $ch, CURLOPT_AUTOREFERER, 1 );
  478. curl_setopt ( $ch, CURLOPT_TIMEOUT, 10 );
  479. // 最好加上http_build_query 转换,防止有些服务器不兼容
  480. if($data){
  481. curl_setopt ( $ch, CURLOPT_POSTFIELDS, http_build_query ( $data ) );
  482. }
  483. curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
  484. $result = curl_exec ( $ch );
  485. curl_close ( $ch );
  486. return $result;
  487. }catch (Exception $e){
  488. return false;
  489. }
  490. }
  491. function is_utf8($string) {
  492. // From http://w3.org/International/questions/qa-forms-utf-8.html
  493. return preg_match('%^(?:
  494. [\x09\x0A\x0D\x20-\x7E] # ASCII
  495. | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
  496. | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
  497. | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
  498. | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
  499. | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
  500. | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
  501. | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
  502. )*$%xs', $string);
  503. }
  504. // 获取当前售卖日期
  505. function get_dinner_day(){
  506. $week = date('w');
  507. $day = date('Y-m-d',time() + 24*60*60);
  508. if($week == 5){
  509. $day = date('Y-m-d',time() + 3*24*60*60);
  510. }else if($week == 6){
  511. $day = date('Y-m-d',time() + 2*24*60*60);
  512. }
  513. return $day;
  514. }
  515. /**
  516. * 根据日期获取上一月
  517. * @param $day
  518. */
  519. function get_lastmonth_by_day($day){
  520. $year = date('Y',strtotime($day));
  521. $month = date('m',strtotime($day));
  522. if($month == 1){
  523. $lastmonth = ($year-1).'-12';
  524. }else if($month <= 10){
  525. $lastmonth = $year.'-0'.($month-1);
  526. }else{
  527. $lastmonth = $year.'-'.($month-1);
  528. }
  529. return $lastmonth;
  530. }
  531. function get_attentance_srecord($records,$val){
  532. $sarr = [];
  533. $ids = [];
  534. foreach ($records as $k => $v){
  535. $ct = strtotime($v['create_time']);
  536. $st = strtotime($val['stime']);
  537. $et = strtotime($val['etime']);
  538. if($ct < $et && $ct > $st){ // 迟到
  539. $v['cate'] = 1;
  540. $v['status'] = 1;
  541. $sarr[] = $v;
  542. $ids[] = $k;
  543. break;
  544. }else if($ct <= $st){ // 正常上班
  545. $v['cate'] = 1;
  546. $v['status'] = 0;
  547. $sarr[] = $v;
  548. $ids[] = $k;
  549. break;
  550. }else if($ct >= $et){ // 缺卡
  551. }
  552. }
  553. $lastrecords = [];
  554. foreach ($records as $k=>$v){
  555. if(!in_array($k,$ids)){
  556. $lastrecords[] = $v;
  557. }
  558. }
  559. return ['arr' => $sarr,'record' => $lastrecords];
  560. }
  561. function get_attentance_erecord($records,$val,$nstart=''){
  562. $sarr = [];
  563. $ids = [];
  564. foreach ($records as $k => $v){
  565. if(!$nstart){ // 最后一班
  566. $ct = strtotime($v['create_time']);
  567. $et = strtotime($val['etime']);
  568. $v['cate'] = 2;
  569. if($ct < $et){ // 早退
  570. $v['status'] = 2;
  571. }else if($ct >= $et){ // 正常下班
  572. $v['status'] = 0;
  573. }
  574. $sarr[] = $v;
  575. $ids[] = $k;
  576. }else{
  577. $ct = strtotime($v['create_time']);
  578. $et = strtotime($val['etime']);
  579. $nst = strtotime($nstart);
  580. $v['cate'] = 2;
  581. $v['status'] = 0;
  582. if($ct < $et){ // 早退
  583. $v['status'] = 2;
  584. $sarr[] = $v;
  585. $ids[] = $k;
  586. }else if($ct >= $et && $ct < $nst){ // 正常下班
  587. $v['status'] = 0;
  588. $sarr[] = $v;
  589. $ids[] = $k;
  590. break;
  591. }
  592. }
  593. }
  594. $lastrecords = [];
  595. foreach ($records as $k=>$v){
  596. if(!in_array($k,$ids)){
  597. $lastrecords[] = $v;
  598. }
  599. }
  600. return ['arr' => $sarr,'record' => $lastrecords];
  601. }