34 changed files with 2226 additions and 76 deletions
@ -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() |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -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) |
|||
{ |
|||
// |
|||
} |
|||
} |
|||
@ -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() |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -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() |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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' |
|||
); |
|||
} |
|||
} |
|||
@ -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(); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
@ -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' |
|||
); |
|||
} |
|||
} |
|||
@ -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'); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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 |
|||
); |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -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'); |
|||
} |
|||
}; |
|||
@ -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 |
|||
], |
|||
]; |
|||
} |
|||
} |
|||
@ -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) |
|||
] |
|||
); |
|||
} |
|||
} |
|||
@ -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); |
|||
// 用户 |
|||
}); |
|||
}); |
|||
Loading…
Reference in new issue