diff --git a/.env.example b/.env.example index 478972c..a689da7 100644 --- a/.env.example +++ b/.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 diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index b1c262c..48967a7 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -2,39 +2,47 @@ 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, \Psr\Log\LogLevel::*> */ - protected $levels = [ - // - ]; + protected $levels + = [ + // + ]; /** * A list of the exception types that are not reported. - * * @var array> */ - protected $dontReport = [ - // - ]; + protected $dontReport + = [ + // + ]; /** * A list of the inputs that are never flashed to the session on validation exceptions. - * * @var array */ - protected $dontFlash = [ - 'current_password', - 'password', - 'password_confirmation', - ]; + protected $dontFlash + = [ + 'current_password', + 'password', + 'password_confirmation', + ]; /** * Register the exception handling callbacks for the application. @@ -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() + ); + } } diff --git a/app/Http/Controllers/Api/AuthController.php b/app/Http/Controllers/Admin/AuthController.php similarity index 53% rename from app/Http/Controllers/Api/AuthController.php rename to app/Http/Controllers/Admin/AuthController.php index b1a92c8..6a59d97 100644 --- a/app/Http/Controllers/Api/AuthController.php +++ b/app/Http/Controllers/Admin/AuthController.php @@ -1,11 +1,12 @@ 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()); } } } diff --git a/app/Http/Controllers/Admin/IndexController.php b/app/Http/Controllers/Admin/IndexController.php new file mode 100644 index 0000000..b05a8bb --- /dev/null +++ b/app/Http/Controllers/Admin/IndexController.php @@ -0,0 +1,60 @@ +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() + ); + } + } +} diff --git a/app/Http/Controllers/Admin/MenuController.php b/app/Http/Controllers/Admin/MenuController.php new file mode 100644 index 0000000..02f78fe --- /dev/null +++ b/app/Http/Controllers/Admin/MenuController.php @@ -0,0 +1,100 @@ +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) + { + // + } +} diff --git a/app/Http/Controllers/Admin/RolesController.php b/app/Http/Controllers/Admin/RolesController.php new file mode 100644 index 0000000..7adf0d8 --- /dev/null +++ b/app/Http/Controllers/Admin/RolesController.php @@ -0,0 +1,246 @@ +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() + ); + } + } +} diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php new file mode 100644 index 0000000..18f6c4b --- /dev/null +++ b/app/Http/Controllers/Admin/UserController.php @@ -0,0 +1,247 @@ +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() + ); + } + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index c34cdcf..e308b4d 100644 --- a/app/Http/Kernel.php +++ b/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, ]; } diff --git a/app/Http/Middleware/AdminAuthMiddleware.php b/app/Http/Middleware/AdminAuthMiddleware.php new file mode 100644 index 0000000..52fc905 --- /dev/null +++ b/app/Http/Middleware/AdminAuthMiddleware.php @@ -0,0 +1,86 @@ +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); + } +} diff --git a/app/Http/Middleware/ApiResponseMiddleware.php b/app/Http/Middleware/ApiResponseMiddleware.php new file mode 100644 index 0000000..8107603 --- /dev/null +++ b/app/Http/Middleware/ApiResponseMiddleware.php @@ -0,0 +1,85 @@ +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; + } +} diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index d4ef644..b2b782b 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/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'); } } diff --git a/app/Http/Middleware/LanguageSwitcher.php b/app/Http/Middleware/LanguageSwitcher.php new file mode 100644 index 0000000..46c60af --- /dev/null +++ b/app/Http/Middleware/LanguageSwitcher.php @@ -0,0 +1,37 @@ +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); + } +} diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 9e86521..763a876 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/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 diff --git a/app/Models/AdminMenu.php b/app/Models/AdminMenu.php new file mode 100644 index 0000000..92bb64a --- /dev/null +++ b/app/Models/AdminMenu.php @@ -0,0 +1,40 @@ + + */ + 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' + ); + } +} diff --git a/app/Models/AdminOperationLog.php b/app/Models/AdminOperationLog.php new file mode 100644 index 0000000..6f4eb8f --- /dev/null +++ b/app/Models/AdminOperationLog.php @@ -0,0 +1,54 @@ + 'json', + 'new_values' => 'json', + ]; + + protected $table = 'admin_operation_log'; + + /** + * 获取进行此操作的用户 + */ + public function user() + { + return $this->belongsTo(User::class); + } + + /** + * 获取关联的模型 + */ + public function model() + { + return $this->morphTo(); + } +} diff --git a/app/Models/AdminRoleMenu.php b/app/Models/AdminRoleMenu.php new file mode 100644 index 0000000..0957c54 --- /dev/null +++ b/app/Models/AdminRoleMenu.php @@ -0,0 +1,59 @@ +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; + } +} diff --git a/app/Models/AdminRoleUsers.php b/app/Models/AdminRoleUsers.php new file mode 100644 index 0000000..50e0e9f --- /dev/null +++ b/app/Models/AdminRoleUsers.php @@ -0,0 +1,12 @@ + + */ + protected $fillable + = [ + 'name', + 'slug' + ]; + + /** + * The attributes that should be hidden for serialization. + * @var array + */ + 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' + ); + } +} diff --git a/app/Models/AdminUsers.php b/app/Models/AdminUsers.php new file mode 100644 index 0000000..0b5641f --- /dev/null +++ b/app/Models/AdminUsers.php @@ -0,0 +1,52 @@ + + */ + protected $fillable + = [ + 'username', + 'name', + 'password', + ]; + + /** + * The attributes that should be hidden for serialization. + * @var array + */ + protected $hidden + = [ + 'password', + 'remember_token', + 'deleted_at', + 'updated_at' + ]; + + /** + * The attributes that should be cast. + * @var array + */ + protected $casts = []; + + /** + * @return BelongsToMany + */ + public function roles(): BelongsToMany + { + return $this->belongsToMany(AdminRoles::class, AdminRoleUsers::class, 'user_id', 'role_id'); + } +} diff --git a/app/Models/Parking.php b/app/Models/Parking.php new file mode 100644 index 0000000..a20dbbf --- /dev/null +++ b/app/Models/Parking.php @@ -0,0 +1,11 @@ +sql); + }); } } diff --git a/app/Services/AdminMenuService.php b/app/Services/AdminMenuService.php new file mode 100644 index 0000000..6047531 --- /dev/null +++ b/app/Services/AdminMenuService.php @@ -0,0 +1,67 @@ +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); + } +} diff --git a/app/Services/AdminRolesService.php b/app/Services/AdminRolesService.php new file mode 100644 index 0000000..11fb610 --- /dev/null +++ b/app/Services/AdminRolesService.php @@ -0,0 +1,190 @@ +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; + } + } +} diff --git a/app/Services/AdminUsersService.php b/app/Services/AdminUsersService.php new file mode 100644 index 0000000..5eae1f8 --- /dev/null +++ b/app/Services/AdminUsersService.php @@ -0,0 +1,146 @@ +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; + } + } +} diff --git a/app/Services/OperationLogService.php b/app/Services/OperationLogService.php new file mode 100644 index 0000000..4c96987 --- /dev/null +++ b/app/Services/OperationLogService.php @@ -0,0 +1,144 @@ + 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 + ); + } +} diff --git a/app/common.php b/app/common.php new file mode 100644 index 0000000..c91296c --- /dev/null +++ b/app/common.php @@ -0,0 +1,41 @@ + 'Y-m-d', + 'datetime' => 'Y-m-d H:i:s', + }; + return date($format, $times); + } +} diff --git a/config/app.php b/config/app.php index bca112f..22bad2a 100644 --- a/config/app.php +++ b/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', /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2026_01_27_084640_create_admin_table.php b/database/migrations/2026_01_27_084640_create_admin_table.php new file mode 100644 index 0000000..311f087 --- /dev/null +++ b/database/migrations/2026_01_27_084640_create_admin_table.php @@ -0,0 +1,129 @@ +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'); + } +}; diff --git a/database/migrations/2026_01_27_023904_create_admins_table.php b/database/migrations/2026_01_29_082121_create_parking_table.php similarity index 50% rename from database/migrations/2026_01_27_023904_create_admins_table.php rename to database/migrations/2026_01_29_082121_create_parking_table.php index 0b3d9f7..54902b5 100644 --- a/database/migrations/2026_01_27_023904_create_admins_table.php +++ b/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'); } }; diff --git a/database/seeders/AdminMenuSeeder.php b/database/seeders/AdminMenuSeeder.php new file mode 100644 index 0000000..8ddc089 --- /dev/null +++ b/database/seeders/AdminMenuSeeder.php @@ -0,0 +1,116 @@ +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 + ], + ]; + } +} diff --git a/database/seeders/AdminUsersSeeder.php b/database/seeders/AdminUsersSeeder.php new file mode 100644 index 0000000..7c5654d --- /dev/null +++ b/database/seeders/AdminUsersSeeder.php @@ -0,0 +1,28 @@ +insert( + [ + 'username' => 'Admin', + 'name' => 'Admin', + 'email' => fake()->unique()->safeEmail(), + 'password' => Hash::make('12345678'), // password + 'remember_token' => Str::random(10) + ] + ); + } +} diff --git a/public/index.php b/public/index.php index 1d69f3a..54a9a54 100644 --- a/public/index.php +++ b/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'; diff --git a/routes/admin/api.php b/routes/admin/api.php new file mode 100644 index 0000000..19bc5f3 --- /dev/null +++ b/routes/admin/api.php @@ -0,0 +1,29 @@ + '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); + // 用户 + }); +}); diff --git a/routes/api.php b/routes/api.php index a8ede8e..9ca9a6c 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,8 +1,6 @@ group(function () { - // 认证相关 - Route::post('/logout', [AuthController::class, 'logout']); - Route::get('/me', [AuthController::class, 'me']); - -}); +include __DIR__ . '/' . 'admin/api.php';