diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index f2a4f91..a7fdb29 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -30,7 +30,7 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Redis; -use Stevebauman\Location\Facades\Location; + class UserController extends Controller { @@ -67,54 +67,33 @@ class UserController extends Controller $data['last_ip'] = $targetUser->last_ip; $data['login_ip'] = $targetUser->login_ip; // 假设表中存在 login_ip 记录本次IP,若无则使用 last_ip 退化 - // 解析归属地 (防崩溃处理:检查服务提供者是否已安装) - // GeoLite2 本地 .mmdb 仅返回英文,这里使用内置翻译表转为中文 - $locationMap = [ - 'China' => '中国', 'Beijing' => '北京', 'Shanghai' => '上海', - 'Tianjin' => '天津', 'Chongqing' => '重庆', 'Hebei' => '河北', - 'Shanxi' => '山西', 'Liaoning' => '辽宁', 'Jilin' => '吉林', - 'Heilongjiang' => '黑龙江', 'Jiangsu' => '江苏', 'Zhejiang' => '浙江', - 'Anhui' => '安徽', 'Fujian' => '福建', 'Jiangxi' => '江西', - 'Shandong' => '山东', 'Henan' => '河南', 'Hubei' => '湖北', - 'Hunan' => '湖南', 'Guangdong' => '广东', 'Hainan' => '海南', - 'Sichuan' => '四川', 'Guizhou' => '贵州', 'Yunnan' => '云南', - 'Shaanxi' => '陕西', 'Gansu' => '甘肃', 'Qinghai' => '青海', - 'Taiwan' => '台湾', 'Inner Mongolia' => '内蒙古', 'Guangxi' => '广西', - 'Tibet' => '西藏', 'Ningxia' => '宁夏', 'Xinjiang' => '新疆', - 'Hong Kong' => '香港', 'Macau' => '澳门', - 'United States' => '美国', 'Japan' => '日本', 'South Korea' => '韩国', - 'United Kingdom' => '英国', 'France' => '法国', 'Germany' => '德国', - 'Russia' => '俄罗斯', 'Canada' => '加拿大', 'Australia' => '澳大利亚', - 'Singapore' => '新加坡', - ]; - $tr = fn(string $name): string => $locationMap[$name] ?? $name; - + // 解析归属地:使用 ip2region 离线库,直接返回原生中文(省|市|ISP) $ipToLookup = $targetUser->login_ip ?: $targetUser->last_ip; if ($ipToLookup) { - if (class_exists('\Stevebauman\Location\Facades\Location')) { - try { - $position = Location::get($ipToLookup); - if ($position) { - $isChinaOrLocal = in_array($position->countryCode ?? '', ['CN', 'TW', 'HK', 'MO']) - || $position->countryName === 'Local'; - if ($isChinaOrLocal) { - $region = $tr($position->regionName ?? ''); - $city = $tr($position->cityName ?? ''); - $data['location'] = trim($region . ($region !== $city ? ' ' . $city : '')); - } else { - $data['location'] = $tr($position->countryName ?? '未知区域'); - } - if (empty($data['location'])) { - $data['location'] = '未知区域'; - } + try { + $ip2r = new \Ip2Region(database_path('ip2region/ip2region.xdb')); + $raw = $ip2r->search($ipToLookup); // 格式: 国家|省份|城市|运营商 + + if ($raw) { + $parts = explode('|', $raw); + // 去掉 "0" 占位符并组合省市 + $parts = array_filter($parts, fn($p) => $p !== '0' && $p !== ''); + $parts = array_values($parts); + $country = $parts[0] ?? ''; + $region = $parts[1] ?? ''; + $city = $parts[2] ?? ''; + + if ($country === '中国') { + // 国内:显示 省份 城市(如果省市不同则都显示) + $data['location'] = trim($region . ($region !== $city ? ' ' . $city : '')); } else { - $data['location'] = '未知区域'; + $data['location'] = $country ?: '未知区域'; } - } catch (\Exception $e) { - $data['location'] = '解析失败'; + } else { + $data['location'] = '未知区域'; } - } else { - $data['location'] = '未安装IP库'; + } catch (\Exception $e) { + $data['location'] = '解析失败'; } } else { $data['location'] = '暂无记录'; diff --git a/composer.json b/composer.json index 5921032..f07eeee 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ "laravel/tinker": "^2.10.1", "mews/captcha": "^3.4", "predis/predis": "^3.4", - "stevebauman/location": "^7.6" + "stevebauman/location": "^7.6", + "zoujingli/ip2region": "^3.0" }, "require-dev": { "fakerphp/faker": "^1.23", diff --git a/composer.lock b/composer.lock index 695f7bc..85ca94b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9ce82fd8935af3aa9c257758c8640c53", + "content-hash": "e1aec7cecd4daa266d448c0e106408c6", "packages": [ { "name": "brick/math", @@ -7733,6 +7733,80 @@ } ], "time": "2024-11-21T01:49:47+00:00" + }, + { + "name": "zoujingli/ip2region", + "version": "v3.0.11", + "source": { + "type": "git", + "url": "https://github.com/zoujingli/ip2region.git", + "reference": "f8285aea7d88a8804d89c6cbb2f4a7ca0a622206" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zoujingli/ip2region/zipball/f8285aea7d88a8804d89c6cbb2f4a7ca0a622206", + "reference": "f8285aea7d88a8804d89c6cbb2f4a7ca0a622206", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "suggest": { + "ext-opcache": "启用 OPcache 以获得更好的性能" + }, + "bin": [ + "bin/ip2down" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "files": [ + "src/common.php" + ], + "psr-4": { + "ip2region\\": "src/ip2region/" + }, + "classmap": [ + "src/Ip2Region.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Anyon", + "email": "zoujingli@qq.com", + "homepage": "https://thinkadmin.top" + } + ], + "description": "ip2region v3.0 for PHP - 企业级 IP 地理位置查询库,支持 IPv4 和 IPv6,多种缓存策略,零依赖,开箱即用", + "homepage": "https://github.com/zoujingli/Ip2Region", + "keywords": [ + "IP", + "Ip2Region", + "composer", + "geolocation", + "ipv4", + "ipv6", + "location", + "php", + "企业级", + "智能加载", + "缓存策略", + "零依赖", + "高性能" + ], + "support": { + "issues": "https://github.com/zoujingli/ip2region/issues", + "source": "https://github.com/zoujingli/ip2region/tree/v3.0.11" + }, + "time": "2026-01-17T01:26:46+00:00" } ], "packages-dev": [ diff --git a/database/ip2region/ip2region.xdb b/database/ip2region/ip2region.xdb new file mode 100644 index 0000000..fe850c2 --- /dev/null +++ b/database/ip2region/ip2region.xdb @@ -0,0 +1,1454 @@ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +