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
+48 -5
View File
@@ -90,18 +90,61 @@ class User extends Authenticatable
* 头像文件名访问器
*
* ASP 系统的头像文件名存储在 usersf 字段中(如 "75.gif"),
* 但项目中各处通过 $user->headface 来引用头像
* accessor headface 属性映射到 usersf 字段,保持代码一致性
* 同时也支持用户自定义上传的头像,保存在 Laravel Storage public 磁盘下
* accessor headface 属性映射到 usersf 字段,如果包含 storage/ 则当作独立路径,自动转换旧版后缀小写
*/
protected function headface(): Attribute
{
return Attribute::make(
// 自动将后缀转小写,兼容数据库中的 .GIF 大写存量
get: fn () => strtolower($this->usersf ?: '1.gif'),
set: fn (string $value) => ['usersf' => strtolower($value)],
get: function () {
$val = $this->usersf ?: '1.gif';
if (str_starts_with($val, 'storage/')) {
return $val;
}
// 仅对非 storage 下的旧头像做小写处理,兼容旧库数据
return strtolower($val);
},
set: function ($value) {
if (str_starts_with($value, 'storage/')) {
return tap($value, fn () => $this->attributes['usersf'] = $value);
}
return tap(strtolower($value), fn () => $this->attributes['usersf'] = strtolower($value));
}
);
}
/**
* 获取带前缀的完整头像 URL
* 避免前端多处硬编码 '/images/headface/'
*/
protected function headfaceUrl(): Attribute
{
return Attribute::make(
get: function () {
$hf = $this->headface;
if (str_starts_with((string) $hf, 'storage/')) {
return '/'.$hf;
}
return '/images/headface/'.$hf;
}
);
}
/**
* 如果当前头像是自定义上传的图片,则从本地存储中删除此文件
*/
public function deleteCustomAvatar(): void
{
$hf = (string) $this->usersf;
if (str_starts_with($hf, 'storage/')) {
$path = substr($hf, 8); // 去除 'storage/' 前缀
\Illuminate\Support\Facades\Storage::disk('public')->delete($path);
}
}
/**
* 关联:用户所属的 VIP 会员等级
*/