933 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			PHP
		
	
	
			
		
		
	
	
			933 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			PHP
		
	
	
<?php
 | 
						||
// +----------------------------------------------------------------------
 | 
						||
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
 | 
						||
// +----------------------------------------------------------------------
 | 
						||
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
 | 
						||
// +----------------------------------------------------------------------
 | 
						||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 | 
						||
// +----------------------------------------------------------------------
 | 
						||
// | Author: 流年 <liu21st@gmail.com>
 | 
						||
// +----------------------------------------------------------------------
 | 
						||
 | 
						||
use think\Collection;
 | 
						||
use think\db\exception\DbException;
 | 
						||
use think\exception\ClassNotFoundException;
 | 
						||
use think\Model;
 | 
						||
use think\Paginator;
 | 
						||
 | 
						||
// 应用公共文件
 | 
						||
 | 
						||
if (!function_exists('widget')) {
 | 
						||
    /**
 | 
						||
     * 渲染输出Widget
 | 
						||
     * @param string $name Widget名称
 | 
						||
     * @param array $data 传入的参数
 | 
						||
     * @return mixed
 | 
						||
     * milo 2019-05-08 从TP5.1代码中拿来修改的
 | 
						||
     */
 | 
						||
    function widget($name, $data = [])
 | 
						||
    {
 | 
						||
        return action($name, $data, 'widget');
 | 
						||
    }
 | 
						||
}
 | 
						||
if (!function_exists('action')) {
 | 
						||
    /**
 | 
						||
     * 调用模块的操作方法 参数格式 [模块/控制器/]操作
 | 
						||
     * @param string $url 调用地址
 | 
						||
     * @param string|array $vars 调用参数 支持字符串和数组
 | 
						||
     * @param string $layer 要调用的控制层名称
 | 
						||
     * @param bool $appendSuffix 是否添加类名后缀
 | 
						||
     * @return mixed
 | 
						||
     * milo 2019-05-08 从TP5.1代码中拿来修改的
 | 
						||
     */
 | 
						||
    function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
 | 
						||
    {
 | 
						||
        $info = pathinfo($url);
 | 
						||
        $action = $info['basename'];
 | 
						||
        $module = '.' != $info['dirname'] ? $info['dirname'] : request()->controller();
 | 
						||
        $class = controller($module, $layer);
 | 
						||
        if (is_scalar($vars)) {
 | 
						||
            if (strpos($vars, '=')) {
 | 
						||
                parse_str($vars, $vars);
 | 
						||
            } else {
 | 
						||
                $vars = [$vars];
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return app()->invokeMethod([$class, $action . config('route.action_suffix')], $vars);
 | 
						||
    }
 | 
						||
}
 | 
						||
if (!function_exists('controller')) {
 | 
						||
    /**
 | 
						||
     * 实例化(分层)控制器 格式:[模块名/]控制器名
 | 
						||
     * @access public
 | 
						||
     * @param string $name 资源地址
 | 
						||
     * @param string $layer 控制层名称
 | 
						||
     * @param bool $appendSuffix 是否添加类名后缀
 | 
						||
     * @param string $empty 空控制器名称
 | 
						||
     * @return object
 | 
						||
     * @throws ClassNotFoundException
 | 
						||
     *
 | 
						||
     * milo 2019-05-08 从TP5.1代码中拿来修改的
 | 
						||
     */
 | 
						||
    function controller($name, $layer = 'controller', $empty = '')
 | 
						||
    {
 | 
						||
        $class = parseClass($name, $layer);
 | 
						||
        if (class_exists($class)) {
 | 
						||
            return app()->make($class);
 | 
						||
        } elseif ($empty && class_exists($emptyClass = app()->parseClass($layer, $empty))) {
 | 
						||
            return app()->make($emptyClass);
 | 
						||
        }
 | 
						||
 | 
						||
        throw new ClassNotFoundException('class not exists:' . $class, $class);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('parseClass')) {
 | 
						||
    /**
 | 
						||
     * 解析模块和类名
 | 
						||
     * @access protected
 | 
						||
     * @param string $name 资源地址
 | 
						||
     * @param string $layer 验证层名称
 | 
						||
     * @param bool $appendSuffix 是否添加类名后缀
 | 
						||
     * @return array
 | 
						||
     *
 | 
						||
     * milo 2019-05-08 从TP5.1代码中拿来修改的
 | 
						||
     */
 | 
						||
    function parseClass($name, $layer)
 | 
						||
    {
 | 
						||
        if (false !== strpos($name, '\\')) {
 | 
						||
            $class = $name;
 | 
						||
        } else {
 | 
						||
            if (strpos($name, '/')) {
 | 
						||
                $names = explode('/', $name, 2);
 | 
						||
                $name = $names[1];
 | 
						||
            }
 | 
						||
            $class = app()->parseClass($layer, $name);
 | 
						||
        }
 | 
						||
        return $class;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
if (!function_exists('randomStr')) {
 | 
						||
    /**
 | 
						||
     * 获取随机字符串
 | 
						||
     * @param int $type 0:数字(默认);1:全部;2:小写字母;3:大写字母;4:字母;
 | 
						||
     * @param int $len 字符串长度
 | 
						||
     * @return string
 | 
						||
     */
 | 
						||
    function randomStr($type = 0, $len = 5)
 | 
						||
    {
 | 
						||
        $strPol = "0123456789";
 | 
						||
        if ($type == 1) {
 | 
						||
            $strPol = "ABCDEFGHIJKLMOPQRSTUVWYZ0123456789abcdefghijklmopqrstuvwyz";
 | 
						||
        } elseif ($type == 2) {
 | 
						||
            $strPol = "abcdefghijklmopqrstuvwyz";
 | 
						||
        } elseif ($type == 3) {
 | 
						||
            $strPol = "ABCDEFGHIJKLMOPQRSTUVWYZ";
 | 
						||
        } elseif ($type == 4) {
 | 
						||
            $strPol = "ABCDEFGHIJKLMOPQRSTUVWYZabcdefghijklmopqrstuvwyz";
 | 
						||
        }
 | 
						||
        $max = strlen($strPol) - 1;
 | 
						||
        $str = '';
 | 
						||
        for ($i = 0; $i < $len; $i++) {
 | 
						||
            $str .= $strPol[rand(0, $max)];
 | 
						||
        }
 | 
						||
        return $str;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('isMobile')) {
 | 
						||
    //判断访问终端是否为移动端
 | 
						||
    function isMobile()
 | 
						||
    {
 | 
						||
        // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
 | 
						||
        if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
 | 
						||
            return true;
 | 
						||
        }
 | 
						||
        // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
 | 
						||
        if (isset($_SERVER['HTTP_VIA'])) {
 | 
						||
            // 找不到为flase,否则为true
 | 
						||
            return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
 | 
						||
        }
 | 
						||
        // 脑残法,判断手机发送的客户端标志,兼容性有待提高。其中'MicroMessenger'是电脑微信
 | 
						||
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
 | 
						||
            $clientkeywords = [
 | 
						||
                'nokia', 'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp', 'sie-', 'philips',
 | 
						||
                'panasonic', 'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu', 'android', 'netfront',
 | 
						||
                'symbian', 'ucweb', 'windowsce', 'palm', 'operamini', 'operamobi', 'openwave', 'nexusone', 'cldc',
 | 
						||
                'midp', 'wap', 'mobile', 'MicroMessenger'
 | 
						||
            ];
 | 
						||
            // 从HTTP_USER_AGENT中查找手机浏览器的关键字
 | 
						||
            if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
 | 
						||
                return true;
 | 
						||
            }
 | 
						||
        }
 | 
						||
        // 协议法,因为有可能不准确,放到最后判断
 | 
						||
        if (isset ($_SERVER['HTTP_ACCEPT'])) {
 | 
						||
            // 如果只支持wml并且不支持html那一定是移动设备
 | 
						||
            // 如果支持wml和html但是wml在html之前则是移动设备
 | 
						||
            if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'],
 | 
						||
                        'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'],
 | 
						||
                            'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
 | 
						||
                return true;
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return false;
 | 
						||
    }
 | 
						||
}
 | 
						||
//根据栏目获取路径
 | 
						||
if (!function_exists('getUri')) {
 | 
						||
    function getUri($cate)
 | 
						||
    {
 | 
						||
        $url = '';
 | 
						||
        if (!empty($cate)) {
 | 
						||
            if ($cate['is_index']) {
 | 
						||
                $url = '/';
 | 
						||
            } elseif (!empty($cate['url'])) {
 | 
						||
                $url = $cate['url'];
 | 
						||
            } else {
 | 
						||
                $url = url($cate['template'] . '/index', ['category_id' => $cate['id']]);
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return $url;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//根据文件大小转换为文字
 | 
						||
if (!function_exists('sizeToStr')) {
 | 
						||
    function sizeToStr($size)
 | 
						||
    {
 | 
						||
        if (!is_numeric($size) || $size <= 0) {
 | 
						||
            return '';
 | 
						||
        }
 | 
						||
        $size = $size / 1024;
 | 
						||
        if ($size < 1024) {
 | 
						||
            return sprintf("%.2fK", $size);
 | 
						||
        }
 | 
						||
        $size = $size / 1024;
 | 
						||
        if ($size < 1024) {
 | 
						||
            return sprintf("%.2fM", $size);
 | 
						||
        }
 | 
						||
        $size = $size / 1024;
 | 
						||
        return sprintf("%.2fG", $size);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//根据路径获取文件名
 | 
						||
if (!function_exists('getKeyByPath')) {
 | 
						||
    function getKeyByPath($path)
 | 
						||
    {
 | 
						||
        return substr($path, strrpos($path, '/') + 1);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//富文本中提取图片路径
 | 
						||
if (!function_exists('getImageUrlFromText')) {
 | 
						||
    function getImageUrlFromText($content)
 | 
						||
    {
 | 
						||
        preg_match_all('/<img.*?src="(.*?)".*?>/is', $content, $imgs);
 | 
						||
        $data = [];
 | 
						||
        if (!empty($imgs) && !empty($imgs[1])) {
 | 
						||
            foreach ($imgs[1] as $img) {
 | 
						||
                if (substr($img, 0, 4) != 'http') {
 | 
						||
                    $key = getKeyByPath($img);
 | 
						||
                    $data[$key] = $img;
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return $data;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//富文本中提取视频路径
 | 
						||
if (!function_exists('getVideoUrlFromText')) {
 | 
						||
    function getVideoUrlFromText($content)
 | 
						||
    {
 | 
						||
        preg_match_all('/<video.*?src="(.*?)".*?>/is', $content, $videos);
 | 
						||
        $data = [];
 | 
						||
        if (!empty($videos) && !empty($videos[1])) {
 | 
						||
            foreach ($videos[1] as $video) {
 | 
						||
                if (substr($video, 0, 4) != 'http') {
 | 
						||
                    $key = getKeyByPath($video);
 | 
						||
                    $data[$key] = $video;
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return $data;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//获取目录下的所有文件
 | 
						||
if (!function_exists('getAllFilesByPath')) {
 | 
						||
    function getAllFilesByPath($path, $rootPath)
 | 
						||
    {
 | 
						||
        if (is_dir($path) && file_exists($path)) {
 | 
						||
            $items = scandir($path);
 | 
						||
            $files = [];
 | 
						||
            foreach ($items as $item) {
 | 
						||
                if (substr($item, 0, 1) != '.' && strpos($item, '_') == false) {
 | 
						||
                    $itemPath = $path . '/' . $item;
 | 
						||
                    if (is_file($itemPath)) {
 | 
						||
                        $size = filesize($itemPath);
 | 
						||
                        $files[$item] = [
 | 
						||
                            'path' => str_replace($rootPath, '/', $itemPath),
 | 
						||
                            'realPath' => $itemPath,
 | 
						||
                            'size' => $size,
 | 
						||
                            'sizeStr' => sizeToStr($size),
 | 
						||
                            'suffix' => strtolower(substr($item, strrpos($item, '.') + 1))    //后缀
 | 
						||
                        ];
 | 
						||
                    } elseif (is_dir($itemPath)) {
 | 
						||
                        $childFiles = getAllFilesByPath($itemPath, $rootPath);
 | 
						||
                        if (!empty($childFiles)) {
 | 
						||
                            $files = array_merge($files, $childFiles);
 | 
						||
                        } else {
 | 
						||
                            rmdir($itemPath);
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
            return $files;
 | 
						||
        }
 | 
						||
        return [];
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//过滤get输入
 | 
						||
if (!function_exists('getFilter')) {
 | 
						||
    function getFilter($value)
 | 
						||
    {
 | 
						||
        $getFilter = "'|(and|or)\b.+?(>|<|=|in|like)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
 | 
						||
        $forArray = false;
 | 
						||
        if (is_array($value)) {
 | 
						||
            $forFilter = implode($value);
 | 
						||
            $forArray = true;
 | 
						||
        } else {
 | 
						||
            $forFilter = $value;
 | 
						||
        }
 | 
						||
        if (preg_match("/" . $getFilter . "/is", $forFilter) == 1) {
 | 
						||
            $value = $forArray ? [] : '';
 | 
						||
        }
 | 
						||
        return filterExp($value);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//过滤post录入
 | 
						||
if (!function_exists('postFilter')) {
 | 
						||
    function postFilter($value)
 | 
						||
    {
 | 
						||
        $postFilter = "\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
 | 
						||
        $forArray = false;
 | 
						||
        if (is_array($value)) {
 | 
						||
            $forFilter = implode($value);
 | 
						||
            $forArray = true;
 | 
						||
        } else {
 | 
						||
            $forFilter = $value;
 | 
						||
        }
 | 
						||
        if (preg_match("/" . $postFilter . "/is", $forFilter) == 1) {
 | 
						||
            $value = $forArray ? [] : '';
 | 
						||
        }
 | 
						||
        return filterExp($value);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//过滤cookie数据
 | 
						||
if (!function_exists('cookieFilter')) {
 | 
						||
    function cookieFilter($value)
 | 
						||
    {
 | 
						||
        $cookieFilter = "\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)";
 | 
						||
        $forArray = false;
 | 
						||
        if (is_array($value)) {
 | 
						||
            $forFilter = implode($value);
 | 
						||
            $forArray = true;
 | 
						||
        } else {
 | 
						||
            $forFilter = $value;
 | 
						||
        }
 | 
						||
        if (preg_match("/" . $cookieFilter . "/is", $forFilter) == 1) {
 | 
						||
            $value = $forArray ? [] : '';
 | 
						||
        }
 | 
						||
        return filterExp($value);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('filterExp')) {
 | 
						||
    function filterExp($value)
 | 
						||
    {
 | 
						||
        $filter = '/^(\s)+(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT LIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)(\s)+$/i';
 | 
						||
        $forArray = false;
 | 
						||
        if (is_array($value)) {
 | 
						||
            $forFilter = implode($value);
 | 
						||
            $forArray = true;
 | 
						||
        } else {
 | 
						||
            $forFilter = $value;
 | 
						||
        }
 | 
						||
        if (preg_match($filter, $forFilter) == 1) {
 | 
						||
            $value = $forArray ? [] : '';
 | 
						||
        }
 | 
						||
        return $value;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('arrayHtmlFilter')) {
 | 
						||
    function arrayHtmlFilter($arr)
 | 
						||
    {
 | 
						||
        foreach ($arr as $k => $one) {
 | 
						||
            if (is_array($one)) {
 | 
						||
                $arr[$k] = arrayHtmlFilter($one);
 | 
						||
            } else {
 | 
						||
                $one = trim($one);
 | 
						||
                $arr[$k] = strip_tags($one);
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return $arr;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('toCamelString')) {
 | 
						||
    /**
 | 
						||
     * 转驼峰
 | 
						||
     *
 | 
						||
     * @param string $string
 | 
						||
     * @param false $small 默认false 为true首字母小写
 | 
						||
     * @return string
 | 
						||
     */
 | 
						||
    function toCamelString(string $string, bool $small = false): string
 | 
						||
    {
 | 
						||
        //例: xxx_yYy_zzZ 和 xxX-yyy-Zzz
 | 
						||
        //1. 字符串转小写 xxx_yyy_zzz xxx-yyy-zzz
 | 
						||
        //2. -和_转空格 xxx yyy zzz
 | 
						||
        //3. 单词首字母大写 Xxx Yyy Zzz
 | 
						||
        //4. 清除空格 XxxYyyZzz
 | 
						||
        //处理下划线、减号 统统专程大驼峰 如xxx_yyy_zzz xxx-yyy-zzz 均转为 XxxYyyZzz
 | 
						||
        $string = strtolower($string);
 | 
						||
        $string = str_replace('-', ' ', $string);
 | 
						||
        $string = str_replace('_', ' ', $string);
 | 
						||
        $string = str_replace(' ', '', ucwords($string));
 | 
						||
        if ($small) {
 | 
						||
            $string = lcfirst($string);
 | 
						||
        }
 | 
						||
        return $string;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('unCamelize')) {
 | 
						||
    /**
 | 
						||
     * 驼峰命名转特定分隔符[如下划线]命名
 | 
						||
     * @param string $camelCaps
 | 
						||
     * @param string $separator
 | 
						||
     * @return string
 | 
						||
     */
 | 
						||
    function unCamelize(string $camelCaps, string $separator = '-'): string
 | 
						||
    {
 | 
						||
        return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
if (!function_exists('generateRand')) {
 | 
						||
    /**
 | 
						||
     * 生成随机数
 | 
						||
     *
 | 
						||
     * @param int $length 长度
 | 
						||
     * @param string $type 模式 默认mix混合 number纯数字 alpha字母
 | 
						||
     * @return string
 | 
						||
     */
 | 
						||
    function generateRand(int $length = 8, string $type = 'mix'): string
 | 
						||
    {
 | 
						||
        $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
 | 
						||
        $number = '0123456789';
 | 
						||
        $alphabetLen = strlen($alphabet) - 1;
 | 
						||
        $numberLen = 9;
 | 
						||
 | 
						||
        switch ($type) {
 | 
						||
            case 'number':
 | 
						||
                $str = $number;
 | 
						||
                $len = $numberLen;
 | 
						||
                break;
 | 
						||
            case 'alpha':
 | 
						||
                $str = $alphabet;
 | 
						||
                $len = $alphabetLen;
 | 
						||
                break;
 | 
						||
            default:
 | 
						||
                $str = $alphabet . $number;
 | 
						||
                $len = $alphabetLen + $numberLen;
 | 
						||
        }
 | 
						||
 | 
						||
        $randStr = '';
 | 
						||
        $str = str_shuffle($str);
 | 
						||
        for ($i = 0; $i < $length; $i++) {
 | 
						||
            $num = mt_rand(0, $len);
 | 
						||
            $randStr .= $str[$num];
 | 
						||
        }
 | 
						||
        return $randStr;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('generateCode')) {
 | 
						||
    /**
 | 
						||
     * 生成特定编码
 | 
						||
     *
 | 
						||
     * @param string $type 类型 默认mix混合 number纯数字 alpha字母
 | 
						||
     * @param int $len 随机数长度
 | 
						||
     * @return string
 | 
						||
     */
 | 
						||
    function generateCode(string $type = 'number', int $len = 6): string
 | 
						||
    {
 | 
						||
        //#时间戳+微秒+6位随机数
 | 
						||
        $time = microtime(true);
 | 
						||
        $timeStr = str_replace('.', '', $time);
 | 
						||
        return sprintf("%s%s", $timeStr, generateRand($len, $type));
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('checkMobile')) {
 | 
						||
    /**
 | 
						||
     * 检测手机号
 | 
						||
     *
 | 
						||
     * @param string $mobile
 | 
						||
     * @return bool
 | 
						||
     */
 | 
						||
    function checkMobile(string $mobile): bool
 | 
						||
    {
 | 
						||
        if (preg_match("/^1[3456789]{1}\d{9}$/", $mobile)) {
 | 
						||
            return true;
 | 
						||
        } else {
 | 
						||
            return false;
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('arrayKeysFilter')) {
 | 
						||
    /**
 | 
						||
     * 一维数组键名过滤
 | 
						||
     *
 | 
						||
     * @param array $data
 | 
						||
     * @param array $allowKeys
 | 
						||
     * @return array
 | 
						||
     */
 | 
						||
    function arrayKeysFilter(array $data, array $allowKeys): array
 | 
						||
    {
 | 
						||
        $list = [];
 | 
						||
        foreach ($data as $key => $val) {
 | 
						||
            if (in_array($key, $allowKeys)) {
 | 
						||
                $list[$key] = $val;
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return $list;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('multiTwoArrayKeysFilter')) {
 | 
						||
    /**
 | 
						||
     * 二维数组键名过滤
 | 
						||
     *
 | 
						||
     * @param  array  $data
 | 
						||
     * @param  array  $allowKeys 允许的字段
 | 
						||
     * @return array
 | 
						||
     */
 | 
						||
    function multiTwoArrayKeysFilter(array $data, array $allowKeys): array
 | 
						||
    {
 | 
						||
        foreach ($data as $ki => $item) {
 | 
						||
            $list = [];
 | 
						||
            foreach ($item as $key => $val) {
 | 
						||
                if (in_array($key, $allowKeys)) {
 | 
						||
                    $list[$key] = $val;
 | 
						||
                }
 | 
						||
            }
 | 
						||
            $data[$ki] = $list;
 | 
						||
        }
 | 
						||
        return $data;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('getFilesize')) {
 | 
						||
    /**
 | 
						||
     * 尺寸单位转换
 | 
						||
     *
 | 
						||
     * @param $num
 | 
						||
     * @return string
 | 
						||
     */
 | 
						||
    function getFilesize($num): string
 | 
						||
    {
 | 
						||
        $p = 0;
 | 
						||
        $format = 'B';
 | 
						||
        if ($num > 0 && $num < 1024) {
 | 
						||
            return number_format($num) . ' ' . $format;
 | 
						||
        }
 | 
						||
        if ($num >= 1024 && $num < pow(1024, 2)) {
 | 
						||
            $p = 1;
 | 
						||
            $format = 'KB';
 | 
						||
        }
 | 
						||
        if ($num >= pow(1024, 2) && $num < pow(1024, 3)) {
 | 
						||
            $p = 2;
 | 
						||
            $format = 'MB';
 | 
						||
        }
 | 
						||
        if ($num >= pow(1024, 3) && $num < pow(1024, 4)) {
 | 
						||
            $p = 3;
 | 
						||
            $format = 'GB';
 | 
						||
        }
 | 
						||
        if ($num >= pow(1024, 4) && $num < pow(1024, 5)) {
 | 
						||
            $p = 3;
 | 
						||
            $format = 'TB';
 | 
						||
        }
 | 
						||
        $num /= pow(1024, $p);
 | 
						||
        return number_format($num, 3) . ' ' . $format;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('arrayNullToString')) {
 | 
						||
    /**
 | 
						||
     * 数组|或数据集中null值转为空字符串,并以数组格式返回
 | 
						||
     * 通常用于api json 返回内容null转换
 | 
						||
     *
 | 
						||
     * @param $data
 | 
						||
     * @return array
 | 
						||
     */
 | 
						||
    function arrayNullToString($data)
 | 
						||
    {
 | 
						||
        if ($data instanceof Collection || $data instanceof Model) {
 | 
						||
            $data = $data->toArray();
 | 
						||
        }
 | 
						||
        // 判断是否可以遍历
 | 
						||
        if (is_iterable($data)) {
 | 
						||
            foreach ($data as $key => $val) {
 | 
						||
                if ($val instanceof Collection || $data instanceof Model) {
 | 
						||
                    $val = $val->toArray();
 | 
						||
                }
 | 
						||
                if (is_iterable($val)) {
 | 
						||
                    $data[$key] = arrayNullToString($val);
 | 
						||
                } elseif ($val === null) {
 | 
						||
                    $data[$key] = '';
 | 
						||
                }
 | 
						||
            }
 | 
						||
        } else {
 | 
						||
            $data = [];
 | 
						||
        }
 | 
						||
        return $data;
 | 
						||
    }
 | 
						||
}
 | 
						||
if (!function_exists('arrayKeysExcludeFilter')) {
 | 
						||
    /**
 | 
						||
     * 一维数组键名排除过滤
 | 
						||
     *
 | 
						||
     * @param array $data
 | 
						||
     * @param array $excludeKeys 排除的字段
 | 
						||
     * @return array
 | 
						||
     */
 | 
						||
    function arrayKeysExcludeFilter(array $data, array $excludeKeys): array
 | 
						||
    {
 | 
						||
        foreach ($data as $key => $val) {
 | 
						||
            if (in_array($key, $excludeKeys)) {
 | 
						||
                unset($data[$key]);
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return $data;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('multiTwoArrayKeysExcludeFilter')) {
 | 
						||
    /**
 | 
						||
     * 二维维数组键名排除过滤
 | 
						||
     *
 | 
						||
     * @param  array  $data
 | 
						||
     * @param  array  $excludeKeys 排除的字段
 | 
						||
     * @return array
 | 
						||
     */
 | 
						||
    function multiTwoArrayKeysExcludeFilter(array $data, array $excludeKeys): array
 | 
						||
    {
 | 
						||
        foreach ($data as $ki => $item) {
 | 
						||
            foreach ($item as $key => $val) {
 | 
						||
                if (in_array($key, $excludeKeys)) {
 | 
						||
                    unset($item[$key]);
 | 
						||
                }
 | 
						||
            }
 | 
						||
            $data[$ki] = $item;
 | 
						||
        }
 | 
						||
        return $data;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
if (!function_exists('getLatelyWeekDate')) {
 | 
						||
    /**
 | 
						||
     * 获取本周的周一 到周日的日期
 | 
						||
     */
 | 
						||
    function getLatelyWeekDate()
 | 
						||
    {
 | 
						||
        //本周一
 | 
						||
        $oneDate = date('Y-m-d 00:00:00', (time() - ((date('w') == 0 ? 7 : date('w')) - 1) * 86400)); //w为星期几的数字形式,这里0为周日
 | 
						||
        $oneDateTime = strtotime($oneDate);
 | 
						||
        //返回周一到周天  1-7
 | 
						||
        return [
 | 
						||
            "1" => ["date"=>$oneDate],
 | 
						||
            "2" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 1)))],
 | 
						||
            "3" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 2)))],
 | 
						||
            "4" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 3)))],
 | 
						||
            "5" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 4)))],
 | 
						||
            "6" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 5)))],
 | 
						||
            "7" => ["date"=>date('Y-m-d 00:00:00', $oneDateTime + ((86400 * 6)))],
 | 
						||
        ];
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('stringDesensitization')) {
 | 
						||
    /**
 | 
						||
     * 字符串脱敏 默认给手机号脱敏 其他未兼容
 | 
						||
     *
 | 
						||
     * @param  string  $string
 | 
						||
     * @param  string  $s
 | 
						||
     * @param  int  $start
 | 
						||
     * @param  int  $len
 | 
						||
     * @return string
 | 
						||
     */
 | 
						||
    function stringDesensitization(string $string, string $s = '****', int $start = 3, int $len = 4): string
 | 
						||
    {
 | 
						||
        return substr_replace($string, $s, $start, $len);
 | 
						||
    }
 | 
						||
}
 | 
						||
/**
 | 
						||
 * UUID
 | 
						||
 */
 | 
						||
if(!function_exists("createUuid")){
 | 
						||
    function createUuid($prefix = "")
 | 
						||
    {
 | 
						||
        $chars = md5(uniqid(mt_rand(), true));
 | 
						||
        $uuid = substr($chars, 0, 8) . '-'
 | 
						||
            . substr($chars, 8, 4) . '-'
 | 
						||
            . substr($chars, 12, 4) . '-'
 | 
						||
            . substr($chars, 16, 4) . '-'
 | 
						||
            . substr($chars, 20, 12);
 | 
						||
        return $prefix . str_replace("-", "", $uuid);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 格式化黑名单时间
 | 
						||
 */
 | 
						||
if(!function_exists("formatBlankTime")){
 | 
						||
    function formatBlankTime($startdate, $enddate) {
 | 
						||
 | 
						||
        if (strtotime($startdate) > strtotime($enddate)) {
 | 
						||
            $ymd = $enddate;
 | 
						||
            $enddate = $startdate;
 | 
						||
            $startdate = $ymd;
 | 
						||
        }
 | 
						||
 | 
						||
        $date=floor((strtotime($enddate)-strtotime($startdate))/86400);
 | 
						||
        //echo "相差天数:".$date."天<br/><br/>";
 | 
						||
 | 
						||
        $hour=floor((strtotime($enddate)-strtotime($startdate))%86400/3600);
 | 
						||
        //echo "相差小时数:".$hour."小时<br/><br/>";
 | 
						||
 | 
						||
        $minute=floor((strtotime($enddate)-strtotime($startdate))%86400/60);
 | 
						||
        //echo "相差分钟数:".$minute."分钟<br/><br/>";
 | 
						||
 | 
						||
        $second=floor((strtotime($enddate)-strtotime($startdate))%86400%60);
 | 
						||
        //echo "相差秒数:".$second."秒";
 | 
						||
 | 
						||
        return  ($date>0?$date."天":'').
 | 
						||
            ($hour>0?$hour."小时":'').
 | 
						||
            ($minute>0?$minute."分钟":'').
 | 
						||
            ($second>0?$second."秒":'');
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 生成用户默认昵称
 | 
						||
 */
 | 
						||
if (!function_exists('generateDefaultNickName')) {
 | 
						||
    function generateDefaultNickName()
 | 
						||
    {
 | 
						||
        return '用户'.generateRand('6', 'mix');
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 根据当前坐标和范围距离计算方形范围内的经纬度坐标取值范围
 | 
						||
 * $curLat double类型 当前坐标纬度
 | 
						||
 * $curLng double类型 当前坐标经度
 | 
						||
 * $distance double类型 查询范围(单位km),当前坐标所在园的半径,与此范围正方形内切
 | 
						||
 *
 | 
						||
 * 相关数学知识:半正矢公式(Haversine公式)、正/反弦函数和正/反切函数等三角函数
 | 
						||
 * 平均地球半径:6371km
 | 
						||
 * 经度范围:-180 ~ 180 (注意差值180度限制时的计算)
 | 
						||
 * 纬度范围:-90 ~ 90
 | 
						||
 *
 | 
						||
 */
 | 
						||
if (!function_exists('getEarthSquareRangePoint')) {
 | 
						||
    function getEarthSquareRangePoint($curLat, $curLng, $distance)
 | 
						||
    {
 | 
						||
        $list = [];
 | 
						||
        $earthRadius    = 6371; // 地球平均半径 6371km
 | 
						||
        $disLat         = rad2deg($distance / $earthRadius);
 | 
						||
        $disLng         = rad2deg(2 * asin(sin($distance / (2 * $earthRadius) / cos(deg2rad($curLat)))));
 | 
						||
        $disLat         = abs($disLat);
 | 
						||
        $disLng         = abs($disLng);
 | 
						||
 | 
						||
        $list['cur_lat']    = $curLat;
 | 
						||
        $list['cur_lng']    = $curLng;
 | 
						||
        $list['dis_lat']    = $disLat;
 | 
						||
        $list['dis_lng']    = $disLng;
 | 
						||
 | 
						||
        $latTop     = $curLat + $disLat;
 | 
						||
        $latBottom  = $curLat - $disLat;
 | 
						||
        $lngLeft    = $curLng - $disLng;
 | 
						||
        $lngRight   = $curLng + $disLng;
 | 
						||
 | 
						||
 | 
						||
        $checkLatTopRem = abs(fmod(floatval($latTop), 180));
 | 
						||
        $checkLatTop    = abs(fmod(intval($latTop / 90), 4));
 | 
						||
        if ($latTop >= 0) {
 | 
						||
            $latTop     = floatval($checkLatTopRem > 90 ? (180 - $checkLatTopRem) : $checkLatTopRem);
 | 
						||
            $latTop     = $checkLatTop >= 2 ? (-$latTop) : $latTop; // 南半球为负数
 | 
						||
        } else {
 | 
						||
            $latTop     = floatval($checkLatTopRem > 90 ? (180 - $checkLatTopRem) : $checkLatTopRem);
 | 
						||
            $latTop     = $checkLatTop < 2 ? (-$latTop) : $latTop; // 南半球为负数
 | 
						||
        }
 | 
						||
 | 
						||
        $checkLatBottomRem  = abs(fmod(floatval($latBottom) ,180));
 | 
						||
        $checkLatBottom     = abs(intval($latBottom / 90) % 4);
 | 
						||
        if ($latBottom >= 0) {
 | 
						||
            $latBottom      = floatval($checkLatBottomRem > 90 ? (180 - $checkLatBottomRem) : $checkLatBottomRem);
 | 
						||
            $latBottom      = $checkLatBottom >= 2 ? (-$latBottom) : $latBottom; // 南半球为负数
 | 
						||
        } else {
 | 
						||
            $latBottom      = floatval($checkLatBottomRem > 90 ? (180 - $checkLatBottomRem) : $checkLatBottomRem);
 | 
						||
            $latBottom      = $checkLatBottom < 2 ? (-$latBottom) : $latBottom; // 南半球为负数
 | 
						||
        }
 | 
						||
 | 
						||
        $list['lat_min']    = min([$latTop, $curLat, $latBottom]);
 | 
						||
        $list['lat_max']    = max([$latTop, $curLat, $latBottom]);
 | 
						||
 | 
						||
 | 
						||
        $checkLngLeftRem    = abs(fmod(floatval($lngLeft), 360));
 | 
						||
        if ($lngLeft >= 0) {
 | 
						||
            $lngLeft        = floatval($checkLngLeftRem > 180 ? -(360 - $checkLngLeftRem) : $checkLngLeftRem); // 西半球为负数
 | 
						||
        } else {
 | 
						||
            $lngLeft        = floatval($checkLngLeftRem > 180 ? (360 - $checkLngLeftRem) : (-$checkLngLeftRem)); // 西半球为负数
 | 
						||
        }
 | 
						||
 | 
						||
        $checkLngRightRem   = abs(fmod(floatval($lngRight), 360));
 | 
						||
        if ($lngRight >= 0) {
 | 
						||
            $lngRight       = floatval($checkLngRightRem > 180 ? -(360 - $checkLngRightRem) : $checkLngRightRem); // 西半球为负数
 | 
						||
        } else {
 | 
						||
            $lngRight       = floatval($checkLngRightRem > 180 ? (360 - $checkLngRightRem) : (-$checkLngRightRem)); // 西半球为负数
 | 
						||
        }
 | 
						||
 | 
						||
        $list['lng_min']    = min([$lngLeft, $curLng, $lngRight]);
 | 
						||
        $list['lng_max']    = max([$lngLeft, $curLng, $lngRight]);
 | 
						||
 | 
						||
        $list['lat_top']    = $latTop;
 | 
						||
        $list['lat_bottom'] = $latBottom;
 | 
						||
        $list['lng_left']   = $lngLeft;
 | 
						||
        $list['lng_right']  = $lngRight;
 | 
						||
 | 
						||
        return $list;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 获取两个地点之鉴的距离
 | 
						||
 * */
 | 
						||
if (!function_exists('get_distance')) {
 | 
						||
    function get_distance($lat1, $lng1, $lat2, $lng2)
 | 
						||
    {
 | 
						||
        $earthRadius = 6367000;
 | 
						||
        $lat1 = ($lat1 * pi()) / 180;
 | 
						||
        $lng1 = ($lng1 * pi()) / 180;
 | 
						||
        $lat2 = ($lat2 * pi()) / 180;
 | 
						||
        $lng2 = ($lng2 * pi()) / 180;
 | 
						||
        $calcLongitude = $lng2 - $lng1;
 | 
						||
        $calcLatitude = $lat2 - $lat1;
 | 
						||
        $stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2);
 | 
						||
        $stepTwo = 2 * asin(min(1, sqrt($stepOne)));
 | 
						||
        $calculatedDistance = $earthRadius * $stepTwo;
 | 
						||
        return round($calculatedDistance);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 格式化优惠券的使用周期
 | 
						||
 * */
 | 
						||
if (!function_exists('encodeCouponCycle')) {
 | 
						||
    function encodeCouponCycle(array $week)
 | 
						||
    {
 | 
						||
        $font =[
 | 
						||
            "0"=>"星期天",
 | 
						||
            "1"=>"星期一",
 | 
						||
            "2"=>"星期二",
 | 
						||
            "3"=>"星期三",
 | 
						||
            "4"=>"星期四",
 | 
						||
            "5"=>"星期五",
 | 
						||
            "6"=>"星期六",
 | 
						||
        ];
 | 
						||
 | 
						||
        $str = [];
 | 
						||
        foreach ($week as $value){
 | 
						||
            if (isset($font[$value])) {
 | 
						||
                $str[] = $font[$value];
 | 
						||
            }
 | 
						||
        }
 | 
						||
        return implode(",",$str);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
if (!function_exists('is_mobile')) {
 | 
						||
    /**
 | 
						||
     * 判断手机号
 | 
						||
     * @param string $num 要验证的手机号
 | 
						||
     * @return bool
 | 
						||
     */
 | 
						||
    function is_mobile($num)
 | 
						||
    {
 | 
						||
        return preg_match("/^1(3|4|5|6|7|8|9)\d{9}$/", $num);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 求两个日期之间相差的天数
 | 
						||
 * (针对1970年1月1日之后,求之前可以采用泰勒公式)
 | 
						||
 * @param string $day1
 | 
						||
 * @param string $day2
 | 
						||
 * @return number
 | 
						||
 */
 | 
						||
if (!function_exists('diffBetweenTwoDays')) {
 | 
						||
    function diffBetweenTwoDays ($day1, $day2)
 | 
						||
    {
 | 
						||
        $second1 = strtotime($day1);
 | 
						||
        $second2 = strtotime($day2);
 | 
						||
 | 
						||
        if ($second1 < $second2) {
 | 
						||
            $tmp = $second2;
 | 
						||
            $second2 = $second1;
 | 
						||
            $second1 = $tmp;
 | 
						||
        }
 | 
						||
        return ($second1 - $second2) / 86400;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 获取当前毫秒数
 | 
						||
 * */
 | 
						||
if (!function_exists('msectime')) {
 | 
						||
    function msectime() {
 | 
						||
        list($msec, $sec) = explode(' ', microtime());
 | 
						||
        $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
 | 
						||
        return $msectime;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
if (!function_exists('filterEmoji')) {
 | 
						||
    function filterEmoji($str)
 | 
						||
    {
 | 
						||
        $str = preg_replace_callback(
 | 
						||
            '/./u',
 | 
						||
            function (array $match) {
 | 
						||
                return strlen($match[0]) >= 4 ? '' : $match[0];
 | 
						||
            },
 | 
						||
            $str);
 | 
						||
 | 
						||
        return $str;
 | 
						||
    }
 | 
						||
}
 |