后台管理系统实战

0 阅读2分钟

RBAC 权限模型

-- 用户表  
CREATE TABLE admins (  
    id INT PRIMARY KEY AUTO_INCREMENT,  
    username VARCHAR(50UNIQUE,  
    password VARCHAR(255),  
    nickname VARCHAR(50),  
    status TINYINT DEFAULT 1,  
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP  
);  
  
-- 角色表  
CREATE TABLE roles (  
    id INT PRIMARY KEY AUTO_INCREMENT,  
    name VARCHAR(50),  
    code VARCHAR(50UNIQUE,  
    description VARCHAR(255)  
);  
  
-- 用户角色关联  
CREATE TABLE admin_roles (  
    admin_id INT,  
    role_id INT,  
    PRIMARY KEY (admin_id, role_id)  
);  
  
-- 菜单/权限表  
CREATE TABLE permissions (  
    id INT PRIMARY KEY AUTO_INCREMENT,  
    parent_id INT DEFAULT 0,  
    name VARCHAR(50),  
    code VARCHAR(100),  
    type TINYINT,  -- 1菜单 2按钮  
    path VARCHAR(200),  
    icon VARCHAR(50),  
    sort INT DEFAULT 0  
);  
  
-- 角色权限关联  
CREATE TABLE role_permissions (  
    role_id INT,  
    permission_id INT,  
    PRIMARY KEY (role_id, permission_id)  
);

权限验证

<?php  
class PermissionService  
{  
    // 获取用户所有权限  
    public function getUserPermissions(int $adminId): array  
    {  
        $cacheKey"admin:permissions:{$adminId}";  
          
        return Cache::remember($cacheKey3600, function () use ($adminId) {  
            return DB::table('admin_roles as ar')  
                ->join('role_permissions as rp''ar.role_id''=''rp.role_id')  
                ->join('permissions as p''rp.permission_id''=''p.id')  
                ->where('ar.admin_id', $adminId)  
                ->pluck('p.code')  
                ->unique()  
                ->toArray();  
        });  
    }  
      
    // 检查权限  
    public function hasPermission(int $adminId, string $code): bool  
    {  
        $permissions$this->getUserPermissions($adminId);  
        return in_array($code, $permissions);  
    }  
      
    // 获取用户菜单  
    public function getUserMenus(int $adminId): array  
    {  
        $permissions = DB::table('admin_roles as ar')  
            ->join('role_permissions as rp''ar.role_id''=''rp.role_id')  
            ->join('permissions as p''rp.permission_id''=''p.id')  
            ->where('ar.admin_id', $adminId)  
            ->where('p.type'1)  
            ->orderBy('p.sort')  
            ->get();  
          
        return $this->buildTree($permissions);  
    }  
      
    private function buildTree($items, $parentId0): array  
    {  
        $tree = [];  
        foreach ($items as $item) {  
            if ($item->parent_id == $parentId) {  
                $children$this->buildTree($items, $item->id);  
                $node = (array) $item;  
                if ($children) {  
                    $node['children'] = $children;  
                }  
                $tree[] = $node;  
            }  
        }  
        return $tree;  
    }  
}

权限中间件

<?php  
class CheckPermission  
{  
    public function handle(Request $request, Closure $next, string $permission)  
    {  
        $admin = auth('admin')->user();  
          
        if (!$this->permissionService->hasPermission($admin->id, $permission)) {  
            return response()->json(['error' => '无权限'], 403);  
        }  
          
        return $next($request);  
    }  
}  
  
// 路由使用  
Route::get('/users', [UserController::class'index'])  
    ->middleware('permission:user.list');  
Route::post('/users', [UserController::class'store'])  
    ->middleware('permission:user.create');

操作日志

<?php  
class OperationLog  
{  
    public static function record(string $module, string $action, $data = null): void  
    {  
        DB::table('operation_logs')->insert([  
            'admin_id' => auth('admin')->id(),  
            'module' => $module,  
            'action' => $action,  
            'data' => json_encode($data),  
            'ip' => request()->ip(),  
            'user_agent' => request()->userAgent(),  
            'created_at' => now()  
        ]);  
    }  
}  
  
// 使用  
OperationLog::record('用户管理''创建用户', ['username' => $user->username]);

数据字典


<?php  
class DictService  
{  
    public function getByType(string $type): array  
    {  
        return Cache::remember("dict:{$type}"3600, function () use ($type) {  
            return DB::table('dicts')  
                ->where('type', $type)  
                ->where('status'1)  
                ->orderBy('sort')  
                ->get()  
                ->toArray();  
        });  
    }  
      
    public function getValue(string $type, $key): ?string  
    {  
        $items$this->getByType($type);  
        foreach ($items as $item) {  
            if ($item->key == $key) {  
                return $item->value;  
            }  
        }  
        return null;  
    }  
}  
  
// 使用  
$statusText = $dictService->getValue('order_status', $order->status);

通用 CRUD

<?php  
abstract class BaseController  
{  
    protected string $model;  
    protected array $searchFields = [];  
      
    public function index(Request $request)  
    {  
        $query$this->model::query();  
          
        // 搜索  
        foreach ($this->searchFields as $field) {  
            if ($request->filled($field)) {  
                $query->where($field'like'"%{$request->input($field)}%");  
            }  
        }  
          
        // 排序  
        $query->orderBy($request->input('sort_field''id'), $request->input('sort_order''desc'));  
          
        // 分页  
        return $query->paginate($request->input('page_size'15));  
    }  
      
    public function store(Request $request)  
    {  
        $data = $request->validated();  
        return $this->model::create($data);  
    }  
      
    public function update(Request $request, int $id)  
    {  
        $model$this->model::findOrFail($id);  
        $model->update($request->validated());  
        return $model;  
    }  
      
    public function destroy(int $id)  
    {  
        $this->model::findOrFail($id)->delete();  
        return response()->json(['message' => '删除成功']);  
    }  
}

导出 Excel

<?php  
use PhpOffice\PhpSpreadsheet\Spreadsheet;  
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;  
  
class ExportService  
{  
    public function export(array $headers, array $data, string $filename): string  
    {  
        $spreadsheetnew Spreadsheet();  
        $sheet = $spreadsheet->getActiveSheet();  
          
        // 写入表头  
        $col'A';  
        foreach ($headers as $header) {  
            $sheet->setCellValue($col'1', $header);  
            $col++;  
        }  
          
        // 写入数据  
        $row2;  
        foreach ($data as $item) {  
            $col'A';  
            foreach ($item as $value) {  
                $sheet->setCellValue($col . $row, $value);  
                $col++;  
            }  
            $row++;  
        }  
          
        $path = storage_path("exports/{$filename}.xlsx");  
        $writernew Xlsx($spreadsheet);  
        $writer->save($path);  
          
        return $path;  
    }  
}

总结

模块关键点
权限RBAC 模型
菜单树形结构
日志操作记录
字典配置管理

后台系统的核心是权限管理,其他功能根据业务需求扩展。