LMS Этап 1 MVP - Laravel 13

 Базовая функциональность:
- Аутентификация (вход/выход/регистрация)
- Роли и разрешения (Administrator, Manager, Curator, Student)
- Панель управления (dashboard) для разных ролей

 База данных (23 миграции):
- users, organizations, groups, user_groups
- course_categories, courses, course_modules
- tests, questions, answers, question_matching_pairs
- test_attempts, test_responses
- course_requests, course_request_items, course_assignments
- scorm_data, user_course_progress, logs
- permission tables

 Модели (15 моделей с отношениями):
- User, Organization, Group
- CourseCategory, Course, CourseModule
- Test, Question, Answer, QuestionMatchingPair
- TestAttempt, TestResponse
- CourseRequest, CourseRequestItem, CourseAssignment
- ScormData, UserCourseProgress, Log

 Seeders:
- RoleSeeder (роли и разрешения)
- UserSeeder (тестовые пользователи)

 Контроллеры:
- LoginController, RegisterController, DashboardController

 Blade-шаблоны:
- layouts/app.blade.php
- auth/login.blade.php, auth/register.blade.php
- dashboard/admin.blade.php, dashboard/curator.blade.php, dashboard/student.blade.php

📦 Пакеты:
- Laravel 13 (dev-master)
- spatie/laravel-permission
- laravel/sanctum

🔧 Инфраструктура:
- Nginx конфигурация
- PHP 8.4-FPM
- MariaDB

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
mirivlad
2026-03-25 17:30:37 +08:00
co-authored by Qwen-Coder
commit 244c56df39
131 changed files with 13381 additions and 0 deletions
@@ -0,0 +1,50 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class LoginController extends Controller
{
public function showLoginForm()
{
return view('auth.login');
}
public function login(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (Auth::attempt($credentials, $request->boolean('remember'))) {
$request->session()->regenerate();
$user = Auth::user();
if (!$user->is_active) {
Auth::logout();
return back()->withErrors(['email' => 'Ваша учетная запись деактивирована.']);
}
return redirect()->intended('/dashboard');
}
return back()->withErrors([
'email' => 'Неверный email или пароль.',
])->onlyInput('email');
}
public function logout(Request $request)
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class RegisterController extends Controller
{
public function showRegistrationForm()
{
return view('auth.register');
}
public function register(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
'phone' => 'nullable|string|max:20',
]);
$user = User::create([
'name' => $validated['name'],
'email' => $validated['email'],
'password' => Hash::make($validated['password']),
'phone' => $validated['phone'] ?? null,
]);
$user->assignRole('Student');
Auth::login($user);
return redirect('/dashboard');
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, ValidatesRequests;
}
@@ -0,0 +1,84 @@
<?php
namespace App\Http\Controllers;
use App\Models\Course;
use App\Models\CourseAssignment;
use App\Models\UserCourseProgress;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class DashboardController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$user = Auth::user();
if ($user->hasRole('Administrator') || $user->hasRole('Manager')) {
return $this->adminDashboard();
}
if ($user->hasRole('Curator')) {
return $this->curatorDashboard();
}
return $this->studentDashboard();
}
private function adminDashboard()
{
$stats = [
'users_count' => \App\Models\User::count(),
'courses_count' => Course::count(),
'organizations_count' => \App\Models\Organization::count(),
'active_assignments' => CourseAssignment::where('is_active', true)->count(),
];
return view('dashboard.admin', compact('stats'));
}
private function curatorDashboard()
{
$user = Auth::user();
$organization = $user->organization;
$stats = [
'users_count' => $organization ? $organization->users()->count() : 0,
'courses_count' => Course::count(),
'groups_count' => $organization ? $organization->groups()->count() : 0,
];
return view('dashboard.curator', compact('stats', 'organization'));
}
private function studentDashboard()
{
$user = Auth::user();
// Получаем назначенные курсы
$assignments = CourseAssignment::where('user_id', $user->id)
->orWhere('organization_id', $user->organization_id)
->orWhereIn('group_id', $user->groups->pluck('id'))
->where('is_active', true)
->with('course')
->get();
$courses = $assignments->pluck('course')->unique('id');
// Прогресс по курсам
$progress = [];
foreach ($courses as $course) {
$userProgress = UserCourseProgress::where('user_id', $user->id)
->where('course_id', $course->id)
->first();
$progress[$course->id] = $userProgress ? $userProgress->completion_percentage : 0;
}
return view('dashboard.student', compact('courses', 'progress'));
}
}