feat: 增加自定义头像上传、自动压缩与自动清理功能,统一全站头像路径读取逻辑

This commit is contained in:
2026-03-12 15:26:54 +08:00
parent ec95d69e92
commit 78564e2a1d
57 changed files with 569 additions and 350 deletions
+74 -3
View File
@@ -35,7 +35,10 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;
use Intervention\Image\Drivers\Gd\Driver;
use Intervention\Image\ImageManager;
class ChatController extends Controller
{
@@ -683,9 +686,12 @@ class ChatController extends Controller
return response()->json(['status' => 'error', 'message' => '头像文件不存在'], 422);
}
// 更新用户头像
$user->usersf = $headface;
$user->save();
// 更新前如为自定义头像,将其从磁盘删除,节约空间
if ($user->usersf !== $headface) {
$user->deleteCustomAvatar();
$user->usersf = $headface;
$user->save();
}
// 将新头像同步到 Redis 在线用户列表中(所有房间)
// 通过更新 Redis 的用户信息,使得其他用户和自己刷新后都能看到新头像
@@ -710,6 +716,71 @@ class ChatController extends Controller
]);
}
/**
* 上传自定义头像
*/
public function uploadAvatar(Request $request): JsonResponse
{
$request->validate([
'file' => 'required|image|mimes:jpeg,png,jpg,gif,webp|max:2048',
]);
$user = Auth::user();
if (! $user) {
return response()->json(['status' => 'error', 'message' => '未登录'], 401);
}
$file = $request->file('file');
try {
$manager = new ImageManager(new Driver);
$image = $manager->read($file);
// 裁剪正方形并压缩为 112x112
$image->cover(112, 112);
// 生成相对路径
$filename = 'custom_'.$user->id.'_'.time().'.'.$file->extension();
$path = 'avatars/'.$filename;
// 保存以高质量 JPG 或原格式
Storage::disk('public')->put($path, (string) $image->encode());
$dbValue = 'storage/'.$path;
// 更新前如为自定义头像,将其从磁盘删除,节约空间
if ($user->usersf !== $dbValue) {
$user->deleteCustomAvatar();
$user->usersf = $dbValue;
$user->save();
}
// 同步 Redis 状态
$superLevel = (int) Sysparam::getValue('superlevel', '100');
$rooms = $this->chatState->getUserRooms($user->username);
foreach ($rooms as $roomId) {
$this->chatState->userJoin((int) $roomId, $user->username, [
'level' => $user->user_level,
'sex' => $user->sex,
'headface' => $user->headface, // Use accessor
'vip_icon' => $user->vipIcon(),
'vip_name' => $user->vipName(),
'vip_color' => $user->isVip() ? ($user->vipLevel?->color ?? '') : '',
'is_admin' => $user->user_level >= $superLevel,
]);
}
return response()->json([
'status' => 'success',
'message' => '头像上传成功!',
'headface' => $user->headface,
]);
} catch (\Exception $e) {
return response()->json(['status' => 'error', 'message' => '上传失败: '.$e->getMessage()], 500);
}
}
/**
* 设置房间公告/祝福语(滚动显示在聊天室顶部)
* 需要房间主人或等级达到 level_announcement 配置值