diff --git a/app/Service/UtilsService.php b/app/Service/UtilsService.php index 6174d59c..643da8e2 100755 --- a/app/Service/UtilsService.php +++ b/app/Service/UtilsService.php @@ -5,7 +5,9 @@ namespace App\Service; use App\Enum\ErrorEnum; use DateTime; use Exception; +use Illuminate\Routing\Route; use Random\RandomException; +use ReflectionClass; class UtilsService { @@ -151,9 +153,9 @@ class UtilsService $len = 9999999999; switch ($type) { case 0: - return 'DK'. date('Ymd') . str_pad(mt_rand(1, $len), 11, '0', STR_PAD_LEFT); + return 'DK' . date('Ymd') . str_pad(mt_rand(1, $len), 11, '0', STR_PAD_LEFT); case 1: - return 'DD'. date('Ymd') . str_pad(mt_rand(1, $len), 11, '0', STR_PAD_LEFT); + return 'DD' . date('Ymd') . str_pad(mt_rand(1, $len), 11, '0', STR_PAD_LEFT); default: return ''; } @@ -217,4 +219,29 @@ class UtilsService $ageInterval = $currentDate->diff($birthDate); return $ageInterval->y; } + + public function autoRouteRegister($class): void + { + foreach ($class as $key => $value) { + + // 获取控制器$value的所有方法 + $methods = (new ReflectionClass($value))->getMethods(); + + // 注册路由 + foreach ($methods as $method) { + // 获取方法注释 @Method + $docComment = $method->getDocComment(); + if ($method->name === '__construct' || preg_match('/@Method\s+(NO)\b/', $docComment, $matches)) { + continue; + } + + $httpMethod = 'any'; +// 查询 @Method GET 或者 @Method POST + if (preg_match('/@Method\s+(GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD|ANY)\b/', $docComment, $matches)) { + $httpMethod = $matches[1]; + } + Route::$httpMethod($key . '/' . cc_camel_case_to_dash($method->getName()), [$value, conjunction_symbol_processing($method->name)]); + } + } + } } diff --git a/bootstrap/app.php b/bootstrap/app.php index 7b162dac..d6542762 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -7,6 +7,7 @@ use Illuminate\Foundation\Configuration\Middleware; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', + api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) diff --git a/config/helpers.php b/config/helpers.php new file mode 100755 index 00000000..808e38cd --- /dev/null +++ b/config/helpers.php @@ -0,0 +1,492 @@ + $value) { + + // 获取控制器$value的所有方法 + $methods = (new ReflectionClass($value))->getMethods(); + + // 注册路由 + foreach ($methods as $method) { + // 获取方法注释 @Method + $docComment = $method->getDocComment(); + if ($method->name === '__construct' || preg_match('/@Method\s+(NO)\b/', $docComment, $matches)) { + continue; + } + + $httpMethod = 'any'; + // 查询 @Method GET 或者 @Method POST + if (preg_match('/@Method\s+(GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD|ANY)\b/', $docComment, $matches)) { + $httpMethod = $matches[1]; + } + Illuminate\Support\Facades\Route::$httpMethod( $key. '/'. cc_camel_case_to_dash($method->getName()), [$value, conjunction_symbol_processing($method->name)] ); + } + } + } +} + +/** + * 无限极分类 + * @param $data + * @param $pid + * @return mixed + */ +if ( !function_exists('tree') ) { + function tree($data, $pid = 0, $idField = 'id', $pidField = 'pid'): array + { + $tree = array(); + foreach ($data as &$v) + { + if ($v[$pidField] == $pid) + { + $v['children'] = tree($data, $v[$idField], $idField, $pidField); + if (empty($v['children'])) unset($v['children']); + $tree[] = $v; + } + } + return $tree; + } +} + + +/** + * 设置不关闭 + * @return true + */ +if ( !function_exists('cc_set_time_limit') ) { + function cc_set_time_limit(): bool { + //让程序一直运行 + set_time_limit(0); + //设置程序运行内存 + ini_set('memory_limit', '1024M'); + return true; + } +} +/** + * 获取ip所属地 + * + * @return true + */ +if ( !function_exists('cc_get_ip_lookup') ) { + function cc_get_ip_lookup($ip = ''): array { + $result = (new GuzzleHttp\Client())->get('https://api.vore.top/api/Weather?ip='. $ip); + $weather = json_decode($result->getBody()->getContents(), true); + if ( empty($weather) ) { + $data = [ + 'weather' => '未知', + 'temperature' => '未知', + 'winddirection' => '未知', + 'reporttime' => '未知', + 'area' => '未知', + 'info' => '未知', + ]; + } else { + $data = [ + 'area' => $weather['data']['ipdata']['area'], + 'info' => $weather['data']['ipdata']['info'], + ]; + } + return $data; + } +} +/** + * 获取ip + */ +if (!function_exists('get_ip')) { + function get_ip() { + return $_SERVER['HTTP_X_FORWARDED_FOR']?? request()->getClientIp(); + } +} + +/** + * 获取操作系统 + * @return string + */ +if ( !function_exists('cc_get_os') ) { + function cc_get_os(): string { + if (!empty($_SERVER['HTTP_USER_AGENT'])) { + $os = $_SERVER['HTTP_USER_AGENT']; + + return match (true) { + str_contains($os, 'Windows') => 'Windows', + str_contains($os, 'Macintosh') => 'Mac', + str_contains($os, 'Linux') => 'Linux', + str_contains($os, 'Android') => 'Android', + str_contains($os, 'iOS') => 'iOS', + str_contains($os, 'Api') => 'Api Post', + default => 'Unknown', + }; + } else { + return "获取访客操作系统信息失败!"; + } + } +} + +/** + * 获取浏览器 + * @return string + */ +if ( !function_exists('cc_get_browser') ) { + function cc_get_browser(): string { + if (empty($_SERVER['HTTP_USER_AGENT'])) { + return "获取浏览器信息失败!"; + } + + $userAgent = $_SERVER['HTTP_USER_AGENT']; + + foreach ([ + 'MSIE' => 'MSIE', + 'Edg' => 'Microsoft Edge', + 'Firefox' => 'Firefox', + 'Chrome' => 'Chrome', + 'Safari' => 'Safari', + 'Opera' => 'Opera', + 'Api' => 'Api Post', + ] as $key => $browser) { + if (str_contains($userAgent, $key)) { + return $browser; + } + } + + return 'Other'; + } +} + +/** + * 在二维数组其中某个值相同时,提取指定的字段 + * @param $arr // 数组 + * @param $extract // 提取字段 + * @param $repeat // 重复字段 + * @param $isUnset // 是否删除未重复的值 + * @return array + */ +if ( !function_exists('cc_get_repeat_values') ) { + function cc_get_repeat_values($arr, $extract, $repeat , $isUnset = false): array { + $key = []; + $result = []; + $len = count($arr); + for ( $i=0; $i<$len; $i++ ) { + if ( !in_array($arr[$i][$repeat], $key) ) { + if ( !array_key_exists($arr[$i][$repeat], $result) ) $result[$arr[$i][$repeat]] = []; + $result[$arr[$i][$repeat]][] = $arr[$i][$extract]; + continue; + } + $key[] = $arr[$i][$repeat]; + } + if ( $isUnset === true ) { + // 删除未重复的下标 + foreach ( $result as $k => &$v ) { + if ( count($v) <= 1 ) { + unset($result[$k]); + } + } + } + return $result; + } +} + +/** + * 数据脱敏 + * @param string $str + * @param string $type + * @return string + */ +if ( !function_exists('desensitization') ) { + + function desensitization(string $str, string $type = 'phone'): string + { + if (empty($str)) return ''; + + if ($type === 'phone') { + if (strlen($str) !== 11) { + throw new Exception('手机号格式错误'); + } + return substr($str, 0, 3) . '****' . substr($str, 7); + } elseif ($type === 'id_card') { + if (strlen($str) !== 18) { + throw new Exception('身份证号格式错误'); + } + return substr($str, 0, 6) . '********' . substr($str, 14); + } else { + throw new Exception('类型错误'); + } + } +} + +/** + * 连赐福转换小驼峰 + * @param $string + * @return string + */ +if(!function_exists('conjunction_symbol_processing')) { + function conjunction_symbol_processing($string): string + { + $string = str_replace('-', ' ', $string); // 将连字符替换为空格 + $string = ucwords($string); // 将每个单词的首字母大写 + $string = str_replace(' ', '', $string); // 空格删除 + $string[0] = lcfirst($string)[0]; // 首字母小写 + + return $string; + } + +} + +// 小驼峰转换- +if ( !function_exists('cc_camel_case_to_dash') ) { + function cc_camel_case_to_dash($str): string + { + return strtolower(preg_replace('/([a-z])([A-Z])/', '$1-$2', $str)); + } +} + +/** + * 将驼峰字符串转化为下划线区分 + * @param $str + * @return string + */ +if ( !function_exists('cc_camel_case_to_underscore') ) { + function cc_camel_case_to_underscore($str): string + { + return strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $str)); + } +} + +/** + * 身份证脱敏 + * @return true + */ +if ( !function_exists('cc_id_card_text') ) { + function cc_id_card_text($idCard): string { + return substr_replace($idCard, '********', 6, 8 ); + } +} + +/** + * 手机号脱敏 + * @return true + */ +if ( !function_exists('cc_phone_text') ) { + function cc_phone_text($phone): string { + return substr_replace($phone, '******', 3, 6 ); + } +} + +/** + * 身份证号验证 + * @param $id + * @return bool + */ +if ( !function_exists('cc_is_id_card') ) { + function cc_is_id_card($id): bool { + $id = strtoupper($id); + $regx = "/(^\d{15}$)|(^\d{17}([0-9]|X)$)/"; + $arr_split = array(); + if (!preg_match($regx, $id)) { + return FALSE; + } + if (15 == strlen($id)) //检查15位 + { + $regx = "/^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/"; + @preg_match($regx, $id, $arr_split); + //检查生日日期是否正确 + $dtm_birth = "19" . $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4]; + if (!strtotime($dtm_birth)) { + return FALSE; + } else { + return TRUE; + } + } else { //检查18位 + $regx = "/^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/"; + @preg_match($regx, $id, $arr_split); + $dtm_birth = $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4]; + if (!strtotime($dtm_birth)) //检查生日日期是否正确 + { + return FALSE; + } else { + //检验18位身份证的校验码是否正确。 + //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。 + $arr_int = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); + $arr_ch = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); + $sign = 0; + for ($i = 0; $i < 17; $i++) { + $b = (int) $id[$i]; + $w = $arr_int[$i]; + $sign += $b * $w; + } + $n = $sign % 11; + $val_num = $arr_ch[$n]; + if ($val_num != substr($id, 17, 1)) { + return FALSE; + } else { + return TRUE; + } + } + } + } +} + +/** + * 分割数字 + */ +if (!function_exists('money_format')) { + function money_format($number) { + return preg_replace("/(?=\B(\d{3})+$)/", ',', $number); + } +} + +/** + * 密码加密处理 + * @param $password + * @return string + */ +if (!function_exists('ase_password')) { + function ase_password($password): string + { + return sha1($password. config('cc.configs.ase.slate')); + } +} + +// 获取当前项目启动的地址 +if (!function_exists('cc_get_project_url')) { + function cc_get_project_url(): string + { + $url = config('cc.configs.project_url'); + if (empty($url)) { + $url = request()->root(true); + } + return $url; + } +} + +/** + * 加密 + * @param $str + * @return mixed|string + */ +if(!function_exists('ase_encode')) { + function ase_encode($str) + { + if (empty($str)) return $str; + return base64_encode(\Illuminate\Support\Str::random(config('ase.len')). base64_encode($str)); + } +} + +/** + * 解密 + * @param $str + * @return false|string + */ +if (!function_exists('ase_decode')) { + function ase_decode($str): bool|string + { + if (empty($str)) return $str?? ''; + $result = base64_decode($str); + $result = base64_decode(substr($result, config('ase.len'))); + $pattern = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\xFF]|[\x{E000}-\x{F8FF}]/u'; + if (preg_match($pattern, $result)) return $str; + return $result; + } +} + + +/** + * 获取选中的时间段有几天 + * + * @param $startTime + * @param $endTime + * @return array + */ +if (!function_exists('get_day_list')) { + function get_day_list($startTime, $endTime): array + { + $day = []; + $currentTime = $startTime; + while ($currentTime <= $endTime) { + $day[] = date('m-d', $currentTime); + $currentTime = strtotime('+1 day', $currentTime); + } + return $day; + } +} + + + +/** + * 获取选中的时间段有几个月 + * + * @param $startTime + * @param $endTime + * @return array + */ +if (!function_exists('get_month_list')) { + function get_month_list($startTime, $endTime): array + { + $monthList = []; + $currentTime = $startTime; + while ($currentTime <= $endTime) { + $monthList[] = date('Y-m', $currentTime); + $currentTime = strtotime('+1 month', $currentTime); + } + return $monthList; + } +} + +/** + * 生成32位的uuid + * + * @return array + */ +if (!function_exists('gen_uuid')) { + function gen_uuid(): string + { + $chart = md5(uniqid(rand(), true)); + $hyphen = chr(45);// "-" + return substr($chart, 0, 8) . $hyphen + . substr($chart, 8, 4) . $hyphen + . substr($chart, 12, 4) . $hyphen + . substr($chart, 16, 4) . $hyphen + . substr($chart, 20, 12); + } +} + +/** + * 获取时间 + * + * @return array + */ +if (!function_exists('get_time')) { + function get_time($isString = false, $format = 'Y-m-d H:i:s'): string + { + return $isString === true ? date($format) : time(); + } +} diff --git a/routes/api.php b/routes/api.php new file mode 100644 index 00000000..e5301a0f --- /dev/null +++ b/routes/api.php @@ -0,0 +1,14 @@ +autoRouteRegister([ +]);