Files
qztool/backend/app/Http/Controllers/Api/V1/Admin/PeopleController.php
T
DevandCursor 60daff2365 搭建轻舟一期门户、后台和统一登录。
让分类、会员和示例工具共用同一账号,本地即可跑通登录与授权。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-09 16:46:35 +08:00

90 lines
3.2 KiB
PHP

<?php
namespace App\Http\Controllers\Api\V1\Admin;
use App\Http\Controllers\Controller;
use App\Models\AuditLog;
use App\Models\Plan;
use App\Models\User;
use App\Services\AuthService;
use App\Services\MembershipService;
use App\Support\Presenter;
use Illuminate\Http\Request;
class PeopleController extends Controller
{
public function __construct(
private readonly MembershipService $membership,
private readonly AuthService $auth,
) {}
public function users(Request $request)
{
$query = User::query()->with('identities', 'subscription.plan');
if ($keyword = trim((string) $request->query('q', ''))) {
$like = '%'.addcslashes($keyword, '%_\\').'%';
$query->where(function ($q) use ($like) {
$q->where('nickname', 'like', $like)
->orWhereHas('identities', fn ($identity) => $identity->where('identifier', 'like', $like));
});
}
$page = $query->latest()->paginate(15);
return $this->ok([
'items' => collect($page->items())->map(fn (User $user) => Presenter::user($user, true))->values(),
'total' => $page->total(),
'page' => $page->currentPage(),
]);
}
public function updateUser(Request $request, User $user)
{
$data = $request->validate([
'status' => ['required', 'in:active,disabled'],
'disabled_reason' => ['nullable', 'string', 'max:255'],
]);
if ($user->id === $request->user()->id && $data['status'] !== 'active') {
return response()->json(['message' => '不能停用当前登录账号', 'code' => 'self'], 422);
}
$user->update($data);
if ($data['status'] !== 'active') {
$this->auth->revokeTokens($user);
}
$this->audit($request->user(), 'user.update', $user, '更新用户状态 '.$user->nickname);
return $this->ok(Presenter::user($user->refresh(), true));
}
public function grant(Request $request, User $user)
{
$data = $request->validate([
'plan_code' => ['required', 'string'],
'days' => ['required', 'integer', 'min:0', 'max:3650'],
]);
if ($data['days'] === 0) {
$this->membership->stop($user);
$this->audit($request->user(), 'membership.stop', $user, '停用会员 '.$user->nickname);
return $this->ok(Presenter::user($user->refresh(), true), '会员已停用');
}
$plan = Plan::query()->where('code', $data['plan_code'])->firstOrFail();
$this->membership->grant($user, $plan, now()->addDays($data['days']));
$this->audit($request->user(), 'membership.grant', $user, '开通 '.$plan->name.' '.$data['days'].' 天');
return $this->ok(Presenter::user($user->refresh(), true), '会员已开通');
}
public function audits()
{
$rows = AuditLog::query()->with('actor:id,nickname')->latest()->limit(100)->get();
return $this->ok($rows->map(fn (AuditLog $row) => [
'id' => $row->id,
'action' => $row->action,
'summary' => $row->summary,
'actor' => $row->actor?->nickname,
'created_at' => $row->created_at?->toIso8601String(),
]));
}
}