Files
FendxPHP/app/Vo/UserVo.php
Lawson 2782d765fb feat(database): 添加用户角色权限系统及相关监控功能
- 创建用户表(users)包含基本信息和认证字段
- 创建角色表(roles)用于权限控制
- 创建权限表(permissions)定义系统权限
- 创建用户角色关联表(user_roles)建立用户与角色关系
- 创建角色权限关联表(role_permissions)建立角色与权限关系
- 创建迁移记录表(migrations)追踪数据库变更
- 添加AdminController提供管理员面板功能
- 实现系统监控、配置管理、缓存清理等功能
- 添加AOP切面编程支持的各种通知类型
- 实现告警管理AlertManager支持多渠道告警
- 添加文档注解接口规范
2026-04-08 17:00:28 +08:00

457 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace App\Vo;
use App\Dto\UserDto;
/**
* 用户前端展示对象
*/
class UserVo
{
private ?int $id = null;
private string $username = '';
private string $email = '';
private string $nickname = '';
private string $phone = '';
private string $avatar = '';
private ?int $status = null;
private ?string $statusText = null;
private ?string $roleName = null;
private ?string $createdAt = null;
private ?string $updatedAt = null;
private ?string $lastLoginAt = null;
private array $permissions = [];
private array $roles = [];
private array $extra = [];
public function __construct(UserDto $userDto = null)
{
if ($userDto) {
$this->fromDto($userDto);
}
}
public function getId(): ?int
{
return $this->id;
}
public function setId(int $id): self
{
$this->id = $id;
return $this;
}
public function getUsername(): string
{
return $this->username;
}
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
public function getEmail(): string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getNickname(): string
{
return $this->nickname;
}
public function setNickname(string $nickname): self
{
$this->nickname = $nickname;
return $this;
}
public function getPhone(): string
{
return $this->phone;
}
public function setPhone(string $phone): self
{
$this->phone = $phone;
return $this;
}
public function getAvatar(): string
{
return $this->avatar;
}
public function setAvatar(string $avatar): self
{
$this->avatar = $avatar;
return $this;
}
public function getStatus(): ?int
{
return $this->status;
}
public function setStatus(int $status): self
{
$this->status = $status;
$this->statusText = $this->getStatusText($status);
return $this;
}
public function getStatusText(): ?string
{
return $this->statusText;
}
public function getRoleName(): ?string
{
return $this->roleName;
}
public function setRoleName(string $roleName): self
{
$this->roleName = $roleName;
return $this;
}
public function getCreatedAt(): ?string
{
return $this->createdAt;
}
public function setCreatedAt(string $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getUpdatedAt(): ?string
{
return $this->updatedAt;
}
public function setUpdatedAt(string $updatedAt): self
{
$this->updatedAt = $updatedAt;
return $this;
}
public function getLastLoginAt(): ?string
{
return $this->lastLoginAt;
}
public function setLastLoginAt(string $lastLoginAt): self
{
$this->lastLoginAt = $lastLoginAt;
return $this;
}
public function getPermissions(): array
{
return $this->permissions;
}
public function setPermissions(array $permissions): self
{
$this->permissions = $permissions;
return $this;
}
public function getRoles(): array
{
return $this->roles;
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
public function getExtra(): array
{
return $this->extra;
}
public function setExtra(array $extra): self
{
$this->extra = $extra;
return $this;
}
/**
* 添加额外信息
*/
public function addExtra(string $key, mixed $value): self
{
$this->extra[$key] = $value;
return $this;
}
/**
* 从DTO转换
*/
public function fromDto(UserDto $dto): self
{
$this->id = $dto->getId();
$this->username = $dto->getUsername();
$this->email = $dto->getEmail();
$this->nickname = $dto->getNickname();
$this->phone = $dto->getPhone();
$this->avatar = $dto->getAvatar();
$this->status = $dto->getStatus();
$this->statusText = $this->getStatusText($this->status);
$this->roleName = $dto->getRoleName();
$this->permissions = $dto->getPermissions();
$this->roles = $dto->getRoles();
// 格式化日期
if ($dto->getCreatedAt()) {
$this->createdAt = $dto->getCreatedAt()->format('Y-m-d H:i:s');
}
if ($dto->getUpdatedAt()) {
$this->updatedAt = $dto->getUpdatedAt()->format('Y-m-d H:i:s');
}
if ($dto->getLastLoginAt()) {
$this->lastLoginAt = $dto->getLastLoginAt()->format('Y-m-d H:i:s');
}
return $this;
}
/**
* 获取状态文本
*/
private function getStatusText(int $status): string
{
return match ($status) {
1 => '正常',
2 => '禁用',
3 => '待审核',
0 => '删除',
default => '未知'
};
}
/**
* 获取显示名称(优先使用昵称)
*/
public function getDisplayName(): string
{
return !empty($this->nickname) ? $this->nickname : $this->username;
}
/**
* 获取头像URL默认头像
*/
public function getAvatarUrl(): string
{
if (!empty($this->avatar)) {
return $this->avatar;
}
// 默认头像
return 'https://via.placeholder.com/100x100?text=' . urlencode(substr($this->getDisplayName(), 0, 1));
}
/**
* 获取手机号显示格式隐藏中间4位
*/
public function getPhoneDisplay(): string
{
if (empty($this->phone)) {
return '';
}
return substr($this->phone, 0, 3) . '****' . substr($this->phone, -4);
}
/**
* 获取邮箱显示格式(隐藏部分字符)
*/
public function getEmailDisplay(): string
{
if (empty($this->email)) {
return '';
}
$parts = explode('@', $this->email);
if (count($parts) !== 2) {
return $this->email;
}
$username = $parts[0];
$domain = $parts[1];
if (strlen($username) <= 3) {
$maskedUsername = str_repeat('*', strlen($username));
} else {
$maskedUsername = substr($username, 0, 2) . str_repeat('*', strlen($username) - 2);
}
return $maskedUsername . '@' . $domain;
}
/**
* 检查是否在线
*/
public function isOnline(): bool
{
if (!$this->lastLoginAt) {
return false;
}
$lastLoginTime = strtotime($this->lastLoginAt);
$onlineThreshold = 30 * 60; // 30分钟内在线
return (time() - $lastLoginTime) < $onlineThreshold;
}
/**
* 检查是否活跃用户
*/
public function isActive(): bool
{
return $this->status === 1;
}
/**
* 获取用户标签
*/
public function getTags(): array
{
$tags = [];
if ($this->isActive()) {
$tags[] = ['text' => '正常', 'type' => 'success'];
} else {
$tags[] = ['text' => $this->statusText, 'type' => 'danger'];
}
if ($this->isOnline()) {
$tags[] = ['text' => '在线', 'type' => 'primary'];
}
if (!empty($this->roleName)) {
$tags[] = ['text' => $this->roleName, 'type' => 'info'];
}
return $tags;
}
/**
* 转换为数组用于API响应
*/
public function toArray(): array
{
return [
'id' => $this->id,
'username' => $this->username,
'email' => $this->email,
'nickname' => $this->nickname,
'phone' => $this->phone,
'avatar' => $this->avatar,
'status' => $this->status,
'status_text' => $this->statusText,
'role_name' => $this->roleName,
'created_at' => $this->createdAt,
'updated_at' => $this->updatedAt,
'last_login_at' => $this->lastLoginAt,
'permissions' => $this->permissions,
'roles' => $this->roles,
'extra' => $this->extra,
// 计算属性
'display_name' => $this->getDisplayName(),
'avatar_url' => $this->getAvatarUrl(),
'phone_display' => $this->getPhoneDisplay(),
'email_display' => $this->getEmailDisplay(),
'is_online' => $this->isOnline(),
'is_active' => $this->isActive(),
'tags' => $this->getTags(),
];
}
/**
* 转换为精简数组(用于列表显示)
*/
public function toSimpleArray(): array
{
return [
'id' => $this->id,
'username' => $this->username,
'nickname' => $this->nickname,
'avatar' => $this->getAvatarUrl(),
'status' => $this->status,
'status_text' => $this->statusText,
'role_name' => $this->roleName,
'is_online' => $this->isOnline(),
'tags' => $this->getTags(),
];
}
/**
* 转换为公开数组(隐藏敏感信息)
*/
public function toPublicArray(): array
{
return [
'id' => $this->id,
'username' => $this->username,
'nickname' => $this->nickname,
'avatar' => $this->getAvatarUrl(),
'role_name' => $this->roleName,
'created_at' => $this->createdAt,
];
}
/**
* 批量转换DTO数组为VO数组
*/
public static function fromDtoArray(array $dtos): array
{
return array_map(fn($dto) => new self($dto), $dtos);
}
/**
* 批量转换为数组
*/
public static function toArrayBatch(array $vos, string $type = 'full'): array
{
return array_map(function($vo) use ($type) {
return match ($type) {
'simple' => $vo->toSimpleArray(),
'public' => $vo->toPublicArray(),
default => $vo->toArray()
};
}, $vos);
}
}