Browse Source

上传部分文件不包括lang文件

master
wanghongjun 1 month ago
parent
commit
3ebea2eae5
  1. 1
      .env.example
  2. 116
      app/Exceptions/Handler.php
  3. 77
      app/Http/Controllers/Admin/AuthController.php
  4. 60
      app/Http/Controllers/Admin/IndexController.php
  5. 100
      app/Http/Controllers/Admin/MenuController.php
  6. 246
      app/Http/Controllers/Admin/RolesController.php
  7. 247
      app/Http/Controllers/Admin/UserController.php
  8. 3
      app/Http/Kernel.php
  9. 86
      app/Http/Middleware/AdminAuthMiddleware.php
  10. 85
      app/Http/Middleware/ApiResponseMiddleware.php
  11. 2
      app/Http/Middleware/Authenticate.php
  12. 37
      app/Http/Middleware/LanguageSwitcher.php
  13. 1
      app/Http/Middleware/VerifyCsrfToken.php
  14. 40
      app/Models/AdminMenu.php
  15. 54
      app/Models/AdminOperationLog.php
  16. 59
      app/Models/AdminRoleMenu.php
  17. 12
      app/Models/AdminRoleUsers.php
  18. 62
      app/Models/AdminRoles.php
  19. 52
      app/Models/AdminUsers.php
  20. 11
      app/Models/Parking.php
  21. 9
      app/Providers/AppServiceProvider.php
  22. 67
      app/Services/AdminMenuService.php
  23. 190
      app/Services/AdminRolesService.php
  24. 146
      app/Services/AdminUsersService.php
  25. 144
      app/Services/OperationLogService.php
  26. 41
      app/common.php
  27. 8
      config/app.php
  28. 129
      database/migrations/2026_01_27_084640_create_admin_table.php
  29. 12
      database/migrations/2026_01_29_082121_create_parking_table.php
  30. 116
      database/seeders/AdminMenuSeeder.php
  31. 28
      database/seeders/AdminUsersSeeder.php
  32. 1
      public/index.php
  33. 29
      routes/admin/api.php
  34. 13
      routes/api.php

1
.env.example

@ -3,6 +3,7 @@ APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_TIMEZONE=Asia/Shanghai
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null

116
app/Exceptions/Handler.php

@ -2,35 +2,43 @@
namespace App\Exceptions;
use App\Services\ApiResponseService;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of exception types with their corresponding custom log levels.
*
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
*/
protected $levels = [
protected $levels
= [
//
];
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [
protected $dontReport
= [
//
];
/**
* A list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
protected $dontFlash
= [
'current_password',
'password',
'password_confirmation',
@ -45,4 +53,100 @@ class Handler extends ExceptionHandler
//
});
}
/**
* Render an exception into an HTTP response.
* @param \Illuminate\Http\Request $request
* @param \Throwable $e
* @return \Symfony\Component\HttpFoundation\Response
* @throws \Throwable
*/
public function render($request, Throwable $e)
{
// API 异常处理
if ($request->expectsJson() || $request->is('api/*')) {
return $this->handleApiException($request, $e);
}
return parent::render($request, $e);
}
/**
* 处理 API 异常
* @param \Illuminate\Http\Request $request
* @param \Throwable $e
* @return \Illuminate\Http\JsonResponse
*/
private function handleApiException(
Request $request,
Throwable $e
): JsonResponse {
// 业务异常
if ($e instanceof CustomException) {
return app(ApiResponseService::class)->businessError(
$e->getMessage(),
$e->getCode() ?: 400
);
}
// 认证异常
if ($e instanceof AuthenticationException) {
return app(ApiResponseService::class)->unauthorized(
$e->getMessage() ?: __('exception.exception_handler.login')
);
}
// 验证异常
if ($e instanceof ValidationException) {
return app(ApiResponseService::class)->businessError(
$e->getMessage(),
422,
422
);
}
// 模型未找到异常
if ($e instanceof ModelNotFoundException) {
return app(ApiResponseService::class)->businessError(
__('exception.exception_handler.resource'),
404
);
}
// 路由未找到异常
if ($e instanceof NotFoundHttpException) {
return app(ApiResponseService::class)->businessError(
__('exception.exception_handler.api'),
404
);
}
// HTTP 异常
if ($e instanceof HttpException) {
$statusCode = $e->getStatusCode();
if ($statusCode === 403) {
return app(ApiResponseService::class)->businessError(
__('exception.exception_handler.role'),
403
);
}
if ($statusCode === 429) {
return app(ApiResponseService::class)->businessError(
__('exception.exception_handler.frequent'),
429
);
}
return app(ApiResponseService::class)->systemError(
$e->getMessage() ?: __('exception.exception_handler.system')
);
}
// 其他异常
return app(ApiResponseService::class)->systemError(
__('exception.exception_handler.system') . ':' . $e->getMessage()
);
}
}

77
app/Http/Controllers/Api/AuthController.php → app/Http/Controllers/Admin/AuthController.php

@ -1,11 +1,12 @@
<?php
namespace App\Http\Controllers\Api;
namespace App\Http\Controllers\Admin;
use App\Exceptions\CustomException;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\AdminUsers;
use App\Services\ApiResponseService;
use App\Services\OperationLogService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@ -19,48 +20,53 @@ class AuthController extends Controller
* @var ApiResponseService
*/
protected ApiResponseService $responseService;
/**
* @var OperationLogService
*/
protected OperationLogService $logService;
/**
* 构造函数
*
* @param ApiResponseService $responseService
* @param OperationLogService $logService
*/
public function __construct(
ApiResponseService $responseService,
OperationLogService $logService,
) {
$this->responseService = $responseService;
$this->logService = $logService;
}
/**
* 用户登录
* @param Request $request
* @return JsonResponse
* @throws ValidationException|CustomException
* @throws CustomException
* @throws ValidationException
*/
public function login(Request $request)
public function login(Request $request): JsonResponse
{
try {
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'password' => 'required|string',
'username' => 'required',
'password' => 'required'
], [
'email.required' => '邮箱不能为空',
'email.email' => '邮箱格式不正确',
'password.required' => '密码不能为空',
'username.required' => __('validation.auth.u_empty'),
'password.required' => __('validation.auth.p_empty'),
]);
if ($validator->fails()) {
throw new ValidationException($validator);
}
$user = User::where('email', $request->email)->first();
$user = AdminUsers::where('username', $request->username)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
throw new CustomException('邮箱或密码错误', 401);
throw new CustomException(__('validation.auth.u_p_error'), 401);
}
if ($user->status !== 1) {
throw new CustomException('账号已被禁用', 403);
throw new CustomException(__('validation.auth.u_disabled'), 403);
}
// 删除旧token
@ -69,32 +75,30 @@ class AuthController extends Controller
// 创建新token
$token = $user->createToken('auth-token')->plainTextToken;
//$this->logService->log('login', $user->name . '登录系统');
// 记录日志
$this->logService->log('login', $user->name . '登录系统');
return $this->responseService->success([
'user' => [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'avatar' => $user->avatar,
'is_admin' => $user->is_admin,
'avatar' => $user->avatar
],
'token' => $token,
]);
} catch (ValidationException|CustomException $e) {
throw $e;
} catch (\Exception $e) {
return $this->responseService->systemError('登录失败:' . $e->getMessage());
$m_prefix = __('admin.login') . __('admin.failed');
return $this->responseService->systemError($m_prefix . ':' . $e->getMessage());
}
}
/**
* 退出登录
*
* @param Request $request
* @return JsonResponse
*/
public function logout(Request $request)
public function logout(): JsonResponse
{
try {
$user = Auth::guard('sanctum')->user();
@ -103,12 +107,13 @@ class AuthController extends Controller
// 删除所有token
$user->tokens()->delete();
//$this->logService->log('logout', $user->name . '退出系统');
$this->logService->log('logout', $user['name'] . '退出系统');
}
return $this->responseService->success(null, '退出成功');
return $this->responseService->success(null, __('admin.logout_successful'));
} catch (\Exception $e) {
return $this->responseService->systemError('退出失败:' . $e->getMessage());
$m_prefix = __('admin.logout') . __('admin.failed');
return $this->responseService->systemError($m_prefix . ':' . $e->getMessage());
}
}
@ -117,10 +122,10 @@ class AuthController extends Controller
* @return JsonResponse
* @throws CustomException
*/
public function me()
public function me(): JsonResponse
{
try {
$user = Auth::user();
$user = Auth::guard('sanctum')->user();
if (!$user) {
throw new CustomException('未登录', 401);
@ -128,22 +133,22 @@ class AuthController extends Controller
// 查询用户角色和权限
$roles = $user->roles()->pluck('name')->toArray();
$permissions = $user->getAllPermissions()->pluck('name')->toArray();
// 查询权限
// $permissions = $user->getAllPermissions()->pluck('name')->toArray();
return $this->responseService->success([
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'phone' => $user->phone,
'avatar' => $user->avatar,
'is_admin' => $user->is_admin,
'id' => $user['id'],
'name' => $user['name'],
'email' => $user['email'],
'avatar' => $user['avatar'],
'roles' => $roles,
'permissions' => $permissions,
// 'permissions' => $permissions,
]);
} catch (CustomException $e) {
throw $e;
} catch (\Exception $e) {
return $this->responseService->systemError('获取用户信息失败:' . $e->getMessage());
$m_prefix = __('exception.get_user_info_error');
return $this->responseService->systemError($m_prefix . ':' . $e->getMessage());
}
}
}

60
app/Http/Controllers/Admin/IndexController.php

@ -0,0 +1,60 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Services\AdminMenuService;
use App\Services\ApiResponseService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class IndexController extends Controller
{
/**
* @var ApiResponseService
*/
protected ApiResponseService $responseService;
/**
* 构造函数
* @param ApiResponseService $responseService
*/
public function __construct(
ApiResponseService $responseService,
) {
$this->responseService = $responseService;
}
//
public function index(): JsonResponse
{
try {
$data = [];
return $this->responseService->success($data);
} catch (Exception $e) {
$m_prefix = __('exception.get_data_failed');
return $this->responseService->systemError(
$m_prefix . ':' . $e->getMessage()
);
}
}
public function menu(): JsonResponse
{
try {
$user = Auth::guard('sanctum')->user();
$user_id = $user['id'] ?? 1;
$data = (new AdminMenuService())->getUserMenuTreeList($user_id);
return $this->responseService->success($data);
} catch (Exception $e) {
$m_prefix = __('exception.get_data_failed');
return $this->responseService->systemError(
$m_prefix . ':' . $e->getMessage()
);
}
}
}

100
app/Http/Controllers/Admin/MenuController.php

@ -0,0 +1,100 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\AdminMenu;
use App\Services\ApiResponseService;
use App\Services\AdminMenuService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class MenuController extends Controller
{
/**
* @var ApiResponseService
*/
protected ApiResponseService $responseService;
/**
* @var AdminMenuService
*/
protected AdminMenuService $Service;
/**
* 构造函数
* @param ApiResponseService $responseService
* @param AdminMenuService $Service
*/
public function __construct(
ApiResponseService $responseService,
AdminMenuService $Service,
) {
$this->responseService = $responseService;
$this->Service = $Service;
}
/**
* Display a listing of the resource.
*/
public function index(): JsonResponse
{
try {
return $this->responseService->success([
'items' => $this->Service->getMenuTreeList(),
]);
} catch (\Exception $e) {
$m_prefix = __('exception.get_user_info_list_failed');
return $this->responseService->systemError(
$m_prefix . ':' . $e->getMessage()
);
}
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

246
app/Http/Controllers/Admin/RolesController.php

@ -0,0 +1,246 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Exceptions\CustomException;
use App\Http\Controllers\Controller;
use App\Models\AdminRoleMenu;
use App\Models\AdminRoles;
use App\Services\AdminMenuService;
use App\Services\ApiResponseService;
use App\Services\AdminRolesService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class RolesController extends Controller
{
/**
* @var ApiResponseService
*/
protected ApiResponseService $responseService;
/**
* @var AdminRolesService
*/
protected AdminRolesService $AdminRolesService;
/**
* 构造函数
* @param ApiResponseService $responseService
* @param AdminRolesService $AdminRolesService
*/
public function __construct(
ApiResponseService $responseService,
AdminRolesService $AdminRolesService,
) {
$this->responseService = $responseService;
$this->AdminRolesService = $AdminRolesService;
}
/**
* Display a listing of the resource.
*/
public function index(Request $request): JsonResponse
{
try {
$query = AdminRoles::query();
// 分页
$page = $request->input('page', 1);
$perPage = $request->input('per_page', 10);
$total = $query->count();
$items = $query->latest()->forPage($page, $perPage)->get();
return $this->responseService->success([
'items' => $items,
'total' => $total,
'page' => $page,
'per_page' => $perPage,
'last_page' => ceil($total / $perPage),
]);
} catch (Exception $e) {
$m_prefix = __('exception.get_user_info_list_failed');
return $this->responseService->systemError(
$m_prefix . ':' . $e->getMessage()
);
}
}
/**
* Show the form for creating a new resource.
*/
public function create(): JsonResponse
{
try {
$data = [
'menu_list' => (new AdminMenuService())->getMenuTreeCacheList()
];
return $this->responseService->success($data);
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.get_data_failed') . ':' . $e->getMessage()
);
}
}
/**
* @param Request $request
* @return JsonResponse
* @throws CustomException
* @throws ValidationException
*/
public function store(Request $request): JsonResponse
{
try {
$this->saveValidator($request->all());
$this->AdminRolesService->createModel($request->all());
return $this->responseService->success(
null,
__('admin.save_succeeded')
);
} catch (ValidationException|CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.create_admin_user_failed') . ':' . $e->getMessage(
)
);
}
}
/**
* @param array $data
* @param int $id
* @return void
* @throws ValidationException
*/
private function saveValidator(array $data, int $id = 0): void
{
$rules = [
'name' => 'required|max:50',
'menu_ids' => 'required|array',
'remark' => 'max:50'
];
$messages = [
'name.required' => __('validation.admin_role.n_empty'),
'name.max' => __('validation.admin_role.n_max'),
'menu_ids.required' => __('validation.admin_role.m_empty'),
'menu_ids.array' => __('validation.admin_role.m_array'),
'remark.max' => __('validation.admin_role.r_max'),
];
if ($id) {
$data['id'] = $id;
$rules['id'] = 'required|numeric';
$messages['id.required'] = __('validation.admin_role.id_empty');
$messages['id.numeric'] = __('validation.admin_role.id_numeric');
}
$validator = Validator::make($data, $rules, $messages);
if ($validator->fails()) {
throw new ValidationException($validator);
}
}
/**
* @param string $id
* @return JsonResponse
*/
public function show(string $id): JsonResponse
{
try {
$data = [
'menu_list' => (new AdminMenuService())->getMenuTreeCacheList(
AdminRoleMenu::getMenuIdArr($id)
),
'item' => AdminRoles::query()
->where('id', $id)
->get()
->toArray()
];
return $this->responseService->success($data);
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.get_data_failed') . ':' . $e->getMessage()
);
}
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id): JsonResponse
{
try {
$data = [
'menu_list' => (new AdminMenuService())->getMenuTreeCacheList(
AdminRoleMenu::getMenuIdArr($id)
),
'item' => AdminRoles::query()
->where('id', $id)
->get()
->toArray()
];
return $this->responseService->success($data);
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.get_data_failed') . ':' . $e->getMessage()
);
}
}
/**
* @param Request $request
* @param string $id
* @return JsonResponse
* @throws CustomException
* @throws ValidationException
*/
public function update(Request $request, string $id): JsonResponse
{
try {
$this->saveValidator($request->all(), $id);
$this->AdminRolesService->updateModel($request->all(), $id);
return $this->responseService->success(
null,
__('admin.update_succeeded')
);
} catch (ValidationException|CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.create_admin_user_failed') . ':' . $e->getMessage(
)
);
}
}
/**
* @param string $id
* @return JsonResponse
* @throws CustomException
*/
public function destroy(string $id): JsonResponse
{
try {
$this->AdminRolesService->deleteModel($id);
return $this->responseService->success(
null,
__('admin.delete_succeeded')
);
} catch (CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
'删除数据模型失败:' . $e->getMessage()
);
}
}
}

247
app/Http/Controllers/Admin/UserController.php

@ -0,0 +1,247 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Exceptions\CustomException;
use App\Http\Controllers\Controller;
use App\Models\AdminRoles;
use App\Models\AdminUsers;
use App\Services\ApiResponseService;
use App\Services\AdminUsersService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class UserController extends Controller
{
/**
* @var ApiResponseService
*/
protected ApiResponseService $responseService;
/**
* @var AdminUsersService
*/
protected AdminUsersService $AdminUserModelService;
/**
* 构造函数
* @param ApiResponseService $responseService
* @param AdminUsersService $AdminUsersService
*/
public function __construct(
ApiResponseService $responseService,
AdminUsersService $AdminUsersService,
) {
$this->responseService = $responseService;
$this->AdminUserModelService = $AdminUsersService;
}
/**
* Display a listing of the resource.
*/
public function index(Request $request): JsonResponse
{
try {
$query = AdminUsers::query();
// 关键词搜索
if ($request->has('keyword')) {
$keyword = $request->input('keyword');
$query->where('name', 'like', "%{$keyword}%");
}
// 分页
$page = $request->input('page', 1);
$perPage = $request->input('per_page', 10);
$total = $query->count();
$items = $query->latest()->forPage($page, $perPage)->get()->each(
function ($item) {
$item['status_str'] = $item['status'] ? __('admin.normal')
: __('admin.freeze');
$item['role_name'] = $item->roles->value('name');
unset($item['roles']);
return $item;
}
);
return $this->responseService->success([
'items' => $items,
'total' => $total,
'page' => $page,
'per_page' => $perPage,
'last_page' => ceil($total / $perPage),
]);
} catch (Exception $e) {
$m_prefix = __('exception.get_user_info_list_failed');
return $this->responseService->systemError(
$m_prefix . ':' . $e->getMessage()
);
}
}
/**
* Show the form for creating a new resource.
*/
public function create(): JsonResponse
{
try {
$data = [
'roles_list' => [],
'permissions_list' => [],
'packing_list' => []
];
return $this->responseService->success($data);
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.get_data_failed') . ':' . $e->getMessage()
);
}
}
/**
* @param Request $request
* @return JsonResponse
* @throws CustomException
* @throws ValidationException
*/
public function store(Request $request): JsonResponse
{
try {
$this->saveValidator($request->all());
$model = $this->AdminUserModelService->createModel($request->all());
return $this->responseService->success($model, '创建用户成功');
} catch (ValidationException|CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.create_admin_user_failed') . ':' . $e->getMessage(
)
);
}
}
/**
* @param array $data
* @param int $id
* @return void
* @throws ValidationException
*/
private function saveValidator(array $data, int $id = 0): void
{
$rules = [
'username' => 'required|alpha_num|between:4,20',
'role_id' => 'required|numeric',
'packing_id' => 'required|numeric',
'password' => 'required|between:12,30',
];
$messages = [
'username.required' => __('validation.admin_user.l_a_empty'),
'username.alpha_num' => __('validation.admin_user.l_a_alpha_num'),
'username.between' => __('validation.admin_user.l_a_between'),
'role_id.required' => __('validation.admin_user.r_empty'),
'packing_id.required' => __('validation.admin_user.s_p_empty'),
'password.required' => __('validation.admin_user.p_empty'),
'password.between' => __('validation.admin_user.p_between'),
];
if ($id) {
$data['id'] = $id;
$rules['id'] = 'required|numeric';
$messages['id.required'] = __('validation.admin_user.id_empty');
$messages['id.numeric'] = __('validation.admin_user.id_numeric');
}
$validator = Validator::make($data, $rules, $messages);
if ($validator->fails()) {
throw new ValidationException($validator);
}
}
/**
* Display the specified resource.
*/
public function show(string $id): JsonResponse
{
try {
$model = AdminUsers::findOrFail($id);
return $this->responseService->success($model);
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.get_data_failed') . ':' . $e->getMessage()
);
}
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id): JsonResponse
{
try {
$data = [
'item' => AdminUsers::query()
->where('id', $id)
->get()
->toArray(),
'roles' => AdminRoles::getRolesList()
];
return $this->responseService->success($data);
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.get_data_failed') . ':' . $e->getMessage()
);
}
}
/**
* @param Request $request
* @param string $id
* @return JsonResponse
* @throws CustomException
* @throws ValidationException
*/
public function update(Request $request, string $id): JsonResponse
{
try {
$this->saveValidator($request->all(), $id);
$this->AdminUserModelService->updateModel($request->all(), $id);
return $this->responseService->success(
null,
__('controller.rule.update_success')
);
} catch (ValidationException|CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
__('exception.create_admin_user_failed') . ':' . $e->getMessage(
)
);
}
}
/**
* @param string $id
* @return JsonResponse
* @throws CustomException
*/
public function destroy(string $id): JsonResponse
{
try {
$this->AdminUserModelService->deleteModel($id);
return $this->responseService->success(null, '删除数据模型成功');
} catch (CustomException $e) {
throw $e;
} catch (Exception $e) {
return $this->responseService->systemError(
'删除数据模型失败:' . $e->getMessage()
);
}
}
}

3
app/Http/Kernel.php

@ -42,6 +42,8 @@ class Kernel extends HttpKernel
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\ApiResponseMiddleware::class,
\App\Http\Middleware\LanguageSwitcher::class
],
];
@ -63,5 +65,6 @@ class Kernel extends HttpKernel
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'admin.auth' => \App\Http\Middleware\AdminAuthMiddleware::class,
];
}

86
app/Http/Middleware/AdminAuthMiddleware.php

@ -0,0 +1,86 @@
<?php
namespace App\Http\Middleware;
use App\Services\ApiResponseService;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
class AdminAuthMiddleware
{
/**
* @var ApiResponseService
*/
protected ApiResponseService $responseService;
/**
* 构造函数
* @param ApiResponseService $responseService
*/
public function __construct(ApiResponseService $responseService)
{
$this->responseService = $responseService;
}
/**
* Handle an incoming request.
* @param Request $request
* @param Closure $next
* @return JsonResponse|mixed
*/
public function handle(Request $request, Closure $next): mixed
{
// 检查请求头中是否有 auth
if (!$request->hasHeader('auth')) {
return $this->responseService->unauthorized(
__('middleware.auth.token_exists')
);
}
$token = $request->header('auth');
// 检查 token 是否有效
if (!Auth::guard('sanctum')->check()) {
// 尝试通过 token 认证
$request->headers->set('Authorization', 'Bearer ' . $token);
if (!Auth::guard('sanctum')->check()) {
return $this->responseService->unauthorized(
__('middleware.auth.token_invalid')
);
}
}
// 检查用户状态
$user = Auth::guard('sanctum')->user();
if (!$user || $user->status !== 1) {
return $this->responseService->error(
__('middleware.auth.user_disabled'),
403
);
}
// 检查是否为 JSON 请求
$contentType = $request->header('Content-Type');
if ($request->isMethod('POST')
&& (!$contentType
|| !str_contains(
$contentType,
'application/json'
))
) {
return $this->responseService->error(
__('middleware.auth.use_json'),
400
);
}
// 检查请求体是否为空对象
if ($request->isMethod('POST') && $request->getContent() === '') {
$request->merge([]);
}
return $next($request);
}
}

85
app/Http/Middleware/ApiResponseMiddleware.php

@ -0,0 +1,85 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ApiResponseMiddleware
{
/**
* Handle an incoming request.
* @param Request $request
* @param Closure $next
* @return JsonResponse|mixed
*/
public function handle(Request $request, Closure $next): mixed
{
$response = $next($request);
// 只处理非标准格式的 API 响应
if ($response instanceof JsonResponse) {
$content = $response->getData(true);
// 如果已经是标准响应格式,则不处理
if (isset($content['error']) && isset($content['body']) && isset($content['message'])) {
return $response;
}
// 处理错误响应
if ($response->getStatusCode() >= 400) {
$error = 500;
$message = '';
// 标准的错误响应
if (isset($content['message'])) {
$message = $content['message'];
}
// 根据状态码设置不同的错误码
if ($response->getStatusCode() === 401) {
$error = 401;
$message = $message ?: __('middleware.api.login');
} elseif ($response->getStatusCode() === 403) {
$error = 403;
$message = $message ?: __('middleware.api.permission');
} elseif ($response->getStatusCode() === 404) {
$error = 404;
$message = $message ?: __('middleware.api.resource');
} elseif ($response->getStatusCode() === 422) {
$error = 422;
$message = $message ?: __('middleware.api.data');
} else {
$message = $message ?: __('middleware.api.system');
}
// 重新包装响应
$newContent = [
'error' => $error,
'body' => (object)[],
'message' => $message,
];
// 如果是验证错误,添加错误详情
if ($response->getStatusCode() === 422 && isset($content['errors'])) {
$newContent['body'] = ['validation_errors' => $content['errors']];
}
$response->setData($newContent);
$response->setStatusCode(200);
}
// 处理成功响应
else {
// 重新包装响应
$response->setData([
'error' => 0,
'body' => $content,
'message' => '',
]);
}
}
return $response;
}
}

2
app/Http/Middleware/Authenticate.php

@ -12,6 +12,6 @@ class Authenticate extends Middleware
*/
protected function redirectTo(Request $request): ?string
{
return $request->expectsJson() ? null : route('login');
return $request->expectsJson() ? null : route('admin/login');
}
}

37
app/Http/Middleware/LanguageSwitcher.php

@ -0,0 +1,37 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
class LanguageSwitcher
{
public function handle(Request $request, Closure $next)
{
$token = $request->header('auth');
if ($token) {
$request->headers->set('Authorization', 'Bearer ' . $token);
}
// 优先使用用户设置的语言
if (Auth::guard('sanctum')->check()
&& Auth::guard('sanctum')->user()->locale
) {
App::setLocale(auth('sanctum')->user()->locale);
} // 其次使用会话中的语言设置
elseif (Session::has('locale')) {
App::setLocale(Session::get('locale'));
} // 最后使用浏览器默认语言
else {
App::setLocale(
$request->getPreferredLanguage(config('app.available_locales'))
?: config('app.fallback_locale')
);
}
return $next($request);
}
}

1
app/Http/Middleware/VerifyCsrfToken.php

@ -2,6 +2,7 @@
namespace App\Http\Middleware;
use App\Http\Controllers\Admin\AuthController;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware

40
app/Models/AdminMenu.php

@ -0,0 +1,40 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\Notifiable;
class AdminMenu extends Model
{
use HasFactory, Notifiable, SoftDeletes;
protected $table = 'admin_menu';
/**
* The attributes that should be hidden for serialization.
* @var array<int, string>
*/
protected $hidden
= [
'updated_at',
'deleted_at',
];
/**
* A Menu belongs to many roles.
* @return BelongsToMany
*/
public function roles(): BelongsToMany
{
return $this->belongsToMany(
AdminRoles::class,
AdminRoleMenu::class,
'menu_id',
'role_id'
);
}
}

54
app/Models/AdminOperationLog.php

@ -0,0 +1,54 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class AdminOperationLog extends Model
{
/**
* 可批量赋值的属性
* @var array
*/
protected $fillable
= [
'user_id',
'action',
'model_type',
'model_id',
'ip',
'description',
'old_values',
'new_values',
];
/**
* 属性类型转换
* @var array
*/
protected $casts
= [
'old_values' => 'json',
'new_values' => 'json',
];
protected $table = 'admin_operation_log';
/**
* 获取进行此操作的用户
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* 获取关联的模型
*/
public function model()
{
return $this->morphTo();
}
}

59
app/Models/AdminRoleMenu.php

@ -0,0 +1,59 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class AdminRoleMenu extends Model
{
use HasFactory;
protected $table = 'admin_role_menu';
/**
* 获取角色所有菜单
* @param int $role_id
* @return array
*/
public static function getMenuIdArr(int $role_id): array
{
return self::query()
->where('role_id', $role_id)
->pluck('menu_id')
->toArray();
}
/**
* @param $menu_ids
* @param $role_id
* @return mixed
*/
public static function createModel($menu_ids, $role_id): mixed
{
$roleMenuData = [];
foreach ($menu_ids as $menu_id) {
$roleMenuData[] = [
'role_id' => $role_id,
'menu_id' => $menu_id,
'created_at' => get_datetime()
];
}
return AdminRoleMenu::insert($roleMenuData);
}
public static function getMenuData($role_id): array
{
return self::query()->where('role_id', $role_id)->select()->get()
->toArray();
}
public static function existsRoleMenu($role_id, $menu_ids): bool
{
$count = count($menu_ids);
$existsCount = self::query()->where('role_id', $role_id)
->whereIn('menu_id', $menu_ids)->count();
return $count != $existsCount;
}
}

12
app/Models/AdminRoleUsers.php

@ -0,0 +1,12 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\belongsToMany;
use Illuminate\Database\Eloquent\Model;
class AdminRoleUsers extends Model
{
use HasFactory;
}

62
app/Models/AdminRoles.php

@ -0,0 +1,62 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\Notifiable;
class AdminRoles extends Model
{
use HasFactory, Notifiable, SoftDeletes;
protected $primaryKey = 'id';
/**
* The attributes that are mass assignable.
* @var array<int, string>
*/
protected $fillable
= [
'name',
'slug'
];
/**
* The attributes that should be hidden for serialization.
* @var array<int, string>
*/
protected $hidden
= [
'updated_at',
'deleted_at'
];
public static function getRolesList(): array
{
$where = ['status' => 1];
return self::query()->where($where)->select()->get()->toArray();
}
public function adminUsers(): BelongsToMany
{
return $this->belongsToMany(
AdminUsers::class,
AdminRoleUsers::class,
'role_id',
'user_id'
);
}
public function menus(): BelongsToMany
{
return $this->belongsToMany(
AdminMenu::class,
AdminRoleMenu::class,
'role_id',
'menu_id'
);
}
}

52
app/Models/AdminUsers.php

@ -0,0 +1,52 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class AdminUsers extends Model
{
use HasApiTokens, HasFactory, Notifiable, SoftDeletes;
/**
* The attributes that are mass assignable.
* @var array<int, string>
*/
protected $fillable
= [
'username',
'name',
'password',
];
/**
* The attributes that should be hidden for serialization.
* @var array<int, string>
*/
protected $hidden
= [
'password',
'remember_token',
'deleted_at',
'updated_at'
];
/**
* The attributes that should be cast.
* @var array<string, string>
*/
protected $casts = [];
/**
* @return BelongsToMany
*/
public function roles(): BelongsToMany
{
return $this->belongsToMany(AdminRoles::class, AdminRoleUsers::class, 'user_id', 'role_id');
}
}

11
app/Models/Parking.php

@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Parking extends Model
{
use HasFactory;
}

9
app/Providers/AppServiceProvider.php

@ -2,6 +2,9 @@
namespace App\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
@ -20,5 +23,11 @@ class AppServiceProvider extends ServiceProvider
public function boot(): void
{
//
Schema::defaultStringLength(120); // 将默认字符串长度设为 191
// 日志记录sql语句
DB::listen(function ($query) {
Log::info($query->sql);
});
}
}

67
app/Services/AdminMenuService.php

@ -0,0 +1,67 @@
<?php
namespace App\Services;
use App\Models\AdminMenu;
use App\Models\AdminRoles;
use App\Models\AdminRoleUsers;
use App\Models\AdminUsers;
final class AdminMenuService
{
/**
* 用户权限id数组
* @var array
*/
protected array $adminRoleMenus = [];
/**
* 缓存菜单
* @param array $adminRoleMenus
* @return array
*/
public function getMenuTreeCacheList(array $adminRoleMenus = []): array
{
$this->adminRoleMenus = $adminRoleMenus;
return $this->getMenuTreeList();
}
/**
* 获取菜单
* @param array $menus_id
* @return array
*/
public function getMenuTreeList(array $menus_id = []): array
{
$model = AdminMenu::query();
if ($menus_id) {
$model->wherein('id', $menus_id);
}
$list = $model->orderBy('order')
->orderBy('id')
->select()
->get()
->toArray();
return generate_tree($list, 0, $this->adminRoleMenus);
}
/**
* 获取用户菜单
* @param $user_id
* @return array
*/
public function getUserMenuTreeList($user_id): array
{
$AdminUsers = AdminUsers::find($user_id);
$roles_id = $AdminUsers->roles()->where('status', 1)->pluck('id')->toArray();
if (!$roles_id) {
return [];
}
$AdminRoles = AdminRoles::find($roles_id[0]);
$menus_id = $AdminRoles->menus()->where('status', 1)->pluck('id')->toArray();
if (!$menus_id) {
return [];
}
return $this->getMenuTreeList($menus_id);
}
}

190
app/Services/AdminRolesService.php

@ -0,0 +1,190 @@
<?php
namespace App\Services;
use App\Models\AdminRoleMenu;
use App\Models\AdminRoles;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
final class AdminRolesService
{
/**
* @var OperationLogService
*/
private OperationLogService $logService;
/**
* 构造函数
* @param OperationLogService $logService
*/
public function __construct(OperationLogService $logService)
{
$this->logService = $logService;
}
/**
* @param array $data
* @param int $id
* @return Model|Builder
* @throws Exception
*/
public function updateModel(array $data, int $id): Model|Builder
{
try {
DB::beginTransaction();
$remark = $data['remark'] ?? '';
$menu_ids = $data['menu_ids'];
// 验证
$existsWhere = [
['name', '=', $data['name']],
['id', '<>', $id]
];
if (AdminRoles::query()->where($existsWhere)->exists()) {
throw new Exception(__('service.admin_role.name_exists'));
}
self::validateMenuIds($menu_ids);
// 更新
$model = AdminRoles::query()->findOrFail($id);
$oldValues = $model->toArray();
$model->update([
'name' => $data['name'],
'remark' => $remark,
'level' => $data['level'],
'updated_at' => get_datetime()
]);
$this->logService->logUpdated($model, $oldValues, '更新角色');
// 删除再创建关联
if (AdminRoleMenu::existsRoleMenu($id, $menu_ids)) {
$this->delAdminRoleMenu($id);
$this->addAdminRoleMenu($id, $menu_ids);
}
DB::commit();
return $model;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
/**
* 验证菜单数据
* @param array $menu_ids
* @return void
* @throws Exception
*/
public static function validateMenuIds(array $menu_ids): void
{
foreach ($menu_ids as $menu_id) {
if (!is_numeric($menu_id)) {
throw new Exception(__('service.admin_role.menu_error'));
}
}
}
/**
* 同步删除角色菜单关联数据
* @param int $role_id
* @return void
*/
private function delAdminRoleMenu(int $role_id): void
{
$oldAdminRoleMenu = AdminRoleMenu::query()->where('role_id', $role_id)
->select()->get()->toArray();
$this->logService->logDeletedData(
new AdminRoleMenu(),
'删除角色关联菜单',
$oldAdminRoleMenu
);
AdminRoleMenu::query()->where('role_id', $role_id)->delete();
}
/**
* 同步添加角色菜单关联数据
* @param int $role_id
* @param array $menu_ids
* @return void
*/
private function addAdminRoleMenu(int $role_id, array $menu_ids): void
{
AdminRoleMenu::createModel($menu_ids, $role_id);
$AdminRoleMenuData = AdminRoleMenu::getMenuData($role_id);
$this->logService->logCreatedData(
new AdminRoleMenu(),
'创建角色关联菜单',
$AdminRoleMenuData
);
}
/**
* 创建角色
* @param array $data
* @return Model|Builder
* @throws Exception
*/
public function createModel(array $data): Model|Builder
{
try {
DB::beginTransaction();
$remark = $data['remark'] ?? '';
$menu_ids = $data['menu_ids'];
if (AdminRoles::query()->where('name', $data['name'])->exists()) {
throw new Exception(__('service.admin_role.name_exists'));
}
self::validateMenuIds($menu_ids);
$model = AdminRoles::query()->create([
'name' => $data['name'],
'remark' => $remark,
'level' => $data['level'],
'created_at' => get_datetime()
]);
$this->logService->logCreated($model, '创建角色');
$this->addAdminRoleMenu($model->id, $menu_ids);
DB::commit();
return $model;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
/**
* 删除角色
* @param int $id
* @return bool
* @throws Exception
*/
public function deleteModel(int $id): bool
{
try {
DB::beginTransaction();
$model = AdminRoles::query()->findOrFail($id);
$this->logService->logDeleted($model, '删除角色');
$model->delete();
$this->delAdminRoleMenu($id);
DB::commit();
return true;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
}

146
app/Services/AdminUsersService.php

@ -0,0 +1,146 @@
<?php
namespace App\Services;
use App\Models\AdminRoleUsers;
use App\Models\AdminUsers;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
final class AdminUsersService
{
/**
* @var OperationLogService
*/
private OperationLogService $logService;
/**
* 构造函数
* @param OperationLogService $logService
*/
public function __construct(OperationLogService $logService)
{
$this->logService = $logService;
}
/**
* @throws Exception
*/
public function createModel(array $data): AdminUsers
{
try {
DB::beginTransaction();
$model = AdminUsers::create([
'username' => $data['username'],
'password' => Hash::make($data['password']),
'name' => $data['name'],
'avatar' => '',
'email' => $data['email'],
'status' => 1,
'created_at' => get_datetime()
]);
$user_id = $model->id;
// 角色id
$role_id = $data['role_id'];
$AdminRoleUsers = AdminRoleUsers::create([
'user_id' => $user_id,
'role_id' => $role_id
]);
// 职位id
$permission_id = $data['permission_id'];
//
$packing_id = $data['packing'];
$this->logService->logCreated($model, '创建用户');
$this->logService->logCreated($AdminRoleUsers, '创建用户关联角色');
return $model;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
/**
* @param array $data
* @param int $id
* @return AdminUsers
* @throws Exception
*/
public function updateModel(array $data, int $id): AdminUsers
{
try {
DB::beginTransaction();
if (AdminUsers::query()->where('username', $data['username'])->exists()) {
throw new Exception(__('service.admin_role.role_exists'));
}
$model = AdminUsers::findOrFail($id);
$model->update([
'username' => $data['username'],
'password' => Hash::make($data['password']),
'name' => $data['name'],
'avatar' => '',
'email' => $data['email'],
'status' => $data['status'],
'created_at' => get_datetime()
]);
// 角色id
$role_id = $data['role_id'];
$DelAdminRoleUsers = AdminRoleUsers::where('user_id', $id)->select();
$DelAdminRoleUsers->delete();
$AddAdminRoleUsers = AdminRoleUsers::create([
'user_id' => $id,
'role_id' => $role_id
]);
// 职位id
$permission_id = $data['permission_id'];
//
$packing_id = $data['packing'];
$this->logService->logCreated($model, '创建用户');
$this->logService->logDeleted($DelAdminRoleUsers, '删除用户关联角色');
$this->logService->logCreated($AddAdminRoleUsers, '创建用户关联角色');
return $model;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
/**
* @param $id
* @return bool
* @throws Exception
*/
public function deleteModel($id): bool
{
try {
DB::beginTransaction();
$model = AdminUsers::findOrFail($id);
$this->logService->logDeleted($model, '删除用户');
$model->delete();
$oldAdminRoleUser = AdminRoleUsers::where(['user_id' => $id])->select();
$this->logService->logDeleted($oldAdminRoleUser, '删除用户关联角色');
$oldAdminRoleUser->delete();
DB::commit();
return true;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
}

144
app/Services/OperationLogService.php

@ -0,0 +1,144 @@
<?php
namespace App\Services;
use App\Models\AdminOperationLog;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Request;
final class OperationLogService
{
/**
* 记录操作日志
*
* @param string $action 操作类型
* @param string $description 操作描述
* @param Model|null $model 关联模型
* @param array|null $oldValues 旧值
* @param array|null $newValues 新值
* @return AdminOperationLog
*/
public function log(
string $action,
string $description,
?Model $model = null,
?array $oldValues = null,
?array $newValues = null
): AdminOperationLog {
$data = [
'user_id' => Auth::id() ?? 0,
'action' => $action,
'description' => $description,
'ip' => Request::ip(),
];
if ($model) {
$data['model_type'] = get_class($model);
$data['model_id'] = $model->getKey();
}
if ($oldValues) {
$data['old_values'] = $oldValues;
}
if ($newValues) {
$data['new_values'] = $newValues;
}
return AdminOperationLog::create($data);
}
/**
* 记录新增操作
*
* @param Model $model 关联模型
* @param string $description 操作描述
* @return AdminOperationLog
*/
public function logCreated(Model $model, string $description = '创建记录'): AdminOperationLog
{
return $this->log(
'create',
$description,
$model,
null,
$model->toArray()
);
}
/**
* 记录新增操作-数据
*
* @param Model $model 关联模型
* @param string $description 操作描述
* @param array $data 数据
* @return AdminOperationLog
*/
public function logCreatedData(Model $model, string $description = '创建记录', array $data = []): AdminOperationLog
{
return $this->log(
'create',
$description,
$model,
null,
$data
);
}
/**
* 记录更新操作
*
* @param Model $model 关联模型
* @param array $oldValues 旧值
* @param string $description 操作描述
* @return AdminOperationLog
*/
public function logUpdated(Model $model, array $oldValues, string $description = '更新记录'): AdminOperationLog
{
return $this->log(
'update',
$description,
$model,
$oldValues,
$model->toArray()
);
}
/**
* 记录删除操作
*
* @param Model $model 关联模型
* @param string $description 操作描述
* @return AdminOperationLog
*/
public function logDeleted(Model $model, string $description = '删除记录'): AdminOperationLog
{
return $this->log(
'delete',
$description,
$model,
$model->toArray(),
null
);
}
/**
* 记录删除操作
*
* @param Model $model 关联模型
* @param string $description 操作描述
* @param array $data 数据
* @return AdminOperationLog
*/
public function logDeletedData(Model $model, string $description = '删除记录', array $data = []): AdminOperationLog
{
return $this->log(
'delete',
$description,
$model,
$data,
null
);
}
}

41
app/common.php

@ -0,0 +1,41 @@
<?php
if (!function_exists('generate_tree')) {
function generate_tree(
array $flatArray,
int $parentId = 0,
array $existsArr = []
): array {
$tree = [];
foreach ($flatArray as $item) {
if ($item['parent_id'] === $parentId) {
$node = $item;
if ($existsArr) {
$node['is_show'] = in_array($item['id'], $existsArr) ? 1
: 0;
}
$node['children'] = generate_tree(
$flatArray,
$item['id'],
$existsArr
);
$tree[] = $node;
}
}
return $tree;
}
}
if (!function_exists('get_datetime')) {
function get_datetime(string $type = 'datetime', int $times = 0): string
{
if (!$times) {
$times = time();
}
$format = match ($type) {
'date' => 'Y-m-d',
'datetime' => 'Y-m-d H:i:s',
};
return date($format, $times);
}
}

8
config/app.php

@ -69,7 +69,7 @@ return [
|
*/
'timezone' => 'UTC',
'timezone' => env('APP_TIMEZONE', 'UTC'),
/*
|--------------------------------------------------------------------------
@ -82,7 +82,7 @@ return [
|
*/
'locale' => 'en',
'locale' => 'zh-CN',
/*
|--------------------------------------------------------------------------
@ -95,7 +95,7 @@ return [
|
*/
'fallback_locale' => 'en',
'fallback_locale' => 'zh-CN',
/*
|--------------------------------------------------------------------------
@ -108,7 +108,7 @@ return [
|
*/
'faker_locale' => 'en_US',
'faker_locale' => 'zh-CN',
/*
|--------------------------------------------------------------------------

129
database/migrations/2026_01_27_084640_create_admin_table.php

@ -0,0 +1,129 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('admin_users', function (Blueprint $table) {
$table->increments('id')->comment('管理用户ID');
$table->string('username', 190)->unique()->comment('登录账号');
$table->string('password', 60)->comment('密码');
$table->string('name')->comment('姓名');
$table->string('avatar')->nullable()->comment('头像');
$table->string('email')->comment('电子邮箱');
$table->string('remember_token', 100)->nullable()->comment('记住令牌');
$table->tinyInteger('status')->default(1)->comment('状态 0冻结 1正常');
$table->string('locale', 10)->nullable()->comment('语言');
$table->softDeletes();
$table->timestamps();
$table->innoDb();
});
Schema::create('admin_roles', function (Blueprint $table) {
$table->increments('id')->comment('角色id');
$table->string('name', 50)->unique()->comment('角色名称');
$table->string('remark', 50)->comment('角色说明');
$table->integer('level')->nullable()->comment('角色级别');
$table->tinyInteger('status')->default(1)->comment('状态 0禁用 1启用');
$table->softDeletes();
$table->timestamps();
$table->innoDb();
});
Schema::create('admin_permissions', function (Blueprint $table) {
$table->increments('id')->comment('权限ID');
$table->string('name', 50)->unique()->comment('权限名称');
$table->string('slug', 50)->unique();
$table->string('http_method')->nullable();
$table->text('http_path')->nullable();
$table->softDeletes();
$table->timestamps();
$table->innoDb();
});
Schema::create('admin_menu', function (Blueprint $table) {
$table->increments('id')->comment('菜单ID');
$table->integer('parent_id')->default(0)->comment('父级菜单ID');
$table->integer('order')->default(0)->comment('排序由小到大');
$table->string('title', 50)->comment('菜单标题');
$table->string('icon', 50)->comment('菜单图标');
$table->string('uri')->nullable()->comment('链接地址');
$table->string('permission')->nullable();
$table->tinyInteger('status')->default(1)->comment('状态 0禁用 1启用');
$table->timestamps();
$table->innoDb();
});
Schema::create('admin_role_users', function (Blueprint $table) {
$table->integer('role_id')->comment('角色ID');
$table->integer('user_id')->comment('用户ID');
$table->index(['role_id', 'user_id']);
$table->timestamps();
$table->innoDb();
});
Schema::create('admin_role_permissions', function (Blueprint $table) {
$table->integer('role_id')->comment('角色ID');
$table->integer('permission_id')->comment('权限ID');
$table->index(['role_id', 'permission_id']);
$table->timestamps();
$table->innoDb();
});
Schema::create('admin_user_permissions', function (Blueprint $table) {
$table->integer('user_id')->comment('用户ID');
$table->integer('permission_id')->comment('权限ID');
$table->index(['user_id', 'permission_id']);
$table->timestamps();
$table->innoDb();
});
Schema::create('admin_role_menu', function (Blueprint $table) {
$table->integer('role_id')->comment('权限ID');
$table->integer('menu_id')->comment('菜单ID');
$table->index(['role_id', 'menu_id']);
$table->timestamps();
$table->innoDb();
});
Schema::create('admin_operation_log', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id')->comment('操作用户ID');
$table->string('action')->comment('操作类型');
$table->string('model_type')->nullable()->comment('模型类型');
$table->unsignedBigInteger('model_id')->nullable()->comment('模型ID');
$table->string('ip')->nullable()->comment('操作IP');
$table->text('description')->nullable()->comment('操作描述');
$table->json('old_values')->nullable()->comment('旧值');
$table->json('new_values')->nullable()->comment('新值');
$table->timestamps();
$table->innoDb();
$table->index(['user_id', 'action']);
$table->index(['model_type', 'model_id']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('admin_user');
Schema::dropIfExists('admin_roles');
Schema::dropIfExists('admin_permissions');
Schema::dropIfExists('admin_menu');
Schema::dropIfExists('admin_role_users');
Schema::dropIfExists('admin_role_permissions');
Schema::dropIfExists('admin_user_permissions');
Schema::dropIfExists('admin_role_menu');
Schema::dropIfExists('admin_operation_log');
}
};

12
database/migrations/2026_01_27_023904_create_admins_table.php → database/migrations/2026_01_29_082121_create_parking_table.php

@ -11,13 +11,9 @@ return new class extends Migration
*/
public function up(): void
{
Schema::create('admins', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->default('');
$table->string('account', 20)->unique();
$table->timestamp('account_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
Schema::create('parking', function (Blueprint $table) {
$table->id();
$table->string('title')->unique();
$table->timestamps();
});
}
@ -27,6 +23,6 @@ return new class extends Migration
*/
public function down(): void
{
Schema::dropIfExists('admins');
Schema::dropIfExists('parking');
}
};

116
database/seeders/AdminMenuSeeder.php

@ -0,0 +1,116 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class AdminMenuSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
DB::table('admin_menu')->insert($this->data());
}
private function data(): array
{
$not_datetime = get_datetime();
return [
[
'id' => 1,
'parent_id' => 0,
'order' => 0,
'title' => '模式管理',
'icon' => '',
'uri' => '',
'permission' => '',
'created_at' => $not_datetime
],
[
'id' => 2,
'parent_id' => 0,
'order' => 0,
'title' => '车位状态',
'icon' => '',
'uri' => '',
'permission' => '',
'created_at' => $not_datetime
],
[
'id' => 3,
'parent_id' => 0,
'order' => 0,
'title' => '特别车位管理',
'icon' => '',
'uri' => '',
'permission' => '',
'created_at' => $not_datetime
],
[
'id' => 4,
'parent_id' => 0,
'order' => 0,
'title' => '信息中心',
'icon' => '',
'uri' => '',
'permission' => '',
'created_at' => $not_datetime
],
[
'id' => 5,
'parent_id' => 0,
'order' => 0,
'title' => '统计报表',
'icon' => '',
'uri' => '',
'permission' => '',
'created_at' => $not_datetime
],
[
'id' => 6,
'parent_id' => 0,
'order' => 0,
'title' => '设备管理',
'icon' => '',
'uri' => '',
'permission' => '',
'created_at' => $not_datetime
],
[
'id' => 7,
'parent_id' => 0,
'order' => 0,
'title' => '系统管理',
'icon' => '',
'uri' => '',
'permission' => '',
'created_at' => $not_datetime
],
[
'id' => 8,
'parent_id' => 7,
'order' => 0,
'title' => '用户管理',
'icon' => '',
'uri' => '',
'permission' => '',
'created_at' => $not_datetime
],
[
'id' => 9,
'parent_id' => 7,
'order' => 0,
'title' => '角色管理',
'icon' => '',
'uri' => '',
'permission' => '',
'created_at' => $not_datetime
],
];
}
}

28
database/seeders/AdminUsersSeeder.php

@ -0,0 +1,28 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class AdminUsersSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
DB::table('admin_users')->insert(
[
'username' => 'Admin',
'name' => 'Admin',
'email' => fake()->unique()->safeEmail(),
'password' => Hash::make('12345678'), // password
'remember_token' => Str::random(10)
]
);
}
}

1
public/index.php

@ -43,6 +43,7 @@ require __DIR__.'/../vendor/autoload.php';
| to this client's browser, allowing them to enjoy our application.
|
*/
require_once __DIR__.'/../app/common.php';
$app = require_once __DIR__.'/../bootstrap/app.php';

29
routes/admin/api.php

@ -0,0 +1,29 @@
<?php
use App\Http\Controllers\Admin\AuthController;
use App\Http\Controllers\Admin\IndexController;
use App\Http\Controllers\Admin\RolesController;
use App\Http\Controllers\Admin\UserController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'admin'], function () {
// 认证相关接口
Route::post('/login', [AuthController::class, 'login']);
// get测试区
Route::resource('users', UserController::class);
// 需要认证的接口
Route::middleware(['admin.auth'])->group(function () {
// 认证相关
Route::post('/logout', [AuthController::class, 'logout']);
Route::get('/me', [AuthController::class, 'me']);
// 首页
Route::get('/index', [IndexController::class, 'index']);
Route::get('/menu', [IndexController::class, 'menu']);
// 角色
Route::resource('roles', RolesController::class);
// 用户
});
});

13
routes/api.php

@ -1,8 +1,6 @@
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\AuthController;
/*
|--------------------------------------------------------------------------
@ -15,13 +13,4 @@ use App\Http\Controllers\Api\AuthController;
|
*/
// 认证相关接口
Route::post('/login', [AuthController::class, 'login']);
// 需要认证的接口
Route::middleware(['api.auth'])->group(function () {
// 认证相关
Route::post('/logout', [AuthController::class, 'logout']);
Route::get('/me', [AuthController::class, 'me']);
});
include __DIR__ . '/' . 'admin/api.php';

Loading…
Cancel
Save