functions.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. <?php
  2. use App\Facades\Servers\Logs\Log;
  3. use Illuminate\Support\Facades\DB;
  4. use Intervention\Image\Facades\Image;
  5. /**
  6. * 响应请求
  7. * @param mixed $data 数据
  8. * @param string $code 状态码
  9. * @param mixed $log 是否记录日志
  10. *
  11. * */
  12. function json_send($data,$code=200){
  13. // 日志名称
  14. $name = empty($data['code']) ? 'unknown' : $data['code'];
  15. // 获取提示消息
  16. $msg = empty($data['msg']) ? '' : $data['msg'];
  17. // 如果提示数据不是成功或者是local
  18. if( ($name != 'success' && $name != 'retry' ) || config('app.env') == 'local' ) {
  19. // 消息key
  20. $msgKey = 'message.'.$msg;
  21. // 提示信息本地化
  22. $trans = trans($msgKey);
  23. // 如果没有找到对应的提示,使用原提示信息
  24. $data['msg'] = ( $trans == $msgKey ) ? $msg : $trans;
  25. // 消息
  26. $msg = request()->ip().' ' .request()->method().' '. request()->getPathInfo().' '.$msg;
  27. // 记录内容
  28. $content = ['param'=>request()->all(),'return'=>$data,'user_agent'=>request()->header('user-agent')];
  29. // 记录日志
  30. Log::info($name,$msg,$content,['filename'=>str_ireplace('/','_',trim(request()->getPathInfo(),'/'))]);
  31. }
  32. // 默认返回数据
  33. $data['data'] = isset($data['data']) ? $data['data'] : '';
  34. // 返回数据
  35. return response()->json($data,$code,[],JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
  36. }
  37. /**
  38. * 雪花算法生成分布式ID
  39. *
  40. * @param int $dataCenterId 数据中心ID 0-31
  41. * @param int $machineId 任务进程ID 0-31
  42. *
  43. * @return string 分布式ID
  44. * */
  45. function make_snow_flake($dataCenterID=0,$machineId=0){
  46. // 获取redis配置
  47. $redis = config('database.redis.default');
  48. // 主机地址
  49. $config['host'] = empty($redis['host']) ? '127.0.0.1' : $redis['host'];
  50. // 端口
  51. $config['port'] = empty($redis['port']) ? 6379 : $redis['port'];
  52. // 密码
  53. if( !empty($redis['password']) ) $config['auth'] = $redis['password'];
  54. // 数据库
  55. if( !empty($redis['database']) ) $config['dbIndex'] = $redis['database'];
  56. // 实例化
  57. $IdWorker = \wantp\Snowflake\IdWorker::getIns($dataCenterID,$machineId);
  58. // 生成
  59. return $IdWorker->setRedisCountServer($config)->id();
  60. }
  61. /**
  62. * 终端设备系统
  63. *
  64. * @param string $agent HTTP_USER_AGENT数据
  65. *
  66. * */
  67. function get_agent_system($agent=''){
  68. //HTTP_USER_AGENT数据
  69. $agent = $agent ? $agent : request()->header('user-agent');
  70. //iOS
  71. if( stripos($agent, 'iphone') || stripos($agent, 'ipad') ) return 'iOS';
  72. //iOS
  73. if( stripos($agent, 'macintosh') ) return 'MacOS';
  74. //安卓
  75. if( stripos($agent, 'android') ) return 'Android';
  76. //安卓
  77. if( stripos($agent, 'okhttp') ) return 'Android';
  78. //Windows
  79. if( stripos($agent, 'win') ) return 'Windows';
  80. //Linux
  81. if( stripos($agent, 'linux') ) return 'Linux';
  82. //Unix
  83. if( stripos($agent, 'unix') ) return 'Unix';
  84. //Other
  85. return 'Other';
  86. }
  87. /**
  88. * 路径兼容输出
  89. *
  90. * @param string $url 文件路径
  91. * @param int|null $width 新图片宽度
  92. * @param int|null $height 新图片高度(如果没有填写高度,把高度等比例缩小)
  93. * @param string $type 文件类型
  94. *
  95. * @author 刘相欣
  96. * */
  97. function path_compat( $url,$witdh=null,$higth=null,$type='') {
  98. // 没有路径的统一返回原数据
  99. if( !$url ) return $type ? $url : request()->root().'/'.ltrim(resize($url,$witdh,$higth),'/');
  100. // 如果是带有http的路径,直接返回
  101. if( stripos('$'.$url, 'http') ) {
  102. // 腾讯云链
  103. if( stripos( $url, 'myqcloud.com') ){
  104. // 开启全球域名全球加速时, 替换COS全球加速域名
  105. if( config('open_accelerate','') ) $url = str_ireplace('.cos.'.config('tencent.cos.region','').'.myqcloud.com','.cos.accelerate.myqcloud.com',$url);
  106. // 如果需要开启CDN,局部开启,全局开启
  107. if( request()->is('api/*') && (request('open_cdn',0) || config('open_cdn',0) ) && config('open_cdn_domain','') ){
  108. // 先把https 换成 http
  109. $url = str_ireplace('https','http',$url);
  110. // 替换域名
  111. $url = str_ireplace(config('tencent.cos.bucket','').'-'.config('tencent.cos.app_id','').'.cos.'.config('tencent.cos.region','').'.myqcloud.com',config('open_cdn_domain',''),$url);
  112. }
  113. }
  114. // 获取扩展信息
  115. $type = strtolower(pathinfo($url, PATHINFO_EXTENSION));
  116. // 如果信息不存在
  117. if( !$type ) return $url;
  118. // 不是图片直接返回路径
  119. if( !in_array($type,['jpg','png','jpeg','gif','bmp']) ) return $url;
  120. // 需要后缀的OSS参数
  121. $param = '';
  122. // 阿里云的OSS
  123. if( stripos( $url, 'aliyuncs.com') ){
  124. // 判断图片的宽高进行缩放处理
  125. if( $witdh && $higth ){
  126. // 宽高都存在时,固定宽高,将延伸出指定w与h的矩形框外的最小图片进行居中裁剪
  127. $param = '?x-oss-process=image/resize,m_fill,limit_0,w_'.$witdh.',h_'.$higth;
  128. }else if($witdh){
  129. $param = '?x-oss-process=image/resize,w_'.$witdh;
  130. }else if($higth){
  131. $param = '?x-oss-process=image/resize,h_'.$higth;
  132. }
  133. }
  134. // 腾讯云的COS
  135. if( stripos( $url, 'myqcloud.com') ){
  136. if( $witdh && $higth ){
  137. // 宽高都存在时,固定宽高,将延伸出指定w与h的矩形框外的最小图片进行居中裁剪
  138. $param = '?imageView2/2/w/'.$witdh.'/h/'.$higth;
  139. }else if($witdh){
  140. $param = '?imageView2/2/w/'.$witdh;
  141. }else if($higth){
  142. $param = '?imageView2/2/h/'.$higth;
  143. }
  144. }
  145. // 路径
  146. return $param ? $url.$param : $url;
  147. }
  148. // 类型
  149. $type = strtolower(pathinfo($url, PATHINFO_EXTENSION));
  150. // 是图片则返回缩略图
  151. if( in_array($type,['jpg','png','jpeg','gif','bmp']) ) return rtrim((config('img_cdn_domain')?config('img_cdn_domain'):request()->root()),'/').'/'.ltrim(resize($url,$witdh,$higth),'/');
  152. // 判断是否存在文件
  153. if( file_exists('uploads/'.$url) ) return request()->root().'/uploads/'.ltrim($url,'/');
  154. // 其他类型文件,统一返回
  155. return request()->root().'/'.ltrim($url,'/');
  156. }
  157. /**
  158. * 自动生成新尺寸 的图片
  159. * @param string $filename 文件名
  160. * @param int $width 新图片宽度
  161. * @param int $height 新图片高度(如果没有填写高度,把高度等比例缩小)
  162. */
  163. function resize( $filename, $width=null, $height=null) {
  164. // 如果不存在图片路径
  165. if( !is_file(DIR_IMAGE.$filename)||empty($filename) ) $filename = config('app.no_pic');
  166. // 如果没有宽高,给原图
  167. if( !$width && !$height ) return 'uploads/'.$filename;
  168. // 调整当前图像的边界到给定的宽和高
  169. $img = Image::make(DIR_IMAGE.$filename)->resizeCanvas($width, $height);
  170. // 获取文件名称
  171. $name = pathinfo($filename,PATHINFO_FILENAME);
  172. // 缓存名
  173. $cacheName = $width ? $name.'_w' .$width : $name;
  174. $cacheName = $height ? $cacheName.'_h' .$height : $cacheName;
  175. // 名称拼接宽高
  176. $filename = str_replace($name,$cacheName,$filename);
  177. // 缓存文件路径
  178. $newFile = 'cache/'.$filename;
  179. // 如果目录不存在,创建目录
  180. if( !is_dir(dirname(DIR_IMAGE.$newFile)) ) mkdir(dirname(DIR_IMAGE.$newFile),0755,true);
  181. // 保存新图
  182. $img->save(DIR_IMAGE.$newFile);
  183. // 返回结果
  184. return 'uploads/'.$newFile;
  185. }
  186. /**
  187. * 新检查用户操作权限
  188. *
  189. * @param int $uid 账号ID
  190. * @param string $module 模块
  191. *
  192. */
  193. function is_super($uid,$module='manager'){
  194. switch ($module){
  195. case 'manager':
  196. $AdminUserModel = new App\Models\Manager\AdminUser();
  197. break;
  198. case 'company':
  199. $AdminUserModel = new App\Models\Manager\AdminUserCompany();
  200. break;
  201. case 'shop':
  202. $AdminUserModel = new App\Models\Manager\AdminUserShop();
  203. break;
  204. }
  205. // 返回结果
  206. $isSuper = $AdminUserModel->query()->where([['uid','=',$uid]])->value('is_super');
  207. // 默认无权限
  208. return $isSuper ? true : false;
  209. }
  210. /**
  211. * 新检查用户操作权限
  212. *
  213. * @param int $uid 账号ID
  214. * @param string $uid 模块
  215. */
  216. function allow_show_phone($uid,$module='manager'){
  217. switch ($module){
  218. case 'manager':
  219. $AuthGroupAccess = new App\Models\Manager\AuthGroupAccess();
  220. break;
  221. case 'company':
  222. $AuthGroupAccess = new App\Models\Manager\AuthGroupAccessCompany();
  223. break;
  224. case 'shop':
  225. $AuthGroupAccess = new App\Models\Manager\AuthGroupAccessShop();
  226. break;
  227. }
  228. // 返回结果
  229. return $AuthGroupAccess->showPhoneByUid($uid);
  230. }
  231. /**
  232. * 把返回的数据集转换成Tree
  233. * @param array $list 要转换的数据集
  234. * @param string $pid parent标记字段
  235. * @param string $level level标记字段
  236. * @return array
  237. *
  238. * @author 麦当苗儿 <zuojiazi@vip.qq.com>
  239. *
  240. */
  241. function list_to_tree($list, $pk='id', $pid = 'pid', $child = 'children', $root = 0) {
  242. // 创建Tree
  243. $tree = array();
  244. if(is_array($list)) {
  245. // 创建基于主键的数组引用
  246. $refer = array();
  247. foreach ($list as $key => $data) {
  248. $refer[$data[$pk]] =& $list[$key];
  249. }
  250. foreach ($list as $key => $data) {
  251. // 判断是否存在parent
  252. $parentId = $data[$pid];
  253. if ($root == $parentId) {
  254. $tree[] =& $list[$key];
  255. }else{
  256. if (isset($refer[$parentId])) {
  257. $parent =& $refer[$parentId];
  258. $parent[$child][] =& $list[$key];
  259. }
  260. }
  261. }
  262. }
  263. return $tree;
  264. }
  265. /**
  266. * 格式化字节
  267. * @param int $byte 字节数值
  268. *
  269. * */
  270. function byte_format($byte){
  271. // 如果是GB
  272. if( $byte >= (1024 * 1024 * 1024) ) return round( $byte / (1024 * 1024 * 1024),2 ).' GB';
  273. // 如果是MB
  274. if( $byte >= (1024 * 1024) ) return round( $byte / (1024 * 1024),2 ).' MB';
  275. // 如果是KB
  276. if( $byte >= 1024 ) return round( $byte / (1024),2 ).' KB';
  277. // 如果是字节
  278. return $byte.' B';
  279. }
  280. /**
  281. * 二维数组排序,根据某个字段
  282. * @param array $array 要排序的数组
  283. * @param string $key 要排序的键字段
  284. * @param string $sort 排序类型 SORT_ASC SORT_DESC
  285. * @return array 排序后的数组
  286. */
  287. function array_sort($array, $key, $sort = SORT_DESC) {
  288. // 获取字段数据
  289. $keys = array_column($array,$key);
  290. // 进行排序
  291. array_multisort($keys, $sort, $array);
  292. // 返回结果
  293. return $array;
  294. }
  295. /**
  296. * 二维数组排序,根据某个字段
  297. * @param string $phoneNumber 手机号
  298. */
  299. function hide_phone($phoneNumber) {
  300. return substr_replace($phoneNumber, '****', 3, 4);
  301. }
  302. /**
  303. * 省份去除自治区等后缀
  304. *
  305. * @param string $province 省份
  306. *
  307. */
  308. function province_rtrim($province) {
  309. // 长度2个字的不处理
  310. if( mb_strlen($province) <= 2 ) return $province;
  311. // 省份信息
  312. $province = str_ireplace(['省','回族','维吾尔','壮族','自治区','特别行政区'],'',$province);
  313. // 返回结果
  314. return $province;
  315. }
  316. /**
  317. * 城市去除自治州等后缀
  318. *
  319. *
  320. * @param string $city 地级市单位
  321. *
  322. */
  323. function city_rtrim($city) {
  324. // 长度2个字的不处理
  325. if( mb_strlen($city) <= 2 ) return $city;
  326. // 名称
  327. $result = mb_strrchr($city,'市',true);
  328. // 返回结果
  329. if( $result ) return $result;
  330. // 名称
  331. $result = mb_strrchr($city,'自治州',true);
  332. // 返回结果
  333. if( $result ) return $result;
  334. // 名称
  335. $result = mb_strrchr($city,'盟',true);
  336. // 返回结果
  337. if( $result ) return $result;
  338. // 名称
  339. $result = mb_strrchr($city,'地区‌',true);
  340. // 返回结果
  341. if( $result ) return $result;
  342. // 返回结果
  343. return $city;
  344. }
  345. /**
  346. * 将字符串追加到某个需要切割成数组的字符串数组
  347. *
  348. *
  349. * @param string $dest 目标字符串
  350. * @param string $source 需要追加的字符串
  351. * @param string $sep 目标字符串切割方式
  352. *
  353. */
  354. function push_str_arr($dest,$source,$sep=',') {
  355. // 转数组
  356. $result = $dest ? explode($sep,$dest) : [];
  357. $result[] = $source;
  358. $result = array_values(array_unique($result));
  359. // 返回结果
  360. return $result;
  361. }
  362. /**
  363. * 多行多条数据范围转数组
  364. *
  365. * @param string $scope 范围字符串
  366. *
  367. * @return array 范围数组
  368. */
  369. function scope_to_array($scope){
  370. // 兼容逗号问题
  371. $scope = str_ireplace(',',',',$scope);
  372. $scope = str_ireplace("\r\n",',',$scope);
  373. $scope = str_ireplace("\n",',',$scope);
  374. // 转数组处理
  375. $scope = explode(',',$scope);
  376. // 去重
  377. $scope = array_unique($scope);
  378. // 返回结果
  379. return array_values($scope);
  380. }
  381. ?>