feat: 任命/撤销通知系统 + 用户名片UI优化

- 任命/撤销事件增加 type 字段区分类型
- 任命:全屏礼花 + 紫色弹窗 + 紫色系统消息
- 撤销:灰色弹窗 + 灰色系统消息,无礼花
- 消息分发:操作者/被操作者显示在私聊面板,其他人显示在公屏
- 系统消息加随机鼓励语(各5条轮换)
- ChatStateService 修复 Redis key 前缀扫描问题(getAllActiveRoomIds)
- 用户名片折叠优化:管理员视野、职务履历均可折叠
- 管理操作 + 职务操作合并为「🔧 管理操作」折叠区
- 悄悄话改为「🎁 送礼物」按钮,礼物面板内联展开
This commit is contained in:
2026-02-28 23:44:38 +08:00
parent a599047cf0
commit 5f30220609
80 changed files with 8579 additions and 473 deletions
+31 -14
View File
@@ -30,8 +30,6 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redis;
class UserController extends Controller
{
/**
@@ -43,6 +41,7 @@ class UserController extends Controller
$operator = Auth::user();
// 基础公开信息
$activePosition = $targetUser->activePosition?->load('position.department')->position;
$data = [
'username' => $targetUser->username,
'sex' => $targetUser->sex,
@@ -52,6 +51,10 @@ class UserController extends Controller
'qianming' => $targetUser->qianming,
'sign' => $targetUser->sign ?? '这个人很懒,什么都没留下。',
'created_at' => $targetUser->created_at->format('Y-m-d'),
// 在职职务(供名片弹窗任命/撤销判断)
'position_name' => $activePosition?->name ?? '',
'position_icon' => $activePosition?->icon ?? '',
'department_name' => $activePosition?->department?->name ?? '',
];
// 只有等级不低于对方,或者自己看自己时,才能看到详细的财富、经验资产
@@ -61,6 +64,20 @@ class UserController extends Controller
$data['meili'] = $targetUser->meili ?? 0;
}
// 职务履历(所有任职记录,按任命时间倒序;positions() 关系已含 with
$data['position_history'] = $targetUser->positions
->map(fn ($up) => [
'position_icon' => $up->position?->icon ?? '',
'position_name' => $up->position?->name ?? '',
'department_name' => $up->position?->department?->name ?? '',
'appointed_at' => $up->appointed_at?->format('Y-m-d'),
'revoked_at' => $up->revoked_at?->format('Y-m-d'),
'is_active' => $up->is_active,
'duration_days' => $up->duration_days,
])
->values()
->all();
// 拥有封禁IPlevel_banip)或踢人以上权限的管理,可以查看IP和归属地
$levelBanIp = (int) Sysparam::getValue('level_banip', '15');
if ($operator && $operator->user_level >= $levelBanIp) {
@@ -72,24 +89,24 @@ class UserController extends Controller
if ($ipToLookup) {
try {
// 不传路径,使用 zoujingli/ip2region 包自带的内置数据库
$ip2r = new \Ip2Region();
$ip2r = new \Ip2Region;
$info = $ip2r->getIpInfo($ipToLookup);
if ($info) {
$country = $info['country'] ?? '';
$country = $info['country'] ?? '';
$province = $info['province'] ?? '';
$city = $info['city'] ?? '';
$city = $info['city'] ?? '';
// 过滤掉占位符 "0"
$province = ($province === '0') ? '' : $province;
$city = ($city === '0') ? '' : $city;
$city = ($city === '0') ? '' : $city;
if ($country === '中国') {
$data['location'] = trim($province . ($province !== $city ? ' ' . $city : ''));
$data['location'] = trim($province.($province !== $city ? ' '.$city : ''));
} else {
$data['location'] = $country ?: '未知区域';
}
if (empty($data['location'])) {
$data['location'] = '未知区域';
}
@@ -117,7 +134,7 @@ class UserController extends Controller
{
$user = Auth::user();
$data = $request->validated();
// 当用户试图更新邮箱,并且新邮箱不等于当前旧邮箱时启动验证码拦截
if (isset($data['email']) && $data['email'] !== $user->email) {
// 首先判断系统开关是否开启,没开启直接禁止修改邮箱
@@ -131,10 +148,10 @@ class UserController extends Controller
}
// 获取缓存的验证码
$codeKey = 'email_verify_code_' . $user->id . '_' . $data['email'];
$codeKey = 'email_verify_code_'.$user->id.'_'.$data['email'];
$cachedCode = \Illuminate\Support\Facades\Cache::get($codeKey);
if (!$cachedCode || $cachedCode != $emailCode) {
if (! $cachedCode || $cachedCode != $emailCode) {
return response()->json(['status' => 'error', 'message' => '验证码不正确或已过期(有效期5分钟),请重新获取。'], 422);
}