mirror of
https://devops.lemonos.cn/lawson/FendxPHP.git
synced 2026-06-15 23:12:49 +08:00
457 lines
10 KiB
PHP
457 lines
10 KiB
PHP
|
|
<?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);
|
|||
|
|
}
|
|||
|
|
}
|