common.php 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659
  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. use app\common\model\Config;
  13. use tools\Qxsms;
  14. /**
  15. * 校验手机格式
  16. * @param $phone
  17. * @return int
  18. */
  19. function check_mobile($phone){
  20. return preg_match("/1\d{10}$/",$phone);
  21. }
  22. /**
  23. * [check_email 校验邮箱格式]
  24. */
  25. function check_email($email){
  26. $pattern = "/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/i";
  27. return preg_match($pattern,$email);
  28. }
  29. /**
  30. * 字符串截取,支持中文和其他编码
  31. * @static
  32. * @access public
  33. * @param string $str 需要转换的字符串
  34. * @param string $start 开始位置
  35. * @param string $length 截取长度
  36. * @param string $charset 编码格式
  37. * @param string $suffix 截断显示字符
  38. * @return string
  39. */
  40. function msubstr($str, $start=0, $length, $charset="utf-8", $suffix=false) {
  41. if(function_exists("mb_substr"))
  42. $slice = mb_substr($str, $start, $length, $charset);
  43. elseif(function_exists('iconv_substr')) {
  44. $slice = iconv_substr($str,$start,$length,$charset);
  45. if(false === $slice) {
  46. $slice = '';
  47. }
  48. }else{
  49. $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
  50. $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
  51. $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
  52. $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
  53. preg_match_all($re[$charset], $str, $match);
  54. $slice = join("",array_slice($match[0], $start, $length));
  55. }
  56. return $suffix ? $slice.'...' : $slice;
  57. }
  58. /**
  59. * 系统加密方法
  60. * @param string $data 要加密的字符串
  61. * @param string $key 加密密钥
  62. * @param int $expire 过期时间 单位 秒
  63. * @return string
  64. */
  65. function think_encrypt($data, $key = '', $expire = 0) {
  66. $key = md5(empty($key) ? config('app.encryption_key') : $key);
  67. $data = base64_encode($data);
  68. $x = 0;
  69. $len = strlen($data);
  70. $l = strlen($key);
  71. $char = '';
  72. for ($i = 0; $i < $len; $i++) {
  73. if ($x == $l) $x = 0;
  74. $char .= substr($key, $x, 1);
  75. $x++;
  76. }
  77. $str = sprintf('%010d', $expire ? $expire + time():0);
  78. for ($i = 0; $i < $len; $i++) {
  79. $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1)))%256);
  80. }
  81. return str_replace(array('+','/','='),array('-','_',''),base64_encode($str));
  82. }
  83. /**
  84. * 系统解密方法
  85. * @param string $data 要解密的字符串 (必须是think_encrypt方法加密的字符串)
  86. * @param string $key 加密密钥
  87. * @return string
  88. */
  89. function think_decrypt($data, $key = ''){
  90. $key = md5(empty($key) ? config('app.encryption_key') : $key);
  91. $data = str_replace(array('-','_'),array('+','/'),$data);
  92. $mod4 = strlen($data) % 4;
  93. if ($mod4) {
  94. $data .= substr('====', $mod4);
  95. }
  96. $data = base64_decode($data);
  97. $expire = substr($data,0,10);
  98. $data = substr($data,10);
  99. if($expire > 0 && $expire < time()) {
  100. return '';
  101. }
  102. $x = 0;
  103. $len = strlen($data);
  104. $l = strlen($key);
  105. $char = $str = '';
  106. for ($i = 0; $i < $len; $i++) {
  107. if ($x == $l) $x = 0;
  108. $char .= substr($key, $x, 1);
  109. $x++;
  110. }
  111. for ($i = 0; $i < $len; $i++) {
  112. if (ord(substr($data, $i, 1))<ord(substr($char, $i, 1))) {
  113. $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
  114. }else{
  115. $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
  116. }
  117. }
  118. return base64_decode($str);
  119. }
  120. /**
  121. * 根据省份证号获取生日和性别
  122. * @param $idcard
  123. * @return array
  124. */
  125. function get_birthday_sex_by_idcard($idcard){
  126. if(mb_strlen($idcard) != 18){
  127. return ['birthday'=>null,'gender'=>0];
  128. }
  129. $birthday = msubstr($idcard, 6, 8);
  130. $birthday = date('Y-m-d',strtotime($birthday));
  131. $gender = msubstr($idcard,16,1)%2;
  132. $gender = $gender?1:2;
  133. return ['birthday'=>$birthday,'gender'=>$gender];
  134. }
  135. /**
  136. * ajax 请求正确返回
  137. * @param string $msg
  138. * @param array $data
  139. * @return json
  140. */
  141. function ajax_return_ok($data = array(),$msg = ''){
  142. $result['code'] = 0;
  143. $result['data'] = $data;
  144. $result['message'] = $msg ;
  145. header('Content-Type:application/json; charset=utf-8');
  146. if(version_compare(PHP_VERSION,'5.4.0','<')){
  147. exit(json_encode($result));
  148. }else{
  149. exit(json_encode($result,JSON_UNESCAPED_UNICODE)); //显示中文
  150. }
  151. }
  152. /**
  153. * ajax 请求错误返回
  154. * @param string $msg
  155. * @param string $code
  156. * @return json
  157. */
  158. function ajax_return_error($msg = null,$code = 1){
  159. if ($msg == null){
  160. $msgDefault = config ( 'e_msg_default' );
  161. $result['msg'] = $msgDefault [$code];
  162. }else{
  163. $result['msg'] = $msg ;
  164. }
  165. $result['status'] = 0;
  166. $result['code'] = $code;
  167. header('Content-Type:application/json; charset=utf-8');
  168. if(version_compare(PHP_VERSION,'5.4.0','<')){
  169. exit(json_encode($result));
  170. }else{
  171. exit(json_encode($result,JSON_UNESCAPED_UNICODE)); //显示中文
  172. }
  173. }
  174. /**
  175. * AES 128 ecb 加密 与java加密保持一致
  176. * @param $data 加密字符串
  177. * @param $key 加密key
  178. * @return string 加密串
  179. */
  180. function aes_encrypt($data) {
  181. $key = config('app.encryption_key');
  182. $data = openssl_encrypt($data, 'aes-128-ecb', $key, OPENSSL_RAW_DATA);
  183. return base64_encode($data);
  184. }
  185. /**
  186. * AES 128 ecb 解密 与java加密保持一致
  187. * @param $data 解密字符串
  188. * @param $key 加密key
  189. * @return string 解密串
  190. */
  191. function aes_decrypt($data) {
  192. $key = config('app.encryption_key');
  193. $encrypted = base64_decode($data);
  194. return openssl_decrypt($encrypted, 'aes-128-ecb', $key, OPENSSL_RAW_DATA);
  195. }
  196. /**
  197. * 下划线转驼峰
  198. * @param $str
  199. * @return string|string[]|null
  200. */
  201. function line_to_hump($str){
  202. return preg_replace_callback('/(_[a-z])/', function ($match) {
  203. return ucfirst(trim($match[0], '_'));
  204. }, $str);
  205. }
  206. /**
  207. * 驼峰转下划线
  208. * @param $str
  209. * @return string|string[]|null
  210. */
  211. function hump_to_line($str){
  212. return preg_replace_callback('/([A-Z])/', function ($match) {
  213. return '_' . lcfirst($match[0]);
  214. }, $str);
  215. }
  216. /**
  217. * 多维数组键值下划线转换为驼峰
  218. * @param $arr
  219. * @return array
  220. */
  221. function array_change_line_to_hump($arr){
  222. $tem = [];
  223. foreach ($arr as $k=>$v){
  224. if(is_array($v)){
  225. $tem[line_to_hump($k)] = array_change_line_to_hump($v);
  226. }else{
  227. $tem[line_to_hump($k)] = $v;
  228. }
  229. }
  230. return $tem;
  231. }
  232. /**
  233. * 多维数组取某一字段
  234. * @param array $arr
  235. * @param string $field 要删除字段
  236. * @param string $child
  237. * @return array
  238. */
  239. function array_delete_char($arr,$field,$child = 'depAndJobDtos'){
  240. $tem = [];
  241. foreach ($arr as $k=>$v){
  242. unset($v[$field]);
  243. if(!empty($v[$child])){
  244. $v[$child] = array_delete_char($v[$child],$field);
  245. }
  246. $tem[$k] = $v;
  247. }
  248. return $tem;
  249. }
  250. /**
  251. * 把返回的数据集转换成Tree 主要组织部门岗位人员树使用
  252. * @param array $list 要转换的数据集
  253. * @param string $pid parent标记字段
  254. * @param string $child 子孙键名
  255. * @param int $root 父级值
  256. * @return array
  257. */
  258. function list_to_tree($list, $pid = 'pid', $child = '_child', $root = 0)
  259. {
  260. $tree = [];
  261. foreach($list as $k => $v){
  262. if($v[$pid] == $root){
  263. $children = list_to_tree($list, $pid, $child, $v['id']);
  264. if(!empty($v[$child])){
  265. $children = array_merge($children,$v[$child]);
  266. }
  267. $v[$child] = $children;
  268. $tree[] = $v;
  269. }
  270. }
  271. return $tree;
  272. }
  273. /**
  274. * 获取编号
  275. * @param $prefix
  276. * @return string
  277. */
  278. function get_unique_id($prefix=''){
  279. return $prefix.date('Ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 12), 1))), 0, 8);
  280. }
  281. /**
  282. * 获取编号
  283. * @param string $prefix
  284. * @return string
  285. */
  286. function get_unique_sn($prefix=''){
  287. return $prefix.date('YmdHis').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 12), 1))), 0, 6);
  288. }
  289. /**
  290. * flowjson排序
  291. * @param $flowJson
  292. * @param string $nodeid
  293. * @param array $result
  294. * @return array
  295. */
  296. function sort_flow_json($flowJson,$nodeid='',&$result=[]){
  297. foreach ($flowJson as $k=>$v){
  298. if((!$nodeid && $v['type'] == 1) || $nodeid && $v['id'] == $nodeid){
  299. $result[] = $v;
  300. if(count($result) != count($flowJson)){
  301. sort_flow_json($flowJson,$v['nextId'],$result);
  302. break;
  303. }
  304. }
  305. }
  306. return $result;
  307. }
  308. /**
  309. *
  310. * @param $start
  311. * @param $end
  312. * @param $type
  313. * @return float|int
  314. */
  315. function calculate_leave($start,$end,$type){
  316. $starts = explode(' ',$start);
  317. $ends = explode(' ',$end);
  318. $start = date('Ymd',strtotime($starts[0]));
  319. $stxt = $starts[1];
  320. $end = date('Ymd',strtotime($ends[0]));
  321. $etxt = $ends[1];
  322. if($start > $end){
  323. return 0;
  324. }
  325. $bxday = \think\Db::name('holiday')
  326. ->where('holiday',0)
  327. ->where('day','>=',date('Y-m-d',strtotime($starts[0])))
  328. ->where('day','<=',date('Y-m-d',strtotime($ends[0])))
  329. ->column('day');
  330. $bxday = $bxday?$bxday:[];
  331. $holiday = \think\Db::name('holiday')
  332. ->where('holiday',1)
  333. ->where('day','>=',date('Y-m-d',strtotime($starts[0])))
  334. ->where('day','<=',date('Y-m-d',strtotime($ends[0])))
  335. ->column('day');
  336. $holiday = $holiday?$holiday:[];
  337. $days = 0;
  338. $cday = (strtotime($end) - strtotime($start))/86400 + 1;
  339. for ($i=1;$i<=$cday;$i++){
  340. if($type == 1){ // 减去节假日
  341. $cur = strtotime($start) + ($i-1)*86400;
  342. $w = date('w',$cur);
  343. $itxt = date('Y-m-d',$cur);
  344. if(($w == 6 || $w == 0) && in_array($itxt,$bxday)){ // 检查是否是补休日
  345. if($i == 1 && $stxt == '下午'){ // 开始日期
  346. $days += 0.5;
  347. }else if($i == $cday && $etxt == '上午'){
  348. $days += 0.5;
  349. }else{
  350. $days++;
  351. }
  352. } else if($w >0 && $w < 6 && !in_array($itxt,$holiday)){
  353. if($i == 1&&$stxt == '下午'){ // 开始日期
  354. $days += 0.5;
  355. } else if($i == $cday && $etxt == '上午'){
  356. $days += 0.5;
  357. }else{
  358. $days++;
  359. }
  360. }
  361. } else { // 不减节假日
  362. $days++;
  363. }
  364. }
  365. return $days;
  366. }
  367. /**
  368. * 计算社保比例金额
  369. * @param $money
  370. * @param $bl
  371. * @param $bl_type
  372. * @param $bl_extra
  373. * @param $free_bl
  374. * @return false|float
  375. */
  376. function calculate_money($money,$bl,$bl_type,$bl_extra,$free_bl){
  377. $gjjp = $money*$bl;
  378. if($bl_extra > 0){
  379. if($bl_type == 1){ // 比例
  380. $gjjp += $money*$bl_extra;
  381. } else { // 整数
  382. $gjjp += $bl_extra;
  383. }
  384. }
  385. $gjjp = $gjjp*(1 - $free_bl);
  386. return round($gjjp,2);
  387. }
  388. /**
  389. * 延迟任务
  390. * @param $delay 延迟时间(s)
  391. * @param $data 数据
  392. * @param int $type 0=推送 1=短信
  393. * @return bool true=成功
  394. */
  395. function queue_later($delay,$data,$type = 0){
  396. $connector = strtolower(config('queue.connector'));
  397. try{
  398. if($type == 0){ //取消订单
  399. $job = "app\queue\OrderJob@cancel";
  400. $queue = "cancel";
  401. }else if($type == 1){ //处理拼团单
  402. $job = "app\queue\OrderJob@group";
  403. $queue = "group";
  404. }else{
  405. return false;
  406. }
  407. if($connector == 'redis'){
  408. \think\Queue::later($delay, $job, $data, $queue);
  409. return true;
  410. }else{
  411. $res = \think\Queue::later($delay, $job, $data, $queue);
  412. return $res?true:false;
  413. }
  414. }catch (Exception $e){
  415. trace($e->getMessage());
  416. }
  417. return false;
  418. }
  419. /**
  420. * 推送队列任务
  421. * @param string $data 业务数据
  422. * @param int $type 0=推送 1=短信
  423. * @param int $delay 延迟时间(s)
  424. * @return bool true=成功
  425. */
  426. function queue_push($data,$type = 0,$delay = 0){
  427. try{
  428. if($type == 0){ //推送
  429. $job = "app\queue\Jobs@jpush";
  430. $queue = "jpush";
  431. }else if($type == 1){ //短信
  432. $job = "app\queue\Jobs@qxsms";
  433. $queue = "qxsms";
  434. }else if($type == 3){ //自动派单
  435. $job = "app\queue\Jobs@autoSend";
  436. $queue = "autoSend";
  437. }else{
  438. return false;
  439. }
  440. if($delay > 0){
  441. \think\Queue::later($delay, $job, $data, $queue);
  442. }else{
  443. \think\Queue::push($job, $data,$queue);
  444. }
  445. return true;
  446. }catch (Exception $e){
  447. trace('队列添加失败:'.$e->getMessage());
  448. return false;
  449. }
  450. }
  451. /**
  452. * 验证短信发送类
  453. * @param $mobile 手机号
  454. * @return bool
  455. */
  456. function send_verify_sms($mobile){
  457. \think\Db::startTrans();
  458. try{
  459. $curTime = time();
  460. $endTime = $curTime + 10*60; //有效期10分钟
  461. $code = mt_rand(100000,999999);
  462. $data = array(
  463. 'mobile' => $mobile,
  464. 'code' => $code,
  465. 'status' => 0,
  466. 'create_yyyymmdd' => date('Ymd',$curTime),
  467. 'create_time' => date('Y-m-d H:i:s',$curTime),
  468. 'end_time' => date('Y-m-d H:i:s',$endTime)
  469. );
  470. $ret = \think\Db::name('sms_record')->insertGetId($data);
  471. if (!$ret) {
  472. exception('短信记录失败');
  473. }
  474. $content = \app\common\util\AppMsg::getSmsMsg(\app\common\util\AppMsg::SMS_VERIFY,['code'=>$code]);
  475. $json = [
  476. 'orgId' => 0,
  477. 'mobiles' => [$mobile],
  478. 'msg' => $content,
  479. 'fromId' => 0,
  480. 'type' => 1
  481. ];
  482. $ret = queue_push(json_encode($json),1);
  483. if(!$ret){
  484. exception('添加短信队列失败');
  485. }
  486. \think\Db::commit();
  487. return true;
  488. }catch (Exception $e){
  489. trace('短信发送失败:'.$e->getMessage());
  490. trace('短信发送号码:'.$mobile);
  491. \think\Db::rollback();
  492. return false;
  493. }
  494. }
  495. /**
  496. * 验证短信验证码
  497. * @param $mobile 手机号
  498. * @param $code 验证码
  499. * @return bool
  500. */
  501. function verify_sms($mobile,$code){
  502. if(!$code){
  503. return false;
  504. }
  505. $curTime = date('Y-m-d H:i:s');
  506. $info = \think\Db::name('sms_record')
  507. ->where('code',$code)
  508. ->where('mobile',$mobile)
  509. ->where('status',0)
  510. ->where('end_time','>=',$curTime)
  511. ->find();
  512. if(!$info){
  513. return false;
  514. }
  515. \think\Db::name('sms_record')->where('id',$info['id'])->setField('status',1);
  516. return true;
  517. }
  518. /**
  519. * 营销短信发送
  520. * @param array $mobiles 手机号
  521. * @param string $msg 内容
  522. * @return bool
  523. */
  524. function send_sms($mobiles,$msg='',$orgId=0,$fromId=0){
  525. if(!$mobiles){
  526. return true;
  527. }
  528. try{
  529. $json = [
  530. 'orgId' => $orgId,
  531. 'mobiles' => $mobiles,
  532. 'msg' => $msg,
  533. 'fromId' => $fromId,
  534. 'type' => 2
  535. ];
  536. $ret = queue_push(json_encode($json),1);
  537. if(!$ret){
  538. exception('添加短信队列失败');
  539. }
  540. return true;
  541. }catch (Exception $e){
  542. trace('短信添加失败:'.$e->getMessage());
  543. trace('短信添加号码:'.implode(',',$mobiles));
  544. \think\Db::rollback();
  545. return false;
  546. }
  547. }
  548. /**
  549. * 极光推送
  550. * @param array $userids
  551. * @param string $msg
  552. * @param array $extras
  553. */
  554. function send_jpush($userids,$type,$msg='',$extras=array()){
  555. if(!$userids){
  556. return true;
  557. }
  558. try {
  559. // {"users":[1,2,3],"type":1,"msg":"有新订单需要你的处理","extra"=>[]}
  560. $json = [
  561. 'users' => $userids,
  562. 'type' => $type,
  563. 'msg' => $msg,
  564. 'extra' => $extras
  565. ];
  566. $ret = queue_push(json_encode($json),0);
  567. if(!$ret){
  568. exception('添加推送队列失败');
  569. }
  570. return true;
  571. } catch (Exception $e) {
  572. trace('push-error:'.$e->getMessage().':'.json_encode($json));
  573. return false;
  574. }
  575. }
  576. /**
  577. * 计算年龄/工龄
  578. * @param $date
  579. * @return false|mixed|string
  580. */
  581. function calculate_age($date){
  582. list($year,$month,$day) = explode("-",$date);
  583. $year_diff = date("Y") - $year;
  584. $month_diff = date("m") - $month;
  585. $day_diff = date("d") - $day;
  586. if ($day_diff < 0 || $month_diff < 0)
  587. $year_diff--;
  588. return $year_diff;
  589. }
  590. // 过滤以逗号分隔的内容,去掉空项
  591. function check_exp_imp($data){
  592. if(!$data){
  593. return '';
  594. }
  595. $vals = explode(',',$data);
  596. $nr = [];
  597. foreach ($vals as $v){
  598. if($v && !in_array($v,$nr)){
  599. $nr[] = $v;
  600. }
  601. }
  602. return empty($nr)?'':implode(',',$nr);
  603. }
  604. /**
  605. * [check_wechat 校验微信号格式]
  606. */
  607. function check_wechat($wechat){
  608. return preg_match('/^[_a-zA-Z0-9]{5,19}+$/isu',$wechat);
  609. }
  610. /**
  611. * [check_link 校验url格式]
  612. */
  613. function check_url($link){
  614. return preg_match("/http[s]?:\/\/[\w.]+[\w\/]*[\w.]*\??[\w=&\+\%]*/is", $link);
  615. }
  616. /**
  617. * 数据签名认证
  618. * @param array $data 被认证的数据
  619. * @return string 签名
  620. */
  621. function data_auth_sign($data) {
  622. //数据类型检测
  623. if(!is_array($data)){
  624. $data = (array)$data;
  625. }
  626. ksort($data); //排序
  627. $code = http_build_query($data); //url编码并生成query字符串
  628. $sign = sha1($code); //生成签名
  629. return $sign;
  630. }
  631. function education($key){
  632. $arr = [
  633. '暂无',
  634. '初中及以下',
  635. '高中',
  636. '中专/中技',
  637. '大专',
  638. '本科',
  639. '硕士',
  640. '博士',
  641. ];
  642. return isset($arr[$key])?$arr[$key]:'暂无';
  643. }
  644. function politics($val){
  645. $arr = [
  646. '暂无',
  647. '中共党员',
  648. '中共预备党员',
  649. '共青团员',
  650. '民革会员',
  651. '民盟盟员',
  652. '民建会员',
  653. '民进会员',
  654. '农工党党员',
  655. '致公党党员',
  656. '九三学社社员',
  657. '台盟盟员',
  658. '无党派人士',
  659. '群众',
  660. ];
  661. return isset($arr[$val])?$arr[$val]:'暂无';
  662. }
  663. /**
  664. * 加载小部件
  665. * @param $template 模板
  666. * @param $data 参数
  667. * @return string
  668. */
  669. function widget_view($template,$data){
  670. return \think\facade\View::fetch($template,$data);
  671. }
  672. /**
  673. * 加载小部件
  674. * @param $template 模板
  675. * @param $data 参数
  676. * @return string
  677. */
  678. function widget($template,$data){
  679. return \think\facade\View::fetch($template,$data);
  680. }
  681. /**
  682. * 创建token
  683. * @param $userid
  684. * @return string
  685. */
  686. function create_token($userid){
  687. //十进制转八进制
  688. $token = decoct($userid).'9'.decoct(intval(time()));
  689. return $token;
  690. }
  691. /**
  692. * select返回的数组进行整数映射转换
  693. *
  694. * @param array $map 映射关系二维数组 array(
  695. * '字段名1'=>array(映射关系数组),
  696. * '字段名2'=>array(映射关系数组),
  697. * ......
  698. * )
  699. * @author 朱亚杰 <zhuyajie@topthink.net>
  700. * @return array
  701. *
  702. * array(
  703. * array('id'=>1,'title'=>'标题','status'=>'1','status_text'=>'正常')
  704. * ....
  705. * )
  706. *
  707. */
  708. function int_to_string(&$data,$map=array('status'=>array(1=>'正常',0=>'禁用'))) {
  709. if($data === false || $data === null ){
  710. return $data;
  711. }
  712. $data = (array)$data;
  713. foreach ($data as $key => $row){
  714. foreach ($map as $col=>$pair){
  715. if(isset($row[$col]) && isset($pair[$row[$col]])){
  716. $data[$key][$col.'_text'] = $pair[$row[$col]];
  717. }
  718. }
  719. }
  720. return $data;
  721. }
  722. //生成guid
  723. function new_guid()
  724. {
  725. if (function_exists('com_create_guid')) {
  726. return com_create_guid();
  727. } else {
  728. mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
  729. $charid = strtoupper(md5(uniqid(rand(), true)));
  730. $hyphen = chr(45);// "-"
  731. $uuid = chr(123)// "{"
  732. .substr($charid, 0, 8).$hyphen
  733. .substr($charid, 8, 4).$hyphen
  734. .substr($charid, 12, 4).$hyphen
  735. .substr($charid, 16, 4).$hyphen
  736. .substr($charid, 20, 12)
  737. .chr(125);// "}"
  738. return $uuid;
  739. }
  740. }
  741. /**
  742. * 获取二维码加密串(urlencode是避免生成的字符被转码)
  743. * @param $type 二维码类型
  744. * @param $id 二维码ID
  745. * @return string 加密后的字符串
  746. */
  747. function get_qrcode_str($type,$id){
  748. $data = array(
  749. 'type' => (string)$type,
  750. 'id' => (int)$id,
  751. 'ucode' => config('app.ucode') //正式使用后不可修改
  752. );
  753. $strs = aes_encrypt(json_encode($data),config('app.encryption_key'));
  754. return str_ireplace('+','_',$strs);
  755. }
  756. /**
  757. * 获取二维码加密串(urlencode是避免生成的字符被转码)
  758. * @param $str 内容
  759. * @return array 解密后的数组
  760. */
  761. function get_qrcode_arr($str){
  762. $str = str_ireplace('_','+',$str);
  763. $data = json_decode(aes_decrypt($str, config('app.encryption_key')),true);
  764. return $data ? $data : array();
  765. }
  766. //本周日期
  767. function get_week_date(){
  768. $week = date('W');
  769. $time = strtotime(date('Y-m-d'));
  770. $arr = array();
  771. for ($i=6; $i>=0; $i--){
  772. $t = $time - $i*24*60*60;
  773. $w = date('W',$t);
  774. if($w == $week) {
  775. $arr[] = date('Ymd', $t);
  776. }
  777. }
  778. return $arr;
  779. }
  780. function getTime(){
  781. return date('Y-m-d H:i:s');
  782. }
  783. function getSite(){
  784. // $http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';
  785. // return $http_type.$_SERVER['HTTP_HOST'];
  786. return config("app.app_host");
  787. }
  788. /**
  789. * 检查字符串是否为空
  790. * @param $str
  791. * @return bool
  792. */
  793. function check_val_empty($str){
  794. if (empty($str)) {
  795. return false;
  796. }
  797. return true;
  798. }
  799. /**
  800. * 对查询结果集进行排序
  801. * @access public
  802. * @param array $list 查询结果
  803. * @param string $field 排序的字段名
  804. * @param array $sortby 排序类型
  805. * asc正向排序 desc逆向排序 nat自然排序
  806. * @return array
  807. */
  808. function list_sort_by($list,$field, $sortby='asc') {
  809. if(is_array($list)){
  810. $refer = $resultSet = array();
  811. foreach ($list as $i => $data)
  812. $refer[$i] = &$data[$field];
  813. switch ($sortby) {
  814. case 'asc': // 正向排序
  815. asort($refer);
  816. break;
  817. case 'desc':// 逆向排序
  818. arsort($refer);
  819. break;
  820. case 'nat': // 自然排序
  821. natcasesort($refer);
  822. break;
  823. }
  824. foreach ( $refer as $key=> $val)
  825. $resultSet[] = &$list[$key];
  826. return $resultSet;
  827. }
  828. return false;
  829. }
  830. // 格式化以符号分隔的字符串,去空值
  831. function format_str($strs,$glup = ','){
  832. if(!$strs){
  833. return '';
  834. }
  835. $arr = explode($glup,$strs);
  836. $news = [];
  837. foreach ($arr as $k=>$v){
  838. if($v){
  839. $news[] = $v;
  840. }
  841. }
  842. return !empty($news)?implode($glup,$news):'';
  843. }
  844. //判断是否是二级调度 1是0否
  845. function check_two_dispatch($userId){
  846. $is = 0;
  847. $roles = \think\Db::name('user_roles')
  848. ->alias('a')
  849. ->join('roles b','a.roles_id=b.id')
  850. ->where('a.user_id',$userId)
  851. ->field('b.level,b.parent_id')
  852. ->find();
  853. if($roles && $roles['level']==2 && $roles['parent_id']==9){
  854. $is = 1;
  855. }
  856. return $is;
  857. }
  858. //二级调度开关
  859. function two_dispatch_off($orgId){
  860. $res = (new \app\common\model\Config())
  861. ->getConfig('org_two_dispatch',$orgId);
  862. return $res?(int)$res:0;
  863. }
  864. //判断是否是一级调度 1是0否
  865. function check_is_dispatch($userId){
  866. $is = 0;
  867. $roles = \think\Db::name('user_roles')
  868. ->alias('a')
  869. ->join('roles b','a.roles_id=b.id')
  870. ->where('a.user_id',$userId)
  871. ->field('b.*')
  872. ->find();
  873. if($roles && $roles['parent_id']==9 && $roles['level']==1){
  874. $is = 1;
  875. }
  876. return $is;
  877. }
  878. //获取调度权限
  879. function get_dispatch_auth($userId){
  880. $ids = [];
  881. $roles = \think\Db::name('user_roles')
  882. ->alias('a')
  883. ->join('roles b','a.roles_id=b.id')
  884. ->where('a.user_id',$userId)
  885. ->field('b.*')
  886. ->find();
  887. if($roles){
  888. $ids = $roles['work_type_mode']?explode(',',$roles['work_type_mode']):[];
  889. }
  890. return $ids;
  891. }
  892. //array
  893. function formatArray($array1,$array2,$type=0){
  894. if($type==0){//保留$array1
  895. foreach ($array2 as $k=>$v){
  896. if(!in_array($k,$array1)){
  897. unset($array2[$k]);
  898. }
  899. }
  900. }else{//剔除$array1
  901. foreach ($array2 as $k=>$v){
  902. if(in_array($k,$array1)){
  903. unset($array2[$k]);
  904. }
  905. }
  906. }
  907. return $array2;
  908. }
  909. // 近一个月
  910. function get_one_month(){
  911. $time = strtotime(date('Y-m-d'));
  912. $arr = array();
  913. for ($i=29; $i>=0; $i--){
  914. $arr[] = date('Ymd',$time - $i*24*60*60);
  915. }
  916. return $arr;
  917. }
  918. function get_unique_id2 ($prefix='')
  919. {
  920. return $prefix . date ( 'Ymd' ) .
  921. substr ( implode ( NULL, array_map ( 'ord', str_split ( substr ( uniqid (), 7, 13 ), 1 ) ) ), 0, 6 );
  922. }
  923. function get_config($name){
  924. $info = \think\Db::name('config')->where('name',$name)->find();
  925. if($info){
  926. return config_parse($info['type'], $info['value']);
  927. }
  928. }
  929. function config_parse($type, $value){
  930. switch ($type) {
  931. case 3: //解析数组
  932. $array = preg_split('/[,;\r\n]+/', trim($value, ",;\r\n"));
  933. if(strpos($value,':')){
  934. $value = array();
  935. foreach ($array as $val) {
  936. list($k, $v) = explode(':', $val);
  937. $value[$k] = $v;
  938. }
  939. }else{
  940. $value = $array;
  941. }
  942. break;
  943. }
  944. return $value;
  945. }
  946. function birthday($birthday){
  947. $age = strtotime($birthday);
  948. if($age === false){
  949. return false;
  950. }
  951. list($y1,$m1,$d1) = explode("-",date("Y-m-d",$age));
  952. $now = strtotime("now");
  953. list($y2,$m2,$d2) = explode("-",date("Y-m-d",$now));
  954. $age = $y2 - $y1;
  955. if((int)($m2.$d2) < (int)($m1.$d1))
  956. $age -= 1;
  957. return $age;
  958. }
  959. function diffBetweenTwoDays ($day1, $day2) {
  960. $second1 = strtotime($day1);
  961. $second2 = strtotime($day2);
  962. if ($second1 < $second2) {
  963. $tmp = $second2;
  964. $second2 = $second1;
  965. $second1 = $tmp;
  966. }
  967. return intval(($second1 - $second2) / 86400)+1;
  968. }
  969. function curl_post($url , $data=array()){
  970. $ch = curl_init();
  971. curl_setopt($ch, CURLOPT_URL, $url);
  972. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  973. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  974. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  975. // POST数据
  976. curl_setopt($ch, CURLOPT_POST, 1);
  977. // 把post的变量加上
  978. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  979. $output = curl_exec($ch);
  980. curl_close($ch);
  981. return $output;
  982. }
  983. function nDate($time) {
  984. $tag = 'Y-m-d H:i:s';
  985. $a = substr($time, 0, 10);
  986. $b = substr($time, 10);//毫秒
  987. $date = date($tag, $a - 28800);//.$b
  988. return $date;
  989. }
  990. function getDay($time){
  991. $days =date("t",$time);
  992. for ($i = 0;$i <intval($days);$i++)
  993. {
  994. $day[] =date('Ymd',strtotime("+" .$i." day",strtotime(date("Y-m-01",$time))));
  995. }
  996. return $day;
  997. }
  998. //本年所有月份 开始和结束
  999. function get_month($time){
  1000. $year = $time;
  1001. $yeararr = [];
  1002. for ($i=1; $i <=12 ; $i++) {
  1003. $yeararr[$i] = [
  1004. 'key'=>$year.'年'.$i.'月份',
  1005. 'date'=>date('Ym',strtotime($year.'-'.$i))
  1006. ];
  1007. }
  1008. return $yeararr;
  1009. }
  1010. /**
  1011. * 本月的开始日期
  1012. *
  1013. * @param bool $His 是否展示时分秒 默认true
  1014. *
  1015. * @return false|string
  1016. */
  1017. function beginMonth($His = true)
  1018. {
  1019. $timestamp = mktime(0, 0, 0, date('m'), 1, date('Y'));
  1020. return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
  1021. }
  1022. /**
  1023. * 本月的结束日期
  1024. *
  1025. * @param bool $His 是否展示时分秒 默认true
  1026. *
  1027. * @return false|string
  1028. */
  1029. function endMonth($His = true)
  1030. {
  1031. $timestamp = mktime(23, 59, 59, date('m'), date('t'), date('Y'));
  1032. return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
  1033. }
  1034. /**
  1035. * 几年的开始日期
  1036. *
  1037. * @param bool $His 是否展示时分秒 默认true
  1038. *
  1039. * @return false|string
  1040. */
  1041. function beginYear($His = true)
  1042. {
  1043. $timestamp = mktime(0, 0, 0, 1, 1, date('Y'));
  1044. return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
  1045. }
  1046. /**
  1047. * 本月的结束日期
  1048. *
  1049. * @param bool $His 是否展示时分秒 默认true
  1050. *
  1051. * @return false|string
  1052. */
  1053. function endYear($His = true)
  1054. {
  1055. $timestamp = mktime(23, 59, 59, 12, 31, date('Y'));
  1056. return $His ? date('Y-m-d H:i:s', $timestamp) : date('Y-m-d', $timestamp);
  1057. }
  1058. /**
  1059. * 生成二维码
  1060. * @param $value 二维码内容
  1061. * @param $filepath 保存路径
  1062. * @return bool
  1063. */
  1064. function create_qrcode($value,$filepath)
  1065. {
  1066. include_once env('root_path').'/extend/phpqrcode/phpqrcode.php';
  1067. if (empty($value)) {
  1068. return false;
  1069. }
  1070. $dirfile = dirname($filepath);
  1071. if(!file_exists($dirfile)){
  1072. @mkdir($dirfile,0777);
  1073. }
  1074. //创建一个临时二维码的地址
  1075. $dir = getcwd().DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'qrcodeimg'.DIRECTORY_SEPARATOR;
  1076. if (!file_exists($dir)) {
  1077. @mkdir($dir);
  1078. }
  1079. //临时二维码地址
  1080. $QRprefix = $dir.DIRECTORY_SEPARATOR.substr(md5($value), 8, 16);
  1081. $QRTemp = $QRprefix.'_temp.png';
  1082. //判断本地是否存在临时的先删了
  1083. if (file_exists($QRTemp)) {
  1084. @unlink($QRTemp);
  1085. }
  1086. $errorCorrectionLevel = 'H';//容错级别
  1087. $matrixPointSize = 6;//生成图片大小
  1088. //生成二维码图片
  1089. QRcode::png(
  1090. $value,
  1091. $QRTemp,
  1092. $errorCorrectionLevel,
  1093. $matrixPointSize,
  1094. 2
  1095. );
  1096. $orgId = cur_org_id();
  1097. if($orgId == 17){
  1098. $logo = env('root_path').'/public/hb.png';//准备好的logo图片
  1099. }else{
  1100. $logo = env('root_path').'/public/logo.png';//准备好的logo图片
  1101. }
  1102. if (!empty($logo)) {
  1103. $QRBuffer = add_logo_2qrcode($QRTemp, $logo);
  1104. } else {
  1105. $QRBuffer = imagecreatefromstring(print_72dip_300dip(file_get_contents($QRTemp)));
  1106. }
  1107. //删除临时文件
  1108. if (file_exists($QRTemp)) {
  1109. @unlink($QRTemp);
  1110. }
  1111. imagejpeg($QRBuffer,$filepath,100);
  1112. ImageDestroy($QRBuffer);
  1113. }
  1114. //添加LOGO
  1115. function add_logo_2qrcode($QRTempPath, $logoPath)
  1116. {
  1117. $QRBuffer = imagecreatefromstring(print_72dip_300dip(file_get_contents($QRTempPath)));
  1118. $logo = imagecreatefromstring(print_72dip_300dip(file_get_contents($logoPath)));
  1119. $QR_width = imagesx($QRBuffer);//二维码图片宽度
  1120. $QR_height = imagesy($QRBuffer);//二维码图片高度
  1121. $logo_width = imagesx($logo);//logo图片宽度
  1122. $logo_height = imagesy($logo);//logo图片高度
  1123. $logo_qr_width = $QR_width / 5;
  1124. $scale = $logo_width/$logo_qr_width;
  1125. $logo_qr_height = $logo_height/$scale;
  1126. $from_width = ($QR_width - $logo_qr_width) / 2;
  1127. //重新组合图片并调整大小
  1128. imagecopyresampled(
  1129. $QRBuffer,
  1130. $logo,
  1131. $from_width,
  1132. $from_width,
  1133. 0,
  1134. 0,
  1135. $logo_qr_width,
  1136. $logo_qr_height,
  1137. $logo_width,
  1138. $logo_height
  1139. );
  1140. return $QRBuffer;
  1141. }
  1142. //浏览器默认输出为72DPI,打印要求为300DPI
  1143. function print_72dip_300dip($QRBufferStr)
  1144. {
  1145. //数据块长度为9
  1146. $len = pack("N", 9);
  1147. //数据块类型标志为pHYs
  1148. $sign = pack("A*", "pHYs");
  1149. //X方向和Y方向的分辨率均为300DPI(1像素/英寸=39.37像素/米),单位为米(0为未知,1为米)
  1150. $data = pack("NNC", 300 * 39.37, 300 * 39.37, 0x01);
  1151. //CRC检验码由数据块符号和数据域计算得到
  1152. $checksum = pack("N", crc32($sign . $data));
  1153. $phys = $len . $sign . $data . $checksum;
  1154. $pos = strpos($QRBufferStr, "pHYs");
  1155. if ($pos > 0) {
  1156. //修改pHYs数据块
  1157. $QRBufferStr = substr_replace($QRBufferStr, $phys, $pos - 4, 21);
  1158. } else {
  1159. //IHDR结束位置(PNG头固定长度为8,IHDR固定长度为25)
  1160. $pos = 33;
  1161. //将pHYs数据块插入到IHDR之后
  1162. $QRBufferStr = substr_replace($QRBufferStr, $phys, $pos, 0);
  1163. }
  1164. return $QRBufferStr;
  1165. }
  1166. /**
  1167. * 压缩文件/目录成zip
  1168. * @param $path
  1169. * @param $zip
  1170. */
  1171. function add_file_to_zip($path,$zip){
  1172. $handler=opendir($path); //打开当前文件夹由$path指定。
  1173. while(($filename=readdir($handler))!==false){
  1174. if($filename != "." && $filename != ".."){//文件夹文件名字为'.'和‘..’,不要对他们进行操作
  1175. if(is_dir($path."/".$filename)){// 如果读取的某个对象是文件夹,则递归
  1176. add_file_to_zip($path."/".$filename, $zip);
  1177. }else{ //将文件加入zip对象
  1178. $pp = $path."/".$filename;
  1179. $pps = explode('//',$pp);
  1180. $zip->addFile($pp,$pps[1]);
  1181. }
  1182. }
  1183. }
  1184. @closedir($path);
  1185. }
  1186. /**
  1187. * 清空文件夹及文件夹下的所有文件
  1188. * @param $path "./code/"
  1189. */
  1190. function deldir($path){
  1191. //如果是目录则继续
  1192. if(is_dir($path)){
  1193. //扫描一个文件夹内的所有文件夹和文件并返回数组
  1194. $p = scandir($path);
  1195. foreach($p as $val){
  1196. //排除目录中的.和..
  1197. if($val !="." && $val !=".."){
  1198. //如果是目录则递归子目录,继续操作
  1199. if(is_dir($path.$val)){
  1200. //子目录中操作删除文件夹和文件
  1201. deldir($path.$val.'/');
  1202. //目录清空后删除空文件夹
  1203. @rmdir($path.$val.'/');
  1204. }else{
  1205. //如果是文件直接删除
  1206. @unlink($path.$val);
  1207. }
  1208. }
  1209. }
  1210. @rmdir($path);
  1211. }
  1212. }
  1213. /*
  1214. * $userId 用户id
  1215. * $delUrl 删除路径(权限标识)
  1216. * */
  1217. function btnAuth($userId,$delUrl){
  1218. if(is_admin($userId)){
  1219. return true;
  1220. }
  1221. $roles = \think\Db::name('user_roles')
  1222. ->alias('a')
  1223. ->join('roles b','a.roles_id=b.id')
  1224. ->where('a.user_id',$userId)
  1225. ->field('b.*')
  1226. ->find();
  1227. if(!empty($roles)){
  1228. $authS = $roles['auths']?explode(',',$roles['auths']):[];
  1229. if($roles['org_id'] > 0){
  1230. $orgauths = \think\Db::name('org')->where('id',$roles['org_id'])->value('auths');
  1231. $orgauths = $orgauths?explode(',',$orgauths):[];
  1232. $authS = array_intersect($authS,$orgauths);
  1233. }
  1234. $menu = \think\Db::name('menu')
  1235. ->where('url',$delUrl)
  1236. ->where('enable',1)
  1237. ->where('del',0)
  1238. ->find();
  1239. if(!empty($menu) && in_array($menu['id'],$authS)){
  1240. return true;
  1241. }
  1242. }
  1243. return false;
  1244. }
  1245. /**
  1246. * 二维数组按照指定字段进行排序
  1247. * @params array $array 需要排序的数组
  1248. * @params string $field 排序的字段
  1249. * @params string $sort 排序顺序标志 SORT_DESC 降序;SORT_ASC 升序
  1250. */
  1251. function arraySequence($array, $field, $sort = 'SORT_ASC') {
  1252. $arrSort = array();
  1253. foreach ($array as $uniqid =>$row) {
  1254. foreach ($row as $key =>$value) {
  1255. $arrSort[$key][$uniqid] = $value;
  1256. }
  1257. }
  1258. array_multisort($arrSort[$field], constant($sort), $array);
  1259. return $array;
  1260. }
  1261. function getM1($do,$cof){
  1262. $diff = strtotime($do) - strtotime($cof);
  1263. $days = floor(($diff )/ (60*60*24));
  1264. $hours = floor(($diff - $days*60*60*24) / (60*60));
  1265. $minutes = floor(($diff - $days*60*60*24 - $hours*60*60)/ 60);
  1266. $seconds = floor(($diff - $days*60*60*24 - $hours*60*60 - $minutes*60));
  1267. if ($diff < 60) {
  1268. $time_cost = $seconds."秒";
  1269. } else if ($diff >= 60 && $diff < 60*60) {
  1270. $time_cost = $minutes."分钟".$seconds."秒";
  1271. } else if ($diff >= 60*60 && $diff < 60*60*24) {
  1272. $time_cost = $hours."小时".$minutes."分钟".$seconds."秒";
  1273. } else {
  1274. $time_cost = $days."天".$hours."小时".$minutes."分钟".$seconds."秒";
  1275. }
  1276. return $time_cost;
  1277. }
  1278. function getOrgGrabOrder($userId,$orgId){
  1279. $rolesId = \think\Db::name('user_roles')
  1280. ->where('user_id', $userId)
  1281. ->value('roles_id');
  1282. $rolesInfo = \think\Db::name('roles')
  1283. ->where('id', $rolesId)
  1284. ->find();
  1285. if ($rolesInfo['parent_id'] > 0) {
  1286. $rolesId = $rolesInfo['parent_id'];
  1287. }
  1288. $workType = \think\Db::name('work_type_mode')
  1289. ->where('type', 1)
  1290. ->where('roles', 'like', '%' . $rolesId . '%')
  1291. ->column('id');
  1292. $is = 0;
  1293. if(empty($workType)){
  1294. return $is;
  1295. }
  1296. foreach ($workType as $k=>$v){
  1297. $orgGrabOrder = (new Config())->getConfig('org_grab_order'.$v,$orgId);
  1298. if($orgGrabOrder && $orgGrabOrder>0){
  1299. $is = 1;
  1300. }
  1301. }
  1302. return $is;
  1303. }
  1304. //获取近12个月 0=包含本月 1=不包含本月
  1305. function monthlater($type=0){
  1306. $str = array();
  1307. for($i=0;$i<12;$i++){
  1308. if($type == 0){
  1309. $str[$i] =date('Y-m',strtotime('-'.$i.'month'));//包含本月
  1310. }else{
  1311. $str[$i] =date('Y-m',strtotime('-1month-'.$i.'month'));//不包含本月
  1312. }
  1313. }
  1314. sort($str);
  1315. return $str;
  1316. }
  1317. function get_sort_user($orgId,$work=-1,$type_id=-1){
  1318. $rolesId = \think\Db::name('roles')
  1319. ->where('parent_id',7)
  1320. ->where('org_id',$orgId)
  1321. ->where('del',0)
  1322. ->column('id');
  1323. $userRolesId = \think\Db::name('user_roles')
  1324. ->where('roles_id','in',$rolesId)
  1325. ->column('user_id');
  1326. $map[] = ['u.id','in',$userRolesId];
  1327. $map[] = ['u.del','=',0];
  1328. $map[] = ['u.type','=',0];
  1329. $map[] = ['u.enable','=',1];
  1330. $map[] = ['u.enable_sorts','=',1];
  1331. $map[] = ['uo.org_id','=',$orgId];
  1332. if($work >0){
  1333. $map[] = ['u.work','=',$work];
  1334. }
  1335. if($type_id >0){
  1336. $map[] = ['u.type_id','=',$type_id];
  1337. }
  1338. $map= empty($map) ? true: $map;
  1339. $lists = \think\Db::name('user')
  1340. ->alias('u')
  1341. ->join('user_org uo','u.id=uo.user_id')
  1342. ->where($map)
  1343. ->field('u.id,uo.org_id')
  1344. ->order(['u.sorts'=>'desc','u.id'=>'asc'])
  1345. ->column('u.id');
  1346. return $lists;
  1347. }
  1348. function get_sort_user_list($orgId,$work=-1){
  1349. $rolesId = \think\Db::name('roles')
  1350. ->where('parent_id',7)
  1351. ->where('org_id',$orgId)
  1352. ->where('del',0)
  1353. ->column('id');
  1354. $userRolesId = \think\Db::name('user_roles')
  1355. ->where('roles_id','in',$rolesId)
  1356. ->column('user_id');
  1357. $map[] = ['u.id','in',$userRolesId];
  1358. $map[] = ['u.del','=',0];
  1359. $map[] = ['u.type','=',0];
  1360. $map[] = ['u.enable','=',1];
  1361. $map[] = ['u.enable_sorts','=',1];
  1362. $map[] = ['uo.org_id','=',$orgId];
  1363. if($work >0){
  1364. $map[] = ['u.work','=',$work];
  1365. }
  1366. $map= empty($map) ? true: $map;
  1367. $lists = \think\Db::name('user')
  1368. ->alias('u')
  1369. ->join('user_org uo','u.id=uo.user_id')
  1370. ->where($map)
  1371. ->field('u.id,uo.org_id,u.sorts')
  1372. ->order(['u.sorts'=>'desc','u.id'=>'asc'])
  1373. ->select();
  1374. return $lists;
  1375. }
  1376. function getDateFromRange($startdate, $enddate){
  1377. $stimestamp = strtotime($startdate);
  1378. $etimestamp = strtotime($enddate);
  1379. // 计算日期段内有多少天
  1380. $days = ($etimestamp-$stimestamp)/86400+1;
  1381. // 保存每天日期
  1382. $date = array();
  1383. for($i=0; $i<$days; $i++){
  1384. $date[] = date('Y-m-d', $stimestamp+(86400*$i));
  1385. }
  1386. return $date;
  1387. }
  1388. /**
  1389. * 加密cookie
  1390. * @param $name
  1391. * @param $val
  1392. * @param $expire
  1393. */
  1394. function encodecookie($name,$val,$expire=100*365*24*60*60){
  1395. cookie($name,think_encrypt($val),$expire);
  1396. }
  1397. /**
  1398. * 解密cookie
  1399. * @param $name
  1400. */
  1401. function decodecookie($name){
  1402. return think_decrypt(cookie($name));
  1403. }
  1404. /**
  1405. * 获取点餐微信公众号配置
  1406. * @param $orgId 组织
  1407. * @return array|bool false=该组织未配置微信账号
  1408. */
  1409. function get_pay_wechat($orgId){
  1410. $wechat = \think\Db::name('dinner_wechat')->where('org_id',$orgId)->order('id','desc')->find();
  1411. if(!$wechat){
  1412. return [];
  1413. }
  1414. $option = [
  1415. 'user_type' => '3'.$wechat['id'],
  1416. 'app_id' => trim($wechat['app_id']),
  1417. 'secret' => trim($wechat['secret']),
  1418. 'mch_id' => trim($wechat['mch_id']), // 商户号
  1419. 'key' => trim($wechat['key']), // API 密钥
  1420. // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
  1421. 'cert_path' => env('root_path').'public'.$wechat['cert_path'],
  1422. 'key_path' => env('root_path').'public'.$wechat['key_path'],
  1423. // 下面为可选项
  1424. // 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
  1425. 'response_type' => 'array',
  1426. 'log' => [
  1427. 'level' => 'error',
  1428. 'file' => env('runtime_path').'/log/wechat.log',
  1429. ],
  1430. ];
  1431. return $option;
  1432. }
  1433. /**
  1434. * 获取某周的周一和周末日期
  1435. * @param int $index //0则代表本周 1则代表下一周
  1436. * @return array
  1437. */
  1438. function get_week_days($index = 0,$format="Y-m-d"){ //0则代表本周
  1439. $week = date('w') == 0 ? 7 : date('w');
  1440. $start = strtotime('today ' . (- ($week - 1) + (7 * $index)) . 'day');
  1441. $end = strtotime('today ' . ((8 - $week) + (7 * $index)) . 'day -1second');
  1442. return [date($format,$start), date($format,$end)];
  1443. }
  1444. /**
  1445. * 获取某天是星期几
  1446. * @param $day 例如:2023-03-30
  1447. * @return string
  1448. */
  1449. function get_week_txt($day){
  1450. $da = date("w",strtotime($day));
  1451. if( $da == "1" ){
  1452. return '周一';
  1453. }else if( $da == "2" ){
  1454. return '周二';
  1455. }else if( $da == "3" ){
  1456. return '周三';
  1457. }else if( $da == "4" ){
  1458. return '周四';
  1459. }else if( $da == "5" ){
  1460. return '周五';
  1461. }else if( $da == "6" ){
  1462. return '周六';
  1463. }else if( $da == "0" ){
  1464. return '周日';
  1465. }
  1466. return '';
  1467. }
  1468. /**
  1469. * 秒数格式化
  1470. * @param $diff
  1471. * @return string
  1472. */
  1473. function second_to_str($diff){
  1474. if($diff <= 0){
  1475. return '0秒';
  1476. }
  1477. $days = floor(($diff )/ (60*60*24));
  1478. $hours = floor(($diff - $days*60*60*24) / (60*60));
  1479. $minutes = floor(($diff - $days*60*60*24 - $hours*60*60)/ 60);
  1480. $seconds = floor(($diff - $days*60*60*24 - $hours*60*60 - $minutes*60));
  1481. if ($diff < 60) {
  1482. $time_cost = $seconds."秒";
  1483. } else if ($diff >= 60 && $diff < 60*60) {
  1484. $time_cost = $minutes."分钟".$seconds."秒";
  1485. } else if ($diff >= 60*60 && $diff < 60*60*24) {
  1486. $time_cost = $hours."小时".$minutes."分钟".$seconds."秒";
  1487. } else {
  1488. $time_cost = $days."天".$hours."小时".$minutes."分钟".$seconds."秒";
  1489. }
  1490. return $time_cost;
  1491. }
  1492. //字符串换行;
  1493. function force_black_string_ex($str, $num){
  1494. $str_length = strlen($str);
  1495. $strNum = $str_length/$num>0 ? ($str_length/$num) : ($str_length/$num)+1;
  1496. $resultStr = '';
  1497. for($i=0; $i<$strNum; $i++){
  1498. $resultStr .= '<br>'.mb_substr($str, $i*$num,$num);
  1499. }
  1500. $resultStr = mb_substr($resultStr, 4);
  1501. return $resultStr;
  1502. }
  1503. //根据分页截取数组
  1504. function array_page_list($list=[],$page=1,$size=10){
  1505. $offset = ($page - 1) * $size;
  1506. $arr = array_slice($list,$offset,$size);
  1507. return $arr;
  1508. }
  1509. //二维数组去重去空
  1510. function array_remove_empty($array, $keys_to_check = []) {
  1511. if (!is_array($array)) {
  1512. return [];
  1513. }
  1514. if(!$array){
  1515. return [];
  1516. }
  1517. $filtered_array = [];
  1518. foreach ($array as $key => $value) {
  1519. if (!is_array($value)) {
  1520. if (!empty($value) || (is_numeric($value) && $value !== 0)) {
  1521. $filtered_array[$key] = $value;
  1522. }
  1523. } else {
  1524. $filtered_array[$key] = array_remove_empty($value, $keys_to_check);
  1525. }
  1526. }
  1527. return $filtered_array;
  1528. }
  1529. //使用htmlpurifier防范xss攻击
  1530. function remove_xss($str){
  1531. $cfg = HTMLPurifier_Config::createDefault();
  1532. $cfg->set('Core.Encoding','UTF-8');
  1533. $cfg->set('HTML.Allowed','div,b,strong,p[style],i,em,a[href|title],ul,ol,li,br,span[style],img[width|height|alt|src]');
  1534. $cfg->set('CSS.AllowedProperties','font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align');
  1535. $cfg->set('HTML.TargetBlank',TRUE);
  1536. // $cfg->set('Core.RemoveJavaScript', true);
  1537. $obj = new HTMLPurifier($cfg);
  1538. return $obj->purify($str);
  1539. }