Files
laravel_swoole/app/Services/Auth/UserService.php
2026-02-18 22:28:08 +08:00

415 lines
12 KiB
PHP

<?php
namespace App\Services\Auth;
use App\Models\Auth\User;
use App\Models\System\Notification;
use App\Services\System\NotificationService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\Auth\UserExport;
use App\Imports\Auth\UserImport;
use App\Jobs\Auth\UserImportJob;
use App\Jobs\Auth\UserExportJob;
class UserService
{
protected $departmentService;
protected $notificationService;
public function __construct(DepartmentService $departmentService, NotificationService $notificationService)
{
$this->departmentService = $departmentService;
$this->notificationService = $notificationService;
}
/**
* 获取当前登录用户ID
*/
protected function getCurrentUserId(): int
{
return Auth::guard('admin')->id();
}
/**
* 获取用户列表
*/
public function getList(array $params): array
{
$query = User::with(['department', 'roles']);
// 搜索条件
if (!empty($params['keyword'])) {
$query->where(function ($q) use ($params) {
$q->where('username', 'like', '%' . $params['keyword'] . '%')
->orWhere('real_name', 'like', '%' . $params['keyword'] . '%')
->orWhere('phone', 'like', '%' . $params['keyword'] . '%')
->orWhere('email', 'like', '%' . $params['keyword'] . '%');
});
}
if (!empty($params['department_id'])) {
// 获取部门及所有子部门的ID
$departmentIds = $this->departmentService->getDepartmentAndChildrenIds($params['department_id']);
$query->whereIn('department_id', $departmentIds);
}
if (isset($params['status']) && $params['status'] !== '') {
$query->where('status', $params['status']);
}
if (!empty($params['role_id'])) {
$query->whereHas('roles', function ($q) use ($params) {
$q->where('role_id', $params['role_id']);
});
}
// 排序
$orderBy = $params['order_by'] ?? 'id';
$orderDirection = $params['order_direction'] ?? 'desc';
$query->orderBy($orderBy, $orderDirection);
// 分页
$page = $params['page'] ?? 1;
$pageSize = $params['page_size'] ?? 20;
$list = $query->paginate($pageSize, ['*'], 'page', $page);
return [
'list' => $list->items(),
'total' => $list->total(),
'page' => $page,
'page_size' => $pageSize,
];
}
/**
* 获取用户详情
*/
public function getById(int $id): array
{
$user = User::with(['department', 'roles'])->find($id);
if (!$user) {
throw ValidationException::withMessages([
'id' => ['用户不存在'],
]);
}
return $this->formatUserInfo($user);
}
/**
* 创建用户
*/
public function create(array $data): User
{
// 检查用户名是否已存在
if (User::where('username', $data['username'])->exists()) {
throw ValidationException::withMessages([
'username' => ['用户名已存在'],
]);
}
// 检查手机号是否已存在
if (!empty($data['phone']) && User::where('phone', $data['phone'])->exists()) {
throw ValidationException::withMessages([
'phone' => ['手机号已被使用'],
]);
}
// 检查邮箱是否已存在
if (!empty($data['email']) && User::where('email', $data['email'])->exists()) {
throw ValidationException::withMessages([
'email' => ['邮箱已被使用'],
]);
}
DB::beginTransaction();
try {
$user = User::create([
'username' => $data['username'],
'password' => Hash::make($data['password']),
'real_name' => $data['real_name'],
'email' => $data['email'] ?? null,
'phone' => $data['phone'] ?? null,
'department_id' => $data['department_id'] ?? null,
'avatar' => $data['avatar'] ?? null,
'status' => $data['status'] ?? 1,
]);
// 关联角色
if (!empty($data['role_ids'])) {
$user->roles()->attach($data['role_ids']);
}
DB::commit();
return $user;
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
}
/**
* 更新用户
*/
public function update(int $id, array $data): User
{
$user = User::find($id);
if (!$user) {
throw ValidationException::withMessages([
'id' => ['用户不存在'],
]);
}
// 检查用户名是否已被其他用户使用
if (isset($data['username']) && $data['username'] !== $user->username) {
if (User::where('username', $data['username'])->exists()) {
throw ValidationException::withMessages([
'username' => ['用户名已存在'],
]);
}
}
// 检查手机号是否已被其他用户使用
if (isset($data['phone']) && $data['phone'] !== $user->phone) {
if (User::where('phone', $data['phone'])->exists()) {
throw ValidationException::withMessages([
'phone' => ['手机号已被使用'],
]);
}
}
// 检查邮箱是否已被其他用户使用
if (isset($data['email']) && $data['email'] !== $user->email) {
if (User::where('email', $data['email'])->exists()) {
throw ValidationException::withMessages([
'email' => ['邮箱已被使用'],
]);
}
}
DB::beginTransaction();
try {
$updateData = [
'real_name' => $data['real_name'] ?? $user->real_name,
'email' => $data['email'] ?? $user->email,
'phone' => $data['phone'] ?? $user->phone,
'department_id' => $data['department_id'] ?? $user->department_id,
'avatar' => $data['avatar'] ?? $user->avatar,
'status' => $data['status'] ?? $user->status,
];
if (isset($data['username'])) {
$updateData['username'] = $data['username'];
}
if (isset($data['password'])) {
$updateData['password'] = Hash::make($data['password']);
}
$user->update($updateData);
// 更新角色关联
if (isset($data['role_ids'])) {
$user->roles()->sync($data['role_ids']);
}
DB::commit();
// 发送更新通知(如果更新的是其他用户)
if ($id !== $this->getCurrentUserId()) {
$this->sendUserUpdateNotification($user, $data);
}
return $user;
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
}
/**
* 删除用户
*/
public function delete(int $id): void
{
$user = User::find($id);
if (!$user) {
throw ValidationException::withMessages([
'id' => ['用户不存在'],
]);
}
$user->delete();
}
/**
* 批量删除用户
*/
public function batchDelete(array $ids): int
{
$currentUserId = $this->getCurrentUserId();
// 检查是否包含当前用户
if (in_array($currentUserId, $ids)) {
throw ValidationException::withMessages([
'ids' => ['不能删除当前登录用户'],
]);
}
return User::whereIn('id', $ids)->delete();
}
/**
* 批量更新用户状态
*/
public function batchUpdateStatus(array $ids, int $status): int
{
$currentUserId = $this->getCurrentUserId();
// 如果是禁用操作,检查是否包含当前用户
if ($status === 0 && in_array($currentUserId, $ids)) {
throw ValidationException::withMessages([
'ids' => ['不能禁用当前登录用户'],
]);
}
return User::whereIn('id', $ids)->update(['status' => $status]);
}
/**
* 批量分配部门
*/
public function batchAssignDepartment(array $ids, int $departmentId): int
{
return User::whereIn('id', $ids)->update(['department_id' => $departmentId]);
}
/**
* 批量分配角色
*/
public function batchAssignRoles(array $ids, array $roleIds): void
{
foreach ($ids as $userId) {
$user = User::find($userId);
if ($user) {
$user->roles()->sync($roleIds);
}
}
}
/**
* 导出用户数据
*/
public function export(array $params): string
{
// 异步导出
$job = new UserExportJob($params);
dispatch($job);
return '导出任务已提交,请稍后在导出列表中查看';
}
/**
* 导入用户数据
*/
public function import(\Illuminate\Http\UploadedFile $file): array
{
$path = $file->store('imports');
// 异步导入
$job = new UserImportJob($path);
dispatch($job);
return [
'message' => '导入任务已提交,请稍后在导入列表中查看',
'file_path' => $path,
];
}
/**
* 格式化用户信息
*/
private function formatUserInfo(User $user): array
{
return [
'id' => $user->id,
'username' => $user->username,
'real_name' => $user->real_name,
'email' => $user->email,
'phone' => $user->phone,
'avatar' => $user->avatar,
'department' => $user->department ? [
'id' => $user->department->id,
'name' => $user->department->name,
] : null,
'roles' => $user->roles->map(function ($role) {
return [
'id' => $role->id,
'name' => $role->name,
'code' => $role->code,
];
})->toArray(),
'status' => $user->status,
'last_login_at' => $user->last_login_at ? $user->last_login_at->toDateTimeString() : null,
'last_login_ip' => $user->last_login_ip,
'created_at' => $user->created_at->toDateTimeString(),
'updated_at' => $user->updated_at->toDateTimeString(),
];
}
/**
* 发送用户更新通知
*/
private function sendUserUpdateNotification(User $user, array $data): void
{
// 收集被更新的字段
$changes = [];
$fieldLabels = [
'username' => '用户名',
'real_name' => '姓名',
'email' => '邮箱',
'phone' => '手机号',
'department_id' => '所属部门',
'avatar' => '头像',
'status' => '状态',
'password' => '密码',
'role_ids' => '角色',
];
foreach ($data as $key => $value) {
if (isset($fieldLabels[$key])) {
$changes[] = $fieldLabels[$key];
}
}
if (empty($changes)) {
return;
}
// 生成通知内容
$content = '您的账户信息已被管理员更新,更新的内容:' . implode('、', $changes);
// 发送通知
$this->notificationService->sendToUser(
$user->id,
'个人信息已更新',
$content,
Notification::TYPE_INFO,
Notification::CATEGORY_SYSTEM,
[
'user_id' => $user->id,
'updated_fields' => $changes,
'action_type' => Notification::ACTION_NONE,
]
);
}
}