|
@@ -0,0 +1,792 @@
|
|
|
+<?php
|
|
|
+// 应用公共文件
|
|
|
+
|
|
|
+use app\model\user\User;
|
|
|
+use Fastknife\Service\BlockPuzzleCaptchaService;
|
|
|
+use Fastknife\Service\ClickWordCaptchaService;
|
|
|
+use qiniu\exceptions\AuthException;
|
|
|
+use qiniu\services\CacheService;
|
|
|
+use qiniu\services\UploadService;
|
|
|
+use think\exception\ValidateException;
|
|
|
+use think\facade\Log;
|
|
|
+
|
|
|
+if (!function_exists('filter_str')) {
|
|
|
+ /**
|
|
|
+ * 过滤字符串敏感字符
|
|
|
+ * @param $str
|
|
|
+ * @return array|mixed|string|string[]|null
|
|
|
+ */
|
|
|
+ function filter_str($str)
|
|
|
+ {
|
|
|
+ $rules = [
|
|
|
+ '/\.\./', // 禁用包含 ../ 的参数
|
|
|
+ '/\<\?/', // 禁止 php 脚本出现
|
|
|
+ '/\bor\b.*=.*/i', // 匹配 'or 1=1',防止 SQL 注入(注意边界词 \b 和不区分大小写 i 修饰符)
|
|
|
+ '/(select[\s\S]*?)(from|limit)/i', // 防止 SQL 注入
|
|
|
+ '/(union[\s\S]*?select)/i', // 防止 SQL 注入
|
|
|
+ '/(having|updatexml|extractvalue)/i', // 防止 SQL 注入
|
|
|
+ '/sleep\((\s*)(\d*)(\s*)\)/i', // 防止 SQL 盲注
|
|
|
+ '/benchmark\((.*)\,(.*)\)/i', // 防止 SQL 盲注
|
|
|
+ '/base64_decode\(/i', // 防止 SQL 变种注入
|
|
|
+ '/(?:from\W+information_schema\W)/i', // 注意这里的 (?:...) 是不合法的,应该是 (?:...) 表示非捕获组,但通常我们不需要这个
|
|
|
+ '/(?:current_|user|database|schema|connection_id)\s*\(/i', // 防止 SQL 注入(注意去掉了不必要的 (?:...))
|
|
|
+ '/(?:etc\/\W*passwd)/i', // 防止窥探 Linux 用户信息
|
|
|
+ '/into(\s+)(?:dump|out)file\s*/i', // 禁用 MySQL 导出函数
|
|
|
+ '/group\s+by.+\(/i', // 防止 SQL 注入
|
|
|
+ '/(?:define|eval|file_get_contents|include|require|require_once|shell_exec|phpinfo|system|passthru|preg_\w+|execute|echo|print|print_r|var_dump|(fp)open|alert|showmodaldialog)\(/i', // 禁用 webshell 相关某些函数
|
|
|
+ '/(gopher|doc|php|glob|file|phar|zlib|ftp|ldap|dict|ogg|data)\:\/\//i', // 防止一些协议攻击(注意协议后的三个斜杠)
|
|
|
+ '/\$_(GET|POST|COOKIE|FILES|SESSION|ENV|GLOBALS|SERVER)\[/i', // 禁用一些内置变量,注意 PHP 变量名通常是大写的
|
|
|
+ '/<(iframe|script|body|img|layer|div|meta|style|base|object|input)/i', // 防止 XSS 标签植入
|
|
|
+ '/(onmouseover|onerror|onload|onclick)\=/i', // 防止 XSS 事件植入
|
|
|
+ '/\|\|.*?(?:ls|pwd|whoami|ll|ifconfig|ipconfig|&&|chmod|cd|mkdir|rmdir|cp|mv)/i', // 防止执行 shell(注意去掉了不合适的 ifconfog)
|
|
|
+ '/\sand\s+.*=.*/i' // 匹配 and 1=1
|
|
|
+ ];
|
|
|
+ if (filter_var($str, FILTER_VALIDATE_URL)) {
|
|
|
+ $url = parse_url($str);
|
|
|
+ if (!isset($url['scheme'])) return $str;
|
|
|
+ $host = $url['scheme'] . '://' . $url['host'];
|
|
|
+ $str = $host . preg_replace($rules, '', str_replace($host, '', $str));
|
|
|
+ } else {
|
|
|
+ $str = preg_replace($rules, '', $str);
|
|
|
+ }
|
|
|
+ return $str;
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('response_log_write')) {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 日志写入
|
|
|
+ * @param array $data
|
|
|
+ * @param string $type
|
|
|
+ */
|
|
|
+ function response_log_write(array $data, string $type = \think\Log::ERROR)
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ $id = 0;
|
|
|
+ foreach (['adminId', 'kefuId', 'uid', 'supplierId'] as $value) {
|
|
|
+ if (method_exists(request(), $value)) {
|
|
|
+ $id = request()->{$value}();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //日志内容
|
|
|
+ $log = [
|
|
|
+ $id, //管理员ID
|
|
|
+ request()->ip(), //客户ip
|
|
|
+ ceil(microtime() - (request()->time(true) * 1000)), //耗时(毫秒)
|
|
|
+ request()->method(true), //请求类型
|
|
|
+ str_replace("/", "", request()->rootUrl()), //应用
|
|
|
+ request()->baseUrl(), //路由
|
|
|
+ json_encode(request()->param(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),//请求参数
|
|
|
+ json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), //报错数据
|
|
|
+ ];
|
|
|
+
|
|
|
+ Log::write(implode("|", $log), $type);
|
|
|
+ } catch (\Throwable $e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('not_empty_check')) {
|
|
|
+ /**
|
|
|
+ * 非空验证
|
|
|
+ * @param $param
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ function not_empty_check($param)
|
|
|
+ {
|
|
|
+ if (is_array($param)) {
|
|
|
+ return !(count($param) <= 0);
|
|
|
+ } else {
|
|
|
+ if ($param == '') {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if ($param == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('do_request')) {
|
|
|
+ /**
|
|
|
+ * CURL 请求接口
|
|
|
+ * @param string $url 请求地址
|
|
|
+ * @param array $data 请求参数
|
|
|
+ * @param array $header 请求头
|
|
|
+ * @param bool $post true:post请求 false:get请求
|
|
|
+ * @param bool $json post请求时 请求数据打包方式是否为json
|
|
|
+ * @param int $format 数据打包为json格式时打包的格式值 来自json_encode
|
|
|
+ * @param bool $form post请求时 请求数据是否为表单 同时为false时为http提交 优先级高于json
|
|
|
+ * @return bool|false|string
|
|
|
+ */
|
|
|
+ function do_request($url, $query, $data, $header = null, $post = true, $json = false, $format = 0, $form = false)
|
|
|
+ {
|
|
|
+ $curl = curl_init();
|
|
|
+ $url .= ('?' . http_build_query($query));
|
|
|
+ curl_setopt($curl, CURLOPT_URL, $url);
|
|
|
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
|
|
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
|
|
+ if ($post) {
|
|
|
+ curl_setopt($curl, CURLOPT_POST, 1);
|
|
|
+ if (!$json && !$form) {
|
|
|
+ curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
|
|
|
+ } else if ($json && !$form) {
|
|
|
+ curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data, $format));
|
|
|
+ } else {
|
|
|
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
|
|
+ if ($header) {
|
|
|
+ curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
|
|
|
+ curl_setopt($curl, CURLOPT_HEADER, 0);
|
|
|
+ }
|
|
|
+ $result = curl_exec($curl);
|
|
|
+ if (curl_errno($curl)) {
|
|
|
+ return json_encode(['status' => curl_errno($curl), 'msg' => '请求失败']);
|
|
|
+ }
|
|
|
+ curl_close($curl);
|
|
|
+ return $result;
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('path_to_url')) {
|
|
|
+ /**
|
|
|
+ * 路径转url路径
|
|
|
+ * @param $path
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ function path_to_url($path)
|
|
|
+ {
|
|
|
+ return trim(str_replace(DS, '/', $path), '.');
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('get_group_user')) {
|
|
|
+ //所有下级
|
|
|
+ function get_group_user($id, $init = true, $members = null)
|
|
|
+ {
|
|
|
+ if ($init) {
|
|
|
+ $us = User::column('spread_uid', 'uid');
|
|
|
+ $members = [];
|
|
|
+ foreach ($us as $k => $v) {
|
|
|
+ if ($v > 0)
|
|
|
+ $members[$v][] = $k;
|
|
|
+ }
|
|
|
+ $id = [$id];
|
|
|
+ }
|
|
|
+ $arr = array();
|
|
|
+ foreach ($id as $v) {
|
|
|
+ $child = $members[$v] ?? [];
|
|
|
+ $arr = array_merge($arr, $child);
|
|
|
+ }
|
|
|
+ if (count($arr)) {
|
|
|
+ return array_merge($arr, get_group_user($arr, false, $members));
|
|
|
+ } else {
|
|
|
+ return $arr;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('sys_config')) {
|
|
|
+ /**
|
|
|
+ * 获取系统单个配置
|
|
|
+ * @param string $name
|
|
|
+ * @param mixed $default
|
|
|
+ * @param bool $cache
|
|
|
+ * @return string|array
|
|
|
+ */
|
|
|
+ function sys_config(string $name, $default = '', bool $cache = false)
|
|
|
+ {
|
|
|
+ if (empty($name))
|
|
|
+ return $default;
|
|
|
+
|
|
|
+ $config = app('sysConfig')->get($name, $default, $cache);
|
|
|
+ if (is_string($config)) $config = trim($config);
|
|
|
+ if ($config === '' || $config === false) {
|
|
|
+ return $default;
|
|
|
+ } else {
|
|
|
+ return $config;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if (!function_exists('store_config')) {
|
|
|
+ /**
|
|
|
+ * 获取系统单个配置
|
|
|
+ * @param string $name
|
|
|
+ * @param int $store_id
|
|
|
+ * @param mixed $default
|
|
|
+ * @param bool $cache
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ function store_config(string $name, int $store_id, $default = '', bool $cache = false)
|
|
|
+ {
|
|
|
+ if (empty($name))
|
|
|
+ return $default;
|
|
|
+
|
|
|
+ $config = app('sysConfig')->setStore($store_id)->get($name, $default, $cache);
|
|
|
+ if (is_string($config)) $config = trim($config);
|
|
|
+ if ($config === '' || $config === false) {
|
|
|
+ return $default;
|
|
|
+ } else {
|
|
|
+ return $config;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('check_phone')) {
|
|
|
+ /**
|
|
|
+ * 手机号验证
|
|
|
+ * @param $phone
|
|
|
+ * @return false|int
|
|
|
+ */
|
|
|
+ function check_phone($phone)
|
|
|
+ {
|
|
|
+ return preg_match("/^1[3456789]\d{9}$/", $phone);
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('check_mail')) {
|
|
|
+ /**
|
|
|
+ * 邮箱验证
|
|
|
+ * @param $mail
|
|
|
+ * @return false|int
|
|
|
+ */
|
|
|
+ function check_mail($mail)
|
|
|
+ {
|
|
|
+ if (filter_var($mail, FILTER_VALIDATE_EMAIL)) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('aj_captcha_check_one')) {
|
|
|
+ /**
|
|
|
+ * 验证滑块1次验证
|
|
|
+ * @param string $token
|
|
|
+ * @param string $pointJson
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ function aj_captcha_check_one(string $captchaType, string $token, string $pointJson)
|
|
|
+ {
|
|
|
+ aj_get_serevice($captchaType)->check($token, $pointJson);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('aj_captcha_check_two')) {
|
|
|
+ /**
|
|
|
+ * 验证滑块2次验证
|
|
|
+ * @param string $token
|
|
|
+ * @param string $pointJson
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ function aj_captcha_check_two(string $captchaType, string $captchaVerification)
|
|
|
+ {
|
|
|
+ aj_get_serevice($captchaType)->verificationByEncryptCode($captchaVerification);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('aj_captcha_create')) {
|
|
|
+ /**
|
|
|
+ * 创建验证码
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ function aj_captcha_create(string $captchaType)
|
|
|
+ {
|
|
|
+ return aj_get_serevice($captchaType)->get();
|
|
|
+ }
|
|
|
+}
|
|
|
+if (!function_exists('aj_get_serevice')) {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param string $captchaType
|
|
|
+ * @return ClickWordCaptchaService|BlockPuzzleCaptchaService
|
|
|
+ */
|
|
|
+ function aj_get_serevice(string $captchaType)
|
|
|
+ {
|
|
|
+ $config = \think\facade\Config::get('ajcaptcha');
|
|
|
+ switch ($captchaType) {
|
|
|
+ case "clickWord":
|
|
|
+ $service = new ClickWordCaptchaService($config);
|
|
|
+ break;
|
|
|
+ case "blockPuzzle":
|
|
|
+ $service = new BlockPuzzleCaptchaService($config);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new ValidateException('captchaType参数不正确!');
|
|
|
+ }
|
|
|
+ return $service;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('sort_list_tier')) {
|
|
|
+ /**
|
|
|
+ * 分级排序
|
|
|
+ * @param $data
|
|
|
+ * @param int $pid
|
|
|
+ * @param string $field
|
|
|
+ * @param string $pk
|
|
|
+ * @param string $html
|
|
|
+ * @param int $level
|
|
|
+ * @param bool $clear
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ function sort_list_tier($data, $pid = 0, $field = 'pid', $pk = 'id', $html = '|-----', $level = 1, $clear = true)
|
|
|
+ {
|
|
|
+ static $list = [];
|
|
|
+ if ($clear) $list = [];
|
|
|
+ foreach ($data as $k => $res) {
|
|
|
+ if ($res[$field] == $pid) {
|
|
|
+ $res['html'] = str_repeat($html, $level);
|
|
|
+ $list[] = $res;
|
|
|
+ unset($data[$k]);
|
|
|
+ sort_list_tier($data, $res[$pk], $field, $pk, $html, $level + 1, false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $list;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('get_tree_children')) {
|
|
|
+ /**
|
|
|
+ * 获取树状结构子集
|
|
|
+ */
|
|
|
+ function get_tree_children($data, $id = 0, $field = 'id', $pid = 'pid', $init = true)
|
|
|
+ {
|
|
|
+ static $children;
|
|
|
+ if ($init) {
|
|
|
+ $children = [];
|
|
|
+ foreach ($data as $v) {
|
|
|
+ $children[$v[$pid]][] = $v;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $arr = ($children[$id] ?? []);
|
|
|
+ foreach ($arr as &$v) {
|
|
|
+ $v['children'] = get_tree_children($data, $v[$field], $field, $pid, false);
|
|
|
+ }
|
|
|
+ return $arr;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('set_file_url')) {
|
|
|
+ /**
|
|
|
+ * @param $file
|
|
|
+ * @return mixed|string
|
|
|
+ */
|
|
|
+ function set_file_url($file)
|
|
|
+ {
|
|
|
+ if (!is_array($file)) {
|
|
|
+ $file = [$file];
|
|
|
+ }
|
|
|
+ foreach ($file as &$v) {
|
|
|
+ if (strpos($v, '://') === false) {
|
|
|
+ $v = rtrim(sys_config('site_url', ''), '/') . '/' . ltrim($v, '/');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $file;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if (!function_exists('check_link')) {
|
|
|
+ /**
|
|
|
+ * @param $file
|
|
|
+ * @return mixed|string
|
|
|
+ */
|
|
|
+ function check_link($url)
|
|
|
+ {
|
|
|
+ $ch = curl_init();
|
|
|
+ try {
|
|
|
+ curl_setopt($ch, CURLOPT_URL, $url);
|
|
|
+ curl_setopt($ch, CURLOPT_HEADER, 1);
|
|
|
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
|
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
|
|
+ $contents = curl_exec($ch);
|
|
|
+ if (preg_match("/404/", $contents)) return false;
|
|
|
+ if (preg_match("/403/", $contents)) return false;
|
|
|
+ return true;
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('filter_emoji')) {
|
|
|
+
|
|
|
+ // 过滤掉emoji表情
|
|
|
+ function filter_emoji($str)
|
|
|
+ {
|
|
|
+ return preg_replace_callback( //执行一个正则表达式搜索并且使用一个回调进行替换
|
|
|
+ '/./u',
|
|
|
+ function (array $match) {
|
|
|
+ return strlen($match[0]) >= 4 ? '' : $match[0];
|
|
|
+ },
|
|
|
+ $str);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if (!function_exists('getFileHeaders')) {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取文件大小头部信息
|
|
|
+ * @param string $url
|
|
|
+ * @param $isData
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ function getFileHeaders(string $url, $isData = true)
|
|
|
+ {
|
|
|
+ stream_context_set_default(['ssl' => ['verify_peer' => false, 'verify_peer_name' => false]]);
|
|
|
+ $header['size'] = 0;
|
|
|
+ $header['type'] = 'image/jpeg';
|
|
|
+ if (!$isData) {
|
|
|
+ return $header;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ $headerArray = get_headers(str_replace('\\', '/', $url), true);
|
|
|
+ if (!isset($headerArray['Content-Length'])) {
|
|
|
+ $header['size'] = 0;
|
|
|
+ } else {
|
|
|
+ if (is_array($headerArray['Content-Length']) && count($headerArray['Content-Length']) == 2) {
|
|
|
+ $header['size'] = $headerArray['Content-Length'][1];
|
|
|
+ } else {
|
|
|
+ $header['size'] = $headerArray['Content-Length'] ?? 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!isset($headerArray['Content-Type'])) {
|
|
|
+ $header['type'] = 'image/jpeg';
|
|
|
+ } else {
|
|
|
+ if (is_array($headerArray['Content-Type']) && count($headerArray['Content-Type']) == 2) {
|
|
|
+ $header['type'] = $headerArray['Content-Type'][1];
|
|
|
+ } else {
|
|
|
+ $header['type'] = $headerArray['Content-Type'] ?? 'image/jpeg';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ }
|
|
|
+ return $header;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('formatFileSize')) {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 格式化文件大小
|
|
|
+ * @param $size
|
|
|
+ * @return mixed|string|null
|
|
|
+ */
|
|
|
+ function formatFileSize($size)
|
|
|
+ {
|
|
|
+ if (!$size) {
|
|
|
+ return '0KB';
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ $toKb = 1024;
|
|
|
+ $toMb = $toKb * 1024;
|
|
|
+ $toGb = $toMb * 1024;
|
|
|
+ if ($size >= $toGb) {
|
|
|
+ return round($size / $toGb, 2) . 'GB';
|
|
|
+ } elseif ($size >= $toMb) {
|
|
|
+ return round($size / $toMb, 2) . 'MB';
|
|
|
+ } elseif ($size >= $toKb) {
|
|
|
+ return round($size / $toKb, 2) . 'KB';
|
|
|
+ } else {
|
|
|
+ return $size . 'B';
|
|
|
+ }
|
|
|
+ } catch (Exception $e) {
|
|
|
+ return '0KB';
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if (!function_exists('get_image_thumb')) {
|
|
|
+ /**
|
|
|
+ * 获取缩略图
|
|
|
+ * @param $filePath
|
|
|
+ * @param string $type all|big|mid|small
|
|
|
+ * @param bool $is_remote_down
|
|
|
+ * @return mixed|string|string[]
|
|
|
+ */
|
|
|
+ function get_image_thumb($filePath, string $type = 'all', bool $is_remote_down = false)
|
|
|
+ {
|
|
|
+ if (!$filePath || !is_string($filePath) || strpos($filePath, '?') !== false) return $filePath;
|
|
|
+ try {
|
|
|
+ $arr = explode('.', $filePath);
|
|
|
+ $ext_name = trim($arr[count($arr) - 1]);
|
|
|
+ if (!in_array($ext_name, ['png', 'jpg', 'jpeg'])) {
|
|
|
+ return $filePath;
|
|
|
+ }
|
|
|
+ $upload = UploadService::getOssInit($filePath, $is_remote_down);
|
|
|
+ $data = $upload->thumb('', $type);
|
|
|
+ $image = $type == 'all' ? $data : $data[$type] ?? $filePath;
|
|
|
+ } catch (\Throwable $e) {
|
|
|
+ $image = $filePath;
|
|
|
+ // throw new ValidateException($e->getMessage());
|
|
|
+ Log::error('获取缩略图失败,原因:' . $e->getMessage() . '----' . $e->getFile() . '----' . $e->getLine() . '----' . $filePath);
|
|
|
+ }
|
|
|
+ $data = parse_url($image);
|
|
|
+ if (!isset($data['host']) && (substr($image, 0, 2) == './' || substr($image, 0, 1) == '/')) {//不是完整地址
|
|
|
+ $image = sys_config('site_url') . $image;
|
|
|
+ }
|
|
|
+ //请求是https 图片是http 需要改变图片地址
|
|
|
+ if (strpos(request()->domain(), 'https:') !== false && strpos($image, 'https:') === false) {
|
|
|
+ $image = str_replace('http:', 'https:', $image);
|
|
|
+ }
|
|
|
+ return $image;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('get_thumb_water')) {
|
|
|
+ /**
|
|
|
+ * 处理数组获取缩略图、水印
|
|
|
+ * @param $list
|
|
|
+ * @param string $type
|
|
|
+ * @param array|string[] $field 1、['image','images'] type 取值参数:type 2、['small'=>'image','mid'=>'images'] type 取field数组的key
|
|
|
+ * @param bool $is_remote_down
|
|
|
+ * @return array|mixed|string|string[]
|
|
|
+ */
|
|
|
+ function get_thumb_water($list, string $type = 'small', array $field = ['image'], bool $is_remote_down = false)
|
|
|
+ {
|
|
|
+ if (!$list || !$field) return $list;
|
|
|
+ $baseType = $type;
|
|
|
+ $data = $list;
|
|
|
+ if (is_string($list)) {
|
|
|
+ $field = [$type => 'image'];
|
|
|
+ $data = ['image' => $list];
|
|
|
+ }
|
|
|
+ if (is_array($data)) {
|
|
|
+ foreach ($field as $type => $key) {
|
|
|
+ if (is_integer($type)) {//索引数组,默认type
|
|
|
+ $type = $baseType;
|
|
|
+ }
|
|
|
+ //一维数组
|
|
|
+ if (isset($data[$key])) {
|
|
|
+ if (is_array($data[$key])) {
|
|
|
+ $path_data = [];
|
|
|
+ foreach ($data[$key] as $k => $path) {
|
|
|
+ $path_data[] = get_image_thumb($path, $type, $is_remote_down);
|
|
|
+ }
|
|
|
+ $data[$key] = $path_data;
|
|
|
+ } else {
|
|
|
+ $data[$key] = get_image_thumb($data[$key], $type, $is_remote_down);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ foreach ($data as &$item) {
|
|
|
+ if (!isset($item[$key]))
|
|
|
+ continue;
|
|
|
+ if (is_array($item[$key])) {
|
|
|
+ $path_data = [];
|
|
|
+ foreach ($item[$key] as $k => $path) {
|
|
|
+ $path_data[] = get_image_thumb($path, $type, $is_remote_down);
|
|
|
+ }
|
|
|
+ $item[$key] = $path_data;
|
|
|
+ } else {
|
|
|
+ $item[$key] = get_image_thumb($item[$key], $type, $is_remote_down);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return is_string($list) ? ($data['image'] ?? '') : $data;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('make_path')) {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 上传路径转化,默认路径
|
|
|
+ * @param $path
|
|
|
+ * @param int $type
|
|
|
+ * @param bool $force
|
|
|
+ * @return string
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ function make_path($path, int $type = 2, bool $force = false)
|
|
|
+ {
|
|
|
+ $path = DS . ltrim(rtrim($path));
|
|
|
+ switch ($type) {
|
|
|
+ case 1:
|
|
|
+ $path .= DS . date('Y');
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ $path .= DS . date('Y') . DS . date('m');
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ $path .= DS . date('Y') . DS . date('m') . DS . date('d');
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ if (is_dir(app()->getRootPath() . 'public' . DS . 'uploads' . $path) == true || mkdir(app()->getRootPath() . 'public' . DS . 'uploads' . $path, 0777, true) == true) {
|
|
|
+ return trim(str_replace(DS, '/', $path), '.');
|
|
|
+ } else return '';
|
|
|
+ } catch (Exception $e) {
|
|
|
+ if ($force)
|
|
|
+ throw new Exception($e->getMessage());
|
|
|
+ return '无法创建文件夹,请检查您的上传目录权限:' . app()->getRootPath() . 'public' . DS . 'uploads' . DS . 'attach' . DS;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if (!function_exists('verify_domain')) {
|
|
|
+ /**
|
|
|
+ * @param $url
|
|
|
+ * @return false|string
|
|
|
+ */
|
|
|
+ function verify_domain($url)
|
|
|
+ {
|
|
|
+ if (!$url) return false;
|
|
|
+ if (strpos($url, 'http') === false) return false;
|
|
|
+ return rtrim($url, '/');
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('password')) {
|
|
|
+ /**
|
|
|
+ * @param $string
|
|
|
+ * @param null $salt
|
|
|
+ * @return array
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ function password($string, $salt = null)
|
|
|
+ {
|
|
|
+ if (!$salt)
|
|
|
+ $salt = bin2hex(random_bytes(6));
|
|
|
+ return [md5(md5($string) . $salt), $salt];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('parseName')) {
|
|
|
+ /**
|
|
|
+ * 字符串命名风格转换
|
|
|
+ * type 0 将 Java 风格转换为 C 的风格 1 将 C 风格转换为 Java 的风格
|
|
|
+ * @access public
|
|
|
+ * @param string $name 字符串
|
|
|
+ * @param integer $type 转换类型
|
|
|
+ * @param bool $ucfirst 首字母是否大写(驼峰规则)
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ function parseName($name, $type = 0, $ucfirst = true)
|
|
|
+ {
|
|
|
+ if ($type) {
|
|
|
+ $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
|
|
|
+ return strtoupper($match[1]);
|
|
|
+ }, $name ?? '');
|
|
|
+
|
|
|
+ return $ucfirst ? ucfirst($name) : lcfirst($name);
|
|
|
+ }
|
|
|
+
|
|
|
+ return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('check_card')) {
|
|
|
+ function check_card($idCard)
|
|
|
+ {
|
|
|
+ // 去除空格
|
|
|
+ $idCard = trim($idCard);
|
|
|
+
|
|
|
+ // 18位身份证号码正则表达式
|
|
|
+ $pattern = '/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[0-9Xx]$/';
|
|
|
+
|
|
|
+ if (!preg_match($pattern, $idCard)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验码验证
|
|
|
+ $weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
|
|
|
+ $checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
|
|
|
+
|
|
|
+ $sum = 0;
|
|
|
+ for ($i = 0; $i < 17; $i++) {
|
|
|
+ $sum += intval($idCard[$i]) * $weights[$i];
|
|
|
+ }
|
|
|
+
|
|
|
+ $checkCodeIndex = $sum % 11;
|
|
|
+ $expectedCheckCode = $checkCodes[$checkCodeIndex];
|
|
|
+
|
|
|
+ return strtoupper($idCard[17]) === $expectedCheckCode;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+if (!function_exists('check_password')) {
|
|
|
+ function check_password($value)
|
|
|
+ {
|
|
|
+ // 正则表达式:至少6位,最多18位,包含大小写字母、数字和特殊字符
|
|
|
+ $pattern = '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{6,18}$/';
|
|
|
+ return preg_match($pattern, $value) === 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if (!function_exists('check_trade_password')) {
|
|
|
+ function check_trade_password($value)
|
|
|
+ {
|
|
|
+ return preg_match('/^\d{6}$/', $value) === 1;
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if (!function_exists('check_sms_captcha')) {
|
|
|
+ function check_sms_captcha($phone, $type, $code)
|
|
|
+ {
|
|
|
+ $verifyCode = CacheService::get('code_' . $phone . '_' . $type);
|
|
|
+ if (!$verifyCode)
|
|
|
+ throw new AuthException('请先获取验证码');
|
|
|
+ $verifyError = (int)CacheService::get('code_error_' . $phone . '_' . $type, 0);
|
|
|
+ if ($verifyError >= 10) {
|
|
|
+ throw new AuthException('错误次数过多,请稍后再试');
|
|
|
+ }
|
|
|
+ $verifyCode = substr($verifyCode, 0, 6);
|
|
|
+ if ($verifyCode != $code) {
|
|
|
+ CacheService::set('code_error_' . $phone . '_' . $type, $verifyError + 1, 180);
|
|
|
+ throw new AuthException('验证码错误');
|
|
|
+ }
|
|
|
+ CacheService::delete('code_' . $phone . '_' . $type);
|
|
|
+ CacheService::delete('code_error_' . $phone . '_' . $type);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if (!function_exists('random_string')) {
|
|
|
+ function random_string($length)
|
|
|
+ {
|
|
|
+ mt_rand();
|
|
|
+ $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
|
+ $randomString = '';
|
|
|
+ for ($i = 0; $i < $length; $i++) {
|
|
|
+ $index = rand(0, strlen($characters) - 1);
|
|
|
+ $randomString .= $characters[$index];
|
|
|
+ }
|
|
|
+ return $randomString;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+if (!function_exists('create_account')) {
|
|
|
+ function create_account()
|
|
|
+ {
|
|
|
+ do {
|
|
|
+ $randomString = 'qn_' . random_string(16) . '_' . random_string(4);
|
|
|
+ } while (User::where('account', $randomString)->find());
|
|
|
+ return $randomString;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+if (!function_exists('curl_file_exist')) {
|
|
|
+ function curl_file_exist($url)
|
|
|
+ {
|
|
|
+ $ch = curl_init($url);
|
|
|
+ curl_setopt($ch, CURLOPT_NOBODY, true); // 不需要返回体
|
|
|
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向
|
|
|
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回结果而不是直接输出
|
|
|
+ curl_exec($ch);
|
|
|
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
|
+ curl_close($ch);
|
|
|
+ return $httpCode == 200;
|
|
|
+ }
|
|
|
+}
|