Feat: 切换IP归属地解析引擎为ip2region,原生返回中文省市运营商,精度到市级
This commit is contained in:
@@ -30,7 +30,7 @@ use Illuminate\Support\Facades\Auth;
|
|||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Redis;
|
use Illuminate\Support\Facades\Redis;
|
||||||
|
|
||||||
use Stevebauman\Location\Facades\Location;
|
|
||||||
|
|
||||||
class UserController extends Controller
|
class UserController extends Controller
|
||||||
{
|
{
|
||||||
@@ -67,45 +67,27 @@ class UserController extends Controller
|
|||||||
$data['last_ip'] = $targetUser->last_ip;
|
$data['last_ip'] = $targetUser->last_ip;
|
||||||
$data['login_ip'] = $targetUser->login_ip; // 假设表中存在 login_ip 记录本次IP,若无则使用 last_ip 退化
|
$data['login_ip'] = $targetUser->login_ip; // 假设表中存在 login_ip 记录本次IP,若无则使用 last_ip 退化
|
||||||
|
|
||||||
// 解析归属地 (防崩溃处理:检查服务提供者是否已安装)
|
// 解析归属地:使用 ip2region 离线库,直接返回原生中文(省|市|ISP)
|
||||||
// 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;
|
|
||||||
|
|
||||||
$ipToLookup = $targetUser->login_ip ?: $targetUser->last_ip;
|
$ipToLookup = $targetUser->login_ip ?: $targetUser->last_ip;
|
||||||
if ($ipToLookup) {
|
if ($ipToLookup) {
|
||||||
if (class_exists('\Stevebauman\Location\Facades\Location')) {
|
|
||||||
try {
|
try {
|
||||||
$position = Location::get($ipToLookup);
|
$ip2r = new \Ip2Region(database_path('ip2region/ip2region.xdb'));
|
||||||
if ($position) {
|
$raw = $ip2r->search($ipToLookup); // 格式: 国家|省份|城市|运营商
|
||||||
$isChinaOrLocal = in_array($position->countryCode ?? '', ['CN', 'TW', 'HK', 'MO'])
|
|
||||||
|| $position->countryName === 'Local';
|
if ($raw) {
|
||||||
if ($isChinaOrLocal) {
|
$parts = explode('|', $raw);
|
||||||
$region = $tr($position->regionName ?? '');
|
// 去掉 "0" 占位符并组合省市
|
||||||
$city = $tr($position->cityName ?? '');
|
$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 : ''));
|
$data['location'] = trim($region . ($region !== $city ? ' ' . $city : ''));
|
||||||
} else {
|
} else {
|
||||||
$data['location'] = $tr($position->countryName ?? '未知区域');
|
$data['location'] = $country ?: '未知区域';
|
||||||
}
|
|
||||||
if (empty($data['location'])) {
|
|
||||||
$data['location'] = '未知区域';
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$data['location'] = '未知区域';
|
$data['location'] = '未知区域';
|
||||||
@@ -113,9 +95,6 @@ class UserController extends Controller
|
|||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$data['location'] = '解析失败';
|
$data['location'] = '解析失败';
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$data['location'] = '未安装IP库';
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$data['location'] = '暂无记录';
|
$data['location'] = '暂无记录';
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -17,7 +17,8 @@
|
|||||||
"laravel/tinker": "^2.10.1",
|
"laravel/tinker": "^2.10.1",
|
||||||
"mews/captcha": "^3.4",
|
"mews/captcha": "^3.4",
|
||||||
"predis/predis": "^3.4",
|
"predis/predis": "^3.4",
|
||||||
"stevebauman/location": "^7.6"
|
"stevebauman/location": "^7.6",
|
||||||
|
"zoujingli/ip2region": "^3.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
|
|||||||
Generated
+75
-1
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "9ce82fd8935af3aa9c257758c8640c53",
|
"content-hash": "e1aec7cecd4daa266d448c0e106408c6",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
@@ -7733,6 +7733,80 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-11-21T01:49:47+00:00"
|
"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": [
|
"packages-dev": [
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user