Feature: 权限优化 - 名片弹窗按等级展示资料,高管可查IP及归属地

This commit is contained in:
2026-02-27 11:29:48 +08:00
parent cef162738a
commit 731792fab6
4 changed files with 391 additions and 17 deletions

View File

@@ -30,6 +30,8 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redis;
use Stevebauman\Location\Facades\Location;
class UserController extends Controller
{
/**
@@ -37,23 +39,53 @@ class UserController extends Controller
*/
public function show(string $username): JsonResponse
{
$user = User::where('username', $username)->firstOrFail();
$targetUser = User::where('username', $username)->firstOrFail();
$operator = Auth::user();
// 基础公开信息
$data = [
'username' => $targetUser->username,
'sex' => $targetUser->sex,
'headface' => $targetUser->headface,
'usersf' => $targetUser->usersf,
'user_level' => $targetUser->user_level,
'qianming' => $targetUser->qianming,
'sign' => $targetUser->sign ?? '这个人很懒,什么都没留下。',
'created_at' => $targetUser->created_at->format('Y-m-d'),
];
// 只有等级不低于对方,或者自己看自己时,才能看到详细的财富、经验资产
if ($operator && ($operator->user_level >= $targetUser->user_level || $operator->id === $targetUser->id)) {
$data['exp_num'] = $targetUser->exp_num ?? 0;
$data['jjb'] = $targetUser->jjb ?? 0;
$data['meili'] = $targetUser->meili ?? 0;
}
// 拥有封禁IPlevel_banip或踢人以上权限的管理可以查看IP和归属地
$levelBanIp = (int) Sysparam::getValue('level_banip', '15');
if ($operator && $operator->user_level >= $levelBanIp) {
$data['last_ip'] = $targetUser->last_ip;
$data['login_ip'] = $targetUser->login_ip; // 假设表中存在 login_ip 记录本次IP若无则使用 last_ip 退化
// 解析归属地
$ipToLookup = $targetUser->login_ip ?: $targetUser->last_ip;
if ($ipToLookup) {
$position = Location::get($ipToLookup);
if ($position) {
$data['location'] = ($position->countryName === 'China' || $position->countryName === 'Local') ?
($position->regionName ?? '').' '.($position->cityName ?? '') :
$position->countryName;
} else {
$data['location'] = '未知区域';
}
} else {
$data['location'] = '暂无记录';
}
}
// 隐藏关键信息,只返回公开资料
return response()->json([
'status' => 'success',
'data' => [
'username' => $user->username,
'sex' => $user->sex,
'headface' => $user->headface,
'usersf' => $user->usersf,
'user_level' => $user->user_level,
'exp_num' => $user->exp_num ?? 0,
'jjb' => $user->jjb ?? 0,
'qianming' => $user->qianming,
'sign' => $user->sign ?? '这个人很懒,什么都没留下。',
'created_at' => $user->created_at->format('Y-m-d'),
],
'data' => $data,
]);
}

View File

@@ -15,7 +15,8 @@
"laravel/reverb": "^1.8",
"laravel/tinker": "^2.10.1",
"mews/captcha": "^3.4",
"predis/predis": "^3.4"
"predis/predis": "^3.4",
"stevebauman/location": "^7.6"
},
"require-dev": {
"fakerphp/faker": "^1.23",

316
composer.lock generated
View File

@@ -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": "b289aa628565e10fed1f7dc23db468e9",
"content-hash": "7c4fa193c06a7d429a4d8a423d2926d4",
"packages": [
{
"name": "brick/math",
@@ -265,6 +265,78 @@
],
"time": "2025-01-03T16:18:33+00:00"
},
{
"name": "composer/ca-bundle",
"version": "1.5.10",
"source": {
"type": "git",
"url": "https://github.com/composer/ca-bundle.git",
"reference": "961a5e4056dd2e4a2eedcac7576075947c28bf63"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/961a5e4056dd2e4a2eedcac7576075947c28bf63",
"reference": "961a5e4056dd2e4a2eedcac7576075947c28bf63",
"shasum": ""
},
"require": {
"ext-openssl": "*",
"ext-pcre": "*",
"php": "^7.2 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^8 || ^9",
"psr/log": "^1.0 || ^2.0 || ^3.0",
"symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\CaBundle\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
"keywords": [
"cabundle",
"cacert",
"certificate",
"ssl",
"tls"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/ca-bundle/issues",
"source": "https://github.com/composer/ca-bundle/tree/1.5.10"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
}
],
"time": "2025-12-08T15:06:51+00:00"
},
{
"name": "dflydev/dot-access-data",
"version": "v3.0.3",
@@ -756,6 +828,64 @@
],
"time": "2025-12-03T09:33:47+00:00"
},
{
"name": "geoip2/geoip2",
"version": "v3.3.0",
"source": {
"type": "git",
"url": "https://github.com/maxmind/GeoIP2-php.git",
"reference": "49fceddd694295e76e970a32848e03bb19e56b42"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/49fceddd694295e76e970a32848e03bb19e56b42",
"reference": "49fceddd694295e76e970a32848e03bb19e56b42",
"shasum": ""
},
"require": {
"ext-json": "*",
"maxmind-db/reader": "^1.13.0",
"maxmind/web-service-common": "~0.11",
"php": ">=8.1"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "3.*",
"phpstan/phpstan": "*",
"phpunit/phpunit": "^10.0",
"squizlabs/php_codesniffer": "4.*"
},
"type": "library",
"autoload": {
"psr-4": {
"GeoIp2\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Gregory J. Oschwald",
"email": "goschwald@maxmind.com",
"homepage": "https://www.maxmind.com/"
}
],
"description": "MaxMind GeoIP2 PHP API",
"homepage": "https://github.com/maxmind/GeoIP2-php",
"keywords": [
"IP",
"geoip",
"geoip2",
"geolocation",
"maxmind"
],
"support": {
"issues": "https://github.com/maxmind/GeoIP2-php/issues",
"source": "https://github.com/maxmind/GeoIP2-php/tree/v3.3.0"
},
"time": "2025-11-20T18:50:15+00:00"
},
{
"name": "graham-campbell/result-type",
"version": "v1.1.4",
@@ -2558,6 +2688,121 @@
],
"time": "2026-01-15T06:54:53+00:00"
},
{
"name": "maxmind-db/reader",
"version": "v1.13.1",
"source": {
"type": "git",
"url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git",
"reference": "2194f58d0f024ce923e685cdf92af3daf9951908"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/2194f58d0f024ce923e685cdf92af3daf9951908",
"reference": "2194f58d0f024ce923e685cdf92af3daf9951908",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"conflict": {
"ext-maxminddb": "<1.11.1 || >=2.0.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "3.*",
"phpstan/phpstan": "*",
"phpunit/phpunit": ">=8.0.0,<10.0.0",
"squizlabs/php_codesniffer": "4.*"
},
"suggest": {
"ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
"ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder",
"ext-maxminddb": "A C-based database decoder that provides significantly faster lookups",
"maxmind-db/reader-ext": "C extension for significantly faster IP lookups (install via PIE: pie install maxmind-db/reader-ext)"
},
"type": "library",
"autoload": {
"psr-4": {
"MaxMind\\Db\\": "src/MaxMind/Db"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Gregory J. Oschwald",
"email": "goschwald@maxmind.com",
"homepage": "https://www.maxmind.com/"
}
],
"description": "MaxMind DB Reader API",
"homepage": "https://github.com/maxmind/MaxMind-DB-Reader-php",
"keywords": [
"database",
"geoip",
"geoip2",
"geolocation",
"maxmind"
],
"support": {
"issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues",
"source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.13.1"
},
"time": "2025-11-21T22:24:26+00:00"
},
{
"name": "maxmind/web-service-common",
"version": "v0.11.1",
"source": {
"type": "git",
"url": "https://github.com/maxmind/web-service-common-php.git",
"reference": "c309236b5a5555b96cf560089ec3cead12d845d2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/c309236b5a5555b96cf560089ec3cead12d845d2",
"reference": "c309236b5a5555b96cf560089ec3cead12d845d2",
"shasum": ""
},
"require": {
"composer/ca-bundle": "^1.0.3",
"ext-curl": "*",
"ext-json": "*",
"php": ">=8.1"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "3.*",
"phpstan/phpstan": "*",
"phpunit/phpunit": "^10.0",
"squizlabs/php_codesniffer": "4.*"
},
"type": "library",
"autoload": {
"psr-4": {
"MaxMind\\Exception\\": "src/Exception",
"MaxMind\\WebService\\": "src/WebService"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Gregory Oschwald",
"email": "goschwald@maxmind.com"
}
],
"description": "Internal MaxMind Web Service API",
"homepage": "https://github.com/maxmind/web-service-common-php",
"support": {
"issues": "https://github.com/maxmind/web-service-common-php/issues",
"source": "https://github.com/maxmind/web-service-common-php/tree/v0.11.1"
},
"time": "2026-01-13T17:56:03+00:00"
},
{
"name": "mews/captcha",
"version": "3.4.7",
@@ -4715,6 +4960,75 @@
],
"time": "2024-06-11T12:45:25+00:00"
},
{
"name": "stevebauman/location",
"version": "v7.6.2",
"source": {
"type": "git",
"url": "https://github.com/stevebauman/location.git",
"reference": "2f7686b685b924f193d6a6b82074861b8cc5aa3a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/stevebauman/location/zipball/2f7686b685b924f193d6a6b82074861b8cc5aa3a",
"reference": "2f7686b685b924f193d6a6b82074861b8cc5aa3a",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"geoip2/geoip2": "^2.0|^3.0",
"guzzlehttp/guzzle": "^7.0",
"illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0",
"php": ">=8.1"
},
"require-dev": {
"mockery/mockery": "^1.0",
"orchestra/testbench": "^6.0|^7.0|^8.0|^9.0|^10.0",
"pestphp/pest": "^1.0|^2.0|^3.7"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Location": "Stevebauman\\Location\\Facades\\Location"
},
"providers": [
"Stevebauman\\Location\\LocationServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Stevebauman\\Location\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Steve Bauman",
"email": "steven_bauman@outlook.com"
}
],
"description": "Retrieve a user's location by their IP Address",
"keywords": [
"IP",
"geo",
"geo-location",
"geoip",
"laravel",
"location",
"php"
],
"support": {
"issues": "https://github.com/stevebauman/location/issues",
"source": "https://github.com/stevebauman/location/tree/v7.6.2"
},
"time": "2026-02-11T16:06:17+00:00"
},
{
"name": "symfony/clock",
"version": "v8.0.0",

View File

@@ -317,7 +317,34 @@
</div>
</div>
</div>
<div class="profile-detail" x-text="userInfo.sign || '这家伙很懒,什么也没留下'"></div>
{{-- 详细信息区 (等级高看等级低,或自己看自己时才有这些字段) --}}
<div x-show="userInfo.exp_num !== undefined"
style="margin-top: 12px; padding: 10px; background: #f8fafc; border-radius: 8px; font-size: 12px; color: #475569; display: grid; grid-template-columns: 1fr 1fr; gap: 8px;">
<div><span style="color: #94a3b8;">经验:</span><span x-text="userInfo.exp_num"
style="font-weight: 600; color: #4f46e5;"></span></div>
<div><span style="color: #94a3b8;">金币:</span><span x-text="userInfo.jjb"
style="font-weight: 600; color: #d97706;"></span></div>
<div><span style="color: #94a3b8;">魅力:</span><span x-text="userInfo.meili"
style="font-weight: 600; color: #db2777;"></span></div>
</div>
{{-- 管理员可见区域 (IP 归属地) --}}
<div x-show="userInfo.last_ip !== undefined"
style="margin-top: 8px; padding: 8px 10px; background: #fee2e2; border: 1px dashed #fca5a5; border-radius: 8px; font-size: 11px; color: #991b1b;">
<div style="font-weight: bold; margin-bottom: 4px; display: flex; align-items: center; gap: 4px;">
<span>🛡️</span> 管理员视野</div>
<div style="display: flex; flex-direction: column; gap: 3px;">
<div><span style="opacity: 0.8;">主要IP</span><span x-text="userInfo.last_ip || '无'"></span>
</div>
<div><span style="opacity: 0.8;">本次IP</span><span x-text="userInfo.login_ip || '无'"></span>
</div>
<div><span style="opacity: 0.8;">归属地:</span><span x-text="userInfo.location || '未知'"></span>
</div>
</div>
</div>
<div class="profile-detail" x-text="userInfo.sign || '这家伙很懒,什么也没留下'" style="margin-top: 12px;"></div>
</div>
{{-- 普通操作按钮 --}}