<?php
/**
 * +------------------------------------------------------------
 * | 应用公共文件
 * +------------------------------------------------------------
 * | @author zhx (10630650@qq.com)
 * +------------------------------------------------------------
 * | @copyright CIM (https://cimxx.com)
 * +------------------------------------------------------------
 * | @todo
 * +------------------------------------------------------------
 */

/**
 * 分析返回用户操作系统名称
 * @return string
 */
function get_client_os()
{
    $_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
    $var = ['miniprogram', 'micromessenger', 'nt 6.1', 'nt 6.0', 'nt 5.1', 'nt 5.2', 'nt 5', 'nt 4.9', 'nt 4', '98', '95', 'nt 10', 'mac', 'linux', 'unix', 'freebsd', 'sunos', 'beos', 'os/2', 'pc', 'aix', 'alipay'];
    $os = ['miniapp', 'wechat', 'Windows 7', 'Windows Vista', 'Windows XP', 'Windows Server 2003', 'Windows 2000', 'Windows ME', 'Windows NT 4.0', 'Windows 98', 'Windows 95', 'Windows 10', 'Mac', 'Linux', 'Unix', 'FreeBSD', 'SunOS', 'BeOS', 'OS/2', 'Macintosh', 'AIX', 'alipay'];
    $exp = 'unknown';
    foreach ($var as $k => $v) {
        if (stripos($_user_agent, $v) !== false) {
            $exp = $os[$k];
            break;
        }
    }
    return $exp;
}

/**
 * 分析返回用户网页浏览器名称
 * @return 浏览器类型
 */
function get_client_browser()
{
    $_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
    $_browsers = ['netcaptor', 'chrome', 'firefox', 'maxthon', 'opera', 'netscape', '360se', 'edge', 'micromessenger'];
    $exp = 'unknown';
    if (stripos($_user_agent, 'mac') !== false && stripos($_user_agent, 'safari') !== false) {
        $exp = 'safari';
        preg_match("/safari\/([0-9.]+)/i", $_user_agent, $rs);
        if (!empty($rs)) $exp = $rs[0];
    }
    foreach ($_browsers as $v) {
        if (stripos($_user_agent, $v) !== false) {
            preg_match("/$v\/([0-9.]+)/i", $_user_agent, $rs);
            if (!empty($rs)) $exp = $rs[0];
        }
    }
    return $exp;
}

/**
 * 头像
 */
function avatar($id = '')
{
    if ($id) {
        $path = DS . 'uploads' . DS . 'user' . DS . 'avatar' . DS;
        $path .= ceil($id / 10000) . DS . $id . '.jpg';
        if (is_file(ROOT_PATH . 'public' . $path)) {
            echo $path;
            exit;
        }
    }
    echo '/static/img/user/avatar.gif';
}


/**
 * get_dir() 获取路径下的文件夹
 * @param string $path 路径
 * @return array
 */
function get_dir($path)
{
    $dir = [];
    if (!file_exists(realpath($path))) {
        return $dir;
    }
    $rs = scandir(realpath($path));
    if (!empty($rs)) {
        foreach ($rs as $v) {
            if ($v != "." && $v != ".." && is_dir($path . '/' . $v)) {
                array_push($dir, $v);
            }
        }
    }
    return $dir;
}

/**
 * 获取路径下的文件
 * @return array
 */
function get_files($path)
{
    $files = [];
    if (!file_exists(realpath($path))) {
        return $files;
    }
    $rs = scandir(realpath($path));
    if (!empty($rs)) {
        foreach ($rs as $v) {
            if ($v != "." && $v != ".." && is_file($path . '/' . $v)) {
                array_push($files, $v);
            }
        }
    }
    return $files;
}

/**
 * 提示消息
 * @param array $ops
 * $ops['status'] 状态，默认 success
 * 'message'='提示','success'='成功','error'='出错','warning'='警告','stop'='阻止','wait'='等待','question'='疑问'
 */
function msg($ops, $msg = '', $url = '', $time = 1)
{
    if (is_array($ops)) {
        if (isset($ops['status'])) {
            $status = $ops['status'];
        }
        if (isset($ops['msg'])) {
            $msg = $ops['msg'];
        }
        if (isset($ops['url'])) {
            $url = $ops['url'];
        }
        if (isset($ops['time'])) {
            $time = $ops['time'];
        }
    } else {
        $status = $ops;
    }
    if ($status == '') {
        $status = 'success';
    }
    if ($url == '' && in_array($status, ['message', 'success'])) {
        $url = (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '');
    }
    return view('common@:msg', [
        'status' => $status,
        'msg' => $msg,
        'url' => $url,
        'time' => $time
    ]);
}

/**
 * 通用方法 函数限制输出字符串的数目，该方法接收一个字符串作为第一个参数以及该字符串最大输出字符数作为第二个参数：以及最后一个参数为超出省略号
 * @param $str
 * @param int $limit
 * @param string $arg
 * @return string
 */
function str_limit($value, $limit = 100, $end = '...')
{
    $value = strip_tags($value);
    if (mb_strwidth($value, 'UTF-8') <= $limit) {
        return $value;
    }
    return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')) . $end;
}


/**
 * 为数组树形排序
 * @param $data   数组
 * @param $parent 父级字段
 * @param $key    键名
 * @return array
 */
function array_to_tree($data, $parent = 'parent_id', $key = 'id')
{
    if (!is_array($data)) {
        return;
    }
    $result = array();
    //定义索引数组，用于记录节点在目标数组的位置
    $I = array();
    foreach ($data as $val) {
        if ($val[$parent] == 0) {
            $i = count($result);
            $result[$val[$key]] = $val;
            $I[$val[$key]] = &$result[$val[$key]];
        } else {
            $i = isset($I[$val[$parent]]['child']) ? count($I[$val[$parent]]['child']) : 0;
            $I[$val[$parent]]['child'][$val[$key]] = $val;
            $I[$val[$key]] = &$I[$val[$parent]]['child'][$val[$key]];
        }
    }
    return $result;
}


/**
 * 友好时间显示
 * 多久以前 / 以后
 * @return string
 */
function from_now($timestamp, $dateformat = 'Y年m月d日 H:i:s')
{
    if (is_string($timestamp)) $timestamp = strtotime($timestamp);
    $_now = time();
    $_time = abs($_now - $timestamp);
    $_end = ($timestamp > $_now ? '后' : '前');
    if ($_time < 60) {
        return $_time . '秒' . $_end;
    } elseif ($_time < 3600 && $_time > 60) {
        return intval($_time / 60) . '分钟' . $_end;
    } elseif ($_time < 86400 && $_time > 3600) {
        return intval($_time / 3600) . '小时' . $_end;
    } elseif ($_time < 604800 && $_time > 86400) {
        return intval($_time / 86400) . '天' . $_end;
    } elseif ($_time < 2592000 && $_time > 604800) {
        return intval($_time / 604800) . '周' . $_end;
    } elseif ($_time < 7776000 && $_time > 2592000) {
        return intval($_time / 2592000) . '个月' . $_end;
    } else {
        return date($dateformat, $timestamp);
    }
}


/**
 * response_code 输出函数
 * @param $errCode 错误码
 * @return void
 */
function response_code($errCode, $errMessage = '')
{
    $_httpCode = array(
        100 => 'Continue',
        101 => 'Switching Protocols',
        200 => 'OK',
        201 => 'Created',
        202 => 'Accepted',
        203 => 'Non-Authoritative Information',
        204 => 'No Content',
        205 => 'Reset Content',
        206 => 'Partial Content',
        300 => 'Multiple Choices',
        301 => 'Moved Permanently',
        302 => 'Found',
        303 => 'See Other',
        304 => 'Not Modified',
        305 => 'Use Proxy',
        307 => 'Temporary Redirect',
        400 => 'Bad Request',
        401 => 'Unauthorized',
        402 => 'Payment Required',
        403 => 'Forbidden',
        404 => 'Not Found',
        405 => 'Method Not Allowed',
        406 => 'Not Acceptable',
        407 => 'Proxy Authentication Required',
        408 => 'Request Timeout',
        409 => 'Conflict',
        410 => 'Gone',
        411 => 'Length Required',
        412 => 'Precondition Failed',
        413 => 'Request Entity Too Large',
        414 => 'Request-URI Too Long',
        415 => 'Unsupported Media Type',
        416 => 'Requested Range Not Satisfiable',
        417 => 'Expectation Failed',
        500 => 'Internal Server Error',
        501 => 'Not Implemented',
        502 => 'Bad Gateway',
        503 => 'Service Unavailable',
        504 => 'Gateway Timeout',
        505 => 'HTTP Version Not Supported'
    );

    // 清除输出缓存
    @ob_end_clean();

    if (array_key_exists($errCode, $_httpCode)) {
        $errMessage = $_httpCode[$errCode];
        @header("HTTP/1.1 {$errCode} {$errMessage}");
        @header("status: {$errCode} {$errMessage}");
    }
}

/**
 * 模板是否存在
 * @return string
 */
function template_exists($path)
{
    $path = config('template.view_base') . $path . '.' . config('template.view_suffix');
    if (is_file($path)) {
        return $path;
    }
}

/**
 * 设置缓存数据
 * @param string $cache_id
 */
function load_setting($cache_id = '', $refresh = 0)
{
    if (!$cache_id) return '';
    if ($refresh) cache($cache_id, null);
    $data = cache($cache_id);
    if (empty($data)) {
        $data = db('setting')->where('id', $cache_id)->find();
        if (!empty($data)) {
            $data = json_decode($data['value'], 1);
            cache($cache_id, $data);
        } else {
            $data = '';
        }
    }
    return $data;
}

/**
 * 获取栏目
 */
function load_columns($tree = 1, $refresh = 0, $key = '', $model = [], $status = 1, $count = 0)
{
    if (is_array($tree)) {
        $status = isset($tree['status']) ? $tree['status'] : $status;
        $model = isset($tree['model']) ? $tree['model'] : $model;
        $key = isset($tree['key']) ? $tree['key'] : $key;
        $refresh = isset($tree['refresh']) ? $tree['refresh'] : $refresh;
        $count = isset($tree['count']) ? $tree['count'] : $count;
        $tree = isset($tree['tree']) ? $tree['tree'] : 1;
    }
    $cache_id = 'columns';
    if ($refresh) cache($cache_id, null);
    $rs = cache($cache_id);
    if (empty($rs)) {
        $rs = model('\app\index\model\Column')->order('parent_id asc,list_order asc,id asc')->column('*', 'id');
        if (!empty($rs)) {
            cache($cache_id, $rs, 0);
        } else {
            $rs = [];
        }
    }
    if ($count) {
        $column_id = array_column($rs, 'id');
        if (!empty($column_id)) {
            $counts = db('data')->field("count(*) as total, column_id")->where('delete_time', 'eq', '0')->cache(true, 86400)->group("column_id")->column('count(*)', 'column_id');
        }
    }
    foreach ($rs as $k => $v) {
        if (!empty($model) && !in_array($v['model'], (array)$model)) {
            unset($rs[$k]);
            continue;
        }
        if ($status !== '' && $v['status'] != $status) {
            unset($rs[$k]);
            continue;
        }
        if (!empty($counts)) $v['count'] = empty($counts[$v['id']]) ? 0 : $counts[$v['id']];
        if ($v['key'] == '') $v['key'] = $k;
        $v['setting'] = json_decode($rs[$k]['setting'], true);
        $v['url'] = url('index/index/column', ['key' => $v['key']]);
        $rs[$k] = $v;
    }
    if ($key) $rs = array_column($rs, NULL, $key);
    return ($tree ? array_to_tree($rs) : $rs);
}

/**
 * 获取单个栏目
 */
function load_column($cid, $child = 0, $status = 1, $group_id = 0)
{
    if (is_numeric($cid)) {
        $columns = load_columns(0, 0, '', '', '');
    } else {
        $columns = load_columns(0, 0, 'key', '', '');
    }
    if (isset($columns[$cid])) {
        $column = $columns[$cid];
        if ($status !== '' && $status != $column['status']) return '';
        if (!empty($column)) {
            $column['group'] = $column['setting']['group'][$group_id] ?? '';
        }
        if ($column['parent_id'] > 0) {
            if (!is_numeric($cid)) $columns = array_column($columns, null, 'id');
            $column['parent'] = isset($columns[$column['parent_id']]) ? $columns[$column['parent_id']] : [];
        } else {
            if ($child) {
                $columns = load_columns(1, 0);
                if (!is_numeric($cid)) $columns = array_column($columns, null, 'key');
                $column['child'] = empty($columns[$cid]['child']) ? '' : $columns[$cid]['child'];
            }
        }
        return $column;
    }
}

/**
 * 获取地区
 */
function load_areas($tree = 1, $refresh = 0)
{
    $cache_id = 'areas';
    if ($refresh) cache($cache_id, null);
    $rs = cache($cache_id);
    if (empty($rs)) {
        $data = db('area')->field('id,name,parent_id')->where('status', 1)->order('id asc')->select();
        if (!empty($data)) {
            $rs = array_column($data, null, 'id');
            cache($cache_id, $rs, 0);
        } else {
            $rs = [];
        }
    }
    if ($tree && !empty($rs)) {
        $rs = array_to_tree($rs);
    }
    return $rs;
}


/**
 * 格式化时间
 */
function time_format($val)
{
    if (is_string($val)) $val = strtotime($val);
    return [
        'ymd' => date("Y-m-d", $val),
        'md' => date("m-d", $val),
        'his' => date("H:i:s", $val),
        'full' => date("Y-m-d H:i:s", $val),
        'short' => date("m-d H:i", $val),
        'from_now' => from_now($val, 'm月d日')
    ];
}


/**
 * 获取 IP  地理位置
 * 淘宝IP接口
 * @Return: array
 */
function get_ip_address($ip = '')
{
    if ($ip == '') $ip = request()->ip();
    include(Env::get('extend_path') . 'IP.php');
    $iploaction = new IpLocation();
    $data = $iploaction->getlocation($ip);
    if (empty($data)) return false;
    return $data;
}

function get_token($data)
{
    //通过计算生成随机token
    $tmpStr = md5(date('YmdHis') . rand(10000, 99999));
    $data['time'] = time();
    cache($tmpStr, $data, 7200);
    return $tmpStr;
}

function create_str()
{
    return md5(microtime(true) . rand(10000, 99999));
}

/**
 * @删除文件夹
 */
function clear_file($path)
{
    if (!file_exists($path)) return;
    if (is_dir($path)) {
        $op = dir($path);
        while (false != ($item = $op->read())) {
            if ($item == '.' || $item == '..') continue;
            if (is_dir($op->path . '/' . $item)) {
                clear_file($op->path . '/' . $item);
                @rmdir($op->path . '/' . $item);
            } else {
                @unlink($op->path . '/' . $item);
            }
        }
        @rmdir($path);
    } else {
        @unlink($path);
    }
}

/**
 * 加载敏感词
 */
function load_words($refresh = 0, $key = '', $action = '')
{
    $cache_key = 'sys_words';
    if ($refresh) {
        cache($cache_key, null);
        \think\facade\Cache::clear('sys_words');
    }
    if (!empty(cache($cache_key))) {
        $rs = cache($cache_key);
    } else {
        $rs = db('words')->alias('w')->field('w.url,w.name,w.level,w.status,substring_index(substring_index(w.fields,\',\',b.id+1),\',\',-1) fields')->join('__TEMP__ b', 'b.id < (length(w.fields)-length(replace(w.fields,\',\',\'\'))+1)')->where('w.fields', 'neq', '')->where('w.status', '=', 1)->select();
        if (!empty($rs)) {
            cache($cache_key, $rs, 3600);
        }
    }
    if (!empty($rs)) {
        $data = [];
        if (!empty($key)) {
            foreach ($rs as $k => $v) {
                if (!$action) {
                    $key = $action . '_' . $key;
                } else {
                    $key = '_' . $key;
                }
                if (strpos($v['fields'], $key)) {
                    $data[] = $v;
                }
            }
        }
        $rs = $data;
    }
    return $rs;
}

/**
 * 将内容中的关键词增加系统设置的关键词链接
 * @param string $content
 * @return string
 */
function word_link($content = '', $column_id = 0)
{
    if (!empty($content)) {
        $where = [
            ['url', 'neq', ''],
            ['status', '=', 1],
        ];
        $words = db('words')->where(array_merge($where, [['column_id', '=', 0]]))->field('*,LENGTH(name) length')->cache('replace_sys_words_column_id_0', 3600, 'sys_words')->select();
        if ($column_id) {
            $column_words = db('words')->where(array_merge($where, [['column_id', '=', $column_id]]))->field('*,LENGTH(name) length')->cache('replace_sys_words_column_id_' . $column_id, 3600, 'sys_words')->select();
            $words = array_values(array_replace(array_column($words, null, 'name'), array_column($column_words, null, 'name')));
        }
        if (!empty($words)) {
            array_multisort(array_column($words, 'length'), SORT_DESC, $words);
            $var = md5(microtime(true));
            foreach ($words as $k => $v) {
                $content = str_replace($v['name'], substr($var, 0, 16) . $k . substr($var, 16, 16), $content);
            }
            foreach ($words as $k => $v) {
                $content = str_replace(substr($var, 0, 16) . $k . substr($var, 16, 16), "<a href=\"" . $v['url'] . "\">" . $v['name'] . "</a>", $content);
            }
        }
    }
    return $content;
}

/**
 * 过滤敏感词
 */
function filter_words($content = '', $behavior = '', $action = '')
{
    $result = [
        'content' => $content,
        'level' => 0,
        'words' => []
    ];
    if (!$content || !$behavior) return $result;
    $data = load_words(0, $behavior, $action);
    if (!empty($data)) {
        foreach ($data as $k => $v) $words[str_replace('_' . $behavior, '', $v['fields'])][] = $v['name'];
        foreach ($words as $k => $v) {
            switch ($k) {
                case 'forbid':
                    foreach ($v as $kk => $vv) {
                        if (strpos($content, $vv) !== false) {
                            if ($result['level'] < 3) $result['level'] = 3;
                            $result['words']['3'][] = $vv;
                        }
                    }
                    break;
                case 'check':
                    foreach ($v as $kk => $vv) {
                        if (strpos($content, $vv) !== false) {
                            if ($result['level'] < 2) $result['level'] = 2;
                            if (strpos($content, $vv) !== false) $result['words'][2][] = $vv;
                        }
                    }
                    break;
                case 'replace':
                    foreach ($v as $kk => $vv) {
                        if (strpos($content, $vv) !== false) {
                            if ($result['level'] < 1) $result['level'] = 1;
                            $result['words'][1][] = $vv;
                            $result['content'] = str_replace($vv, implode('', array_fill(0, strlen($vv), '*')), $content);
                        }
                    }
                    break;
            }
        }
    }
    return $result;
}

/**
 * 对象转数组
 * @return array
 */
function object_to_array($data)
{
    $data = (array)$data;
    foreach ($data as $k => $v) {
        if (gettype($v) == 'resource') return;
        if (gettype($v) == 'object' || gettype($v) == 'array')
            $data[$k] = (array)object_to_array($v);
    }
    return $data;
}

/**
 * 获取数组中的指定键值对
 */
function get_array_keys($arr = [], $key = [], $model = '')
{
    if (!is_array($arr)) return '';
    if (is_string($key)) $key = explode(',', $key);
    if (empty($key)) return $arr;
    $result = [];
    foreach ($key as $k => $v) {
        if (strpos($v, '.')) {
            if (count($key) == 1) {
                $result = get_array_keys($arr[substr($v, 0, strpos($v, '.'))], substr($v, strpos($v, '.') + 1));
            } else {
                $result[substr($v, 0, strpos($v, '.'))] = get_array_keys($arr[substr($v, 0, strpos($v, '.'))], substr($v, strpos($v, '.') + 1));
            }
        } else {
            if ($model == 1 || count($key) > 1) {
                $result[$v] = isset($arr[$v]) ? $arr[$v] : '';
            } else {
                $result = isset($arr[$v]) ? $arr[$v] : '';
            }
        }
    }
    return $result;
}

/**
 * curl
 */
function http($url, $timeout = 30, $method = 'GET', $postfields = NULL)
{
    $ci = curl_init();
    /* Curl settings */
    curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $timeout);
    curl_setopt($ci, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ci, CURLOPT_ENCODING, "");
    curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, 'FALSE');
    curl_setopt($ci, CURLOPT_HEADER, FALSE);
    switch ($method) {
        case 'POST':
            curl_setopt($ci, CURLOPT_POST, TRUE);
            if (!empty($postfields)) {
                curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
            }
            break;
        case 'DELETE':
            curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
            if (!empty($postfields)) {
                $url = "{$url}?{$postfields}";
            }
    }
    $headers[] = "API-RemoteIP: " . $_SERVER['REMOTE_ADDR'];
    curl_setopt($ci, CURLOPT_URL, $url);
    curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ci, CURLINFO_HEADER_OUT, TRUE);
    $response = curl_exec($ci);
    curl_close($ci);
    return $response;
}

/**
 * 获取栏目字段
 */
function load_fields($cid, $refresh = 0, $list_show = '', $use = '', $model = 'column')
{
    $fields = new \app\common\controller\Fields();
    return $fields->read($cid, $refresh, $list_show, $use, $model);
}

/**
 * 高德地图地址转坐标
 * @return array
 */
function address_to_point($address = '')
{
    if ($address) {
        //todo 获取配置的地图api
        $result = http('https://restapi.amap.com/v3/geocode/geo?address=' . $address . '&key=91c152ffa49c449eafc06bf7454d4a96', 2);
        if (!empty($result)) {
            $result = json_decode($result, 1);
            if ($result['status'] == 1) {
                return explode(',', $result['geocodes'][0]['location']);
            }
        }
    }
    return '';
}

/**
 * 加载模板路径
 * 根据控制台设定切换到手机端模板目录
 */
function load_template_path($name = 'template')
{
    $_cim_config = cache('cim');
    $template_path = \Env::get('root_path') . $name . '/';
    if (!empty($_cim_config)) {
        if (isset($_cim_config['mobile']) && $_cim_config['mobile'] == 1 && request()->isMobile()) {
            if (file_exists(\Env::get('root_path') . $name . '/mobile/')) $template_path = \Env::get('root_path') . $name . '/mobile/';
        }
    }
    return $template_path;
}

/**
 * 获取栏目数据量
 */
function column_count($id = '', $model = [])
{
    $columns = load_columns([
        'tree' => 0,
        'model' => $model
    ]);
    if (!empty($id)) $columns = get_array_keys($columns, implode(',', (array)$id));
    if (!empty($columns)) {
        //栏目今天发布数量
        $today_counts = db('data')->field('count(*) as total,column_id')->where("FROM_UNIXTIME(create_time, '%Y%m%d')=" . date('Ymd'))->where('delete_time', '=', 0)->cache(true, 86400)->group('column_id')->column('count(*)', 'column_id');
        //栏目昨日发布数量
        $yesterday_counts = db('data')->field('count(*) as total,column_id')->where("FROM_UNIXTIME(create_time, '%Y%m%d')=" . date('Ymd', time() - 86400))->where('delete_time', '=', 0)->cache(true, 86400)->group('column_id')->column('count(*)', 'column_id');
        if (count($columns) == 1) {
            $column_key = array_values($columns)[0]['id'];
            $columns = [
                'today' => empty($today_counts[$columns[$column_key]['id']]) ? 0 : $today_counts[$columns[$column_key]['id']],
                'yesterday' => empty($yesterday_counts[$columns[$column_key]['id']]) ? 0 : $yesterday_counts[$columns[$column_key]['id']]
            ];
        } else {
            $columns = [
                'today' => array_sum(array_values($today_counts)),
                'yesterday' => array_sum(array_values($yesterday_counts))
            ];
        }
    }
    return $columns;
}

/**
 * 获取插件类的类名
 * @param $name 插件名
 * @param string $type 返回命名空间类型
 * @param string $class 当前类名
 * @return string
 */
function get_addon_class($name, $type = '', $class = null)
{
    $name = \think\Loader::parseName($name);
    // 处理多级控制器情况
    if (!is_null($class) && strpos($class, '.')) {
        $class = explode('.', $class);
        foreach ($class as $key => $cls) {
            $class[$key] = \think\Loader::parseName($cls, 1);
        }
        $class = implode('\\', $class);
    } else {
        $class = \think\Loader::parseName(is_null($class) ? $name : $class, 1);
    }
    switch ($type) {
        case 'controller':
            $namespace = "\\addons\\" . $name . "\\controller\\" . $class;
            break;
        default:
            $namespace = "\\addons\\" . $name . "\\" . $class;
    }

    return class_exists($namespace) ? $namespace : '';
}

/**
 * 返回插件url
 * @param $url
 */
function addons_url($url, $param = [], $suffix = true, $domain = false)
{
    return url("@addons/{$url}", $param, $suffix, $domain);
}

/**
 * 复制文件夹
 * @param $source
 * @param $dest
 */
function copydir($source, $dest)
{
    if (!file_exists($dest)) mkdir($dest);
    $handle = opendir($source);
    while (($item = readdir($handle)) !== false) {
        if ($item == '.' || $item == '..') continue;
        $_source = $source . '/' . $item;
        $_dest = $dest . '/' . $item;
        if (is_file($_source)) copy($_source, $_dest);
        if (is_dir($_source)) copydir($_source, $_dest);
    }
    closedir($handle);
}

/**
 * 加载自定义函数库文件
 */
if (file_exists('./custom.php')) include_once('./custom.php');
