我想用thinkphp8+layui2.11来开发个后台管理系统,请帮我规划,按最新2025年的技术开发
ThinkPHP8 + Layui2.11 后台管理系统开发规划(2025版)
一、技术栈选型
后端技术栈
- ThinkPHP 8.0.x (PHP 8.1+)
- MySQL 8.0+ / MariaDB 10.6+
- Redis 7.0+ (缓存/队列)
- Composer 2.x (依赖管理)
前端技术栈
- Layui 2.11
- jQuery 3.7+
- ES6+ JavaScript
- CSS3 + Less/Sass
- Axios (Ajax请求)
开发环境
- PHP 8.1+ (推荐 8.2+)
- Nginx 1.24+ / Apache 2.4+
- Node.js 20+ (前端构建工具)
- Git (版本控制)
二、项目目录结构
project/
├── app/ # 应用目录
│ ├── admin/ # 后台模块
│ │ ├── controller/ # 控制器
│ │ │ ├── Auth.php # 登录认证
│ │ │ ├── Index.php # 首页
│ │ │ ├── System.php # 系统管理
│ │ │ ├── User.php # 用户管理
│ │ │ ├── Role.php # 角色管理
│ │ │ └── Menu.php # 菜单管理
│ │ ├── model/ # 模型
│ │ ├── validate/ # 验证器
│ │ ├── service/ # 业务逻辑层
│ │ ├── middleware/ # 中间件
│ │ └── common.php # 公共函数
│ ├── api/ # API模块(可选)
│ ├── common/ # 公共模块
│ │ ├── model/ # 公共模型
│ │ ├── service/ # 公共服务
│ │ └── library/ # 类库
│ ├── ExceptionHandle.php # 异常处理
│ ├── Request.php # 请求类
│ └── event.php # 事件定义
├── config/ # 配置目录
│ ├── app.php # 应用配置
│ ├── cache.php # 缓存配置
│ ├── database.php # 数据库配置
│ ├── filesystem.php # 文件系统
│ ├── log.php # 日志配置
│ ├── middleware.php # 中间件配置
│ └── route.php # 路由配置
├── public/ # 公共资源目录
│ ├── index.php # 入口文件
│ ├── static/ # 静态资源
│ │ ├── admin/ # 后台静态资源
│ │ │ ├── css/
│ │ │ ├── js/
│ │ │ ├── images/
│ │ │ └── layui/ # Layui框架
│ │ └── uploads/ # 上传文件
│ └── .htaccess
├── runtime/ # 运行时目录
├── vendor/ # 第三方类库
├── view/ # 视图目录
│ └── admin/ # 后台视图
│ ├── layout/ # 布局模板
│ │ ├── layout.html # 主布局
│ │ └── iframe.html # iframe布局
│ ├── index/ # 首页视图
│ ├── auth/ # 登录视图
│ ├── user/ # 用户管理
│ ├── role/ # 角色管理
│ └── menu/ # 菜单管理
├── route/ # 路由目录
│ └── admin.php # 后台路由
├── .env # 环境变量
├── composer.json # Composer配置
└── think # 命令行工具
三、核心功能模块
1. 基础架构模块
// 功能清单
✓ 用户认证(JWT Token / Session)
✓ 权限管理(RBAC - 角色权限控制)
✓ 菜单管理(动态菜单树)
✓ 操作日志(用户行为追踪)
✓ 数据字典
✓ 系统配置
✓ 文件上传(本地/OSS)
✓ 定时任务
2. 系统管理模块
✓ 管理员管理
✓ 角色管理
✓ 权限管理
✓ 部门管理
✓ 岗位管理
✓ 菜单管理
✓ 参数配置
✓ 通知公告
3. 监控模块
✓ 在线用户
✓ 操作日志
✓ 登录日志
✓ 系统监控
✓ 数据监控
四、数据库设计
核心数据表
-- 管理员表
CREATE TABLE `admin_user` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '密码',
`nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
`mobile` varchar(20) DEFAULT NULL COMMENT '手机号',
`dept_id` int DEFAULT NULL COMMENT '部门ID',
`status` tinyint DEFAULT '1' COMMENT '状态:0禁用,1正常',
`login_ip` varchar(50) DEFAULT NULL COMMENT '最后登录IP',
`login_time` datetime DEFAULT NULL COMMENT '最后登录时间',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`delete_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管理员表';
-- 角色表
CREATE TABLE `admin_role` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '角色名称',
`code` varchar(50) NOT NULL COMMENT '角色标识',
`sort` int DEFAULT '0' COMMENT '排序',
`status` tinyint DEFAULT '1' COMMENT '状态',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
-- 菜单表
CREATE TABLE `admin_menu` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`pid` int DEFAULT '0' COMMENT '父ID',
`type` tinyint DEFAULT '1' COMMENT '类型:1目录,2菜单,3按钮',
`title` varchar(50) NOT NULL COMMENT '菜单名称',
`icon` varchar(50) DEFAULT NULL COMMENT '图标',
`path` varchar(200) DEFAULT NULL COMMENT '路由地址',
`component` varchar(200) DEFAULT NULL COMMENT '组件路径',
`permission` varchar(100) DEFAULT NULL COMMENT '权限标识',
`sort` int DEFAULT '0' COMMENT '排序',
`visible` tinyint DEFAULT '1' COMMENT '是否显示',
`status` tinyint DEFAULT '1' COMMENT '状态',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜单表';
-- 权限关联表
CREATE TABLE `admin_role_menu` (
`role_id` int NOT NULL,
`menu_id` int NOT NULL,
PRIMARY KEY (`role_id`,`menu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色菜单关联表';
-- 用户角色关联表
CREATE TABLE `admin_user_role` (
`user_id` int NOT NULL,
`role_id` int NOT NULL,
PRIMARY KEY (`user_id`,`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表';
-- 操作日志表
CREATE TABLE `admin_log` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`user_id` int DEFAULT NULL COMMENT '用户ID',
`username` varchar(50) DEFAULT NULL COMMENT '用户名',
`module` varchar(50) DEFAULT NULL COMMENT '模块',
`action` varchar(50) DEFAULT NULL COMMENT '操作',
`method` varchar(20) DEFAULT NULL COMMENT '请求方式',
`url` varchar(500) DEFAULT NULL COMMENT '请求URL',
`ip` varchar(50) DEFAULT NULL COMMENT 'IP地址',
`params` text COMMENT '请求参数',
`result` text COMMENT '返回结果',
`status` tinyint DEFAULT '1' COMMENT '状态:0失败,1成功',
`error_msg` text COMMENT '错误信息',
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='操作日志表';
五、核心代码实现
1. 基础控制器
<?php
// app/admin/controller/Base.php
namespace app\admin\controller;
use think\App;
use think\facade\Session;
abstract class Base
{
protected $app;
protected $request;
protected $middleware = ['auth'];
// 无需登录的方法
protected $noNeedLogin = [];
// 无需权限的方法
protected $noNeedRight = [];
public function __construct(App $app)
{
$this->app = $app;
$this->request = $this->app->request;
// 初始化
$this->initialize();
}
protected function initialize()
{
// 检查登录
$action = $this->request->action();
if (!in_array($action, $this->noNeedLogin)) {
$this->checkLogin();
}
// 检查权限
if (!in_array($action, $this->noNeedRight)) {
$this->checkAuth();
}
}
protected function checkLogin()
{
if (!Session::has('admin_user_id')) {
if ($this->request->isAjax()) {
return json(['code' => 401, 'msg' => '请先登录']);
}
redirect('/admin/auth/login')->send();
exit;
}
}
protected function checkAuth()
{
// 权限验证逻辑
}
protected function success($msg = '操作成功', $data = [], $code = 200)
{
return json(['code' => $code, 'msg' => $msg, 'data' => $data]);
}
protected function error($msg = '操作失败', $data = [], $code = 400)
{
return json(['code' => $code, 'msg' => $msg, 'data' => $data]);
}
}
2. 登录控制器
<?php
// app/admin/controller/Auth.php
namespace app\admin\controller;
use app\admin\model\AdminUser;
use think\facade\Session;
class Auth extends Base
{
protected $noNeedLogin = ['login', 'captcha'];
public function login()
{
if ($this->request->isPost()) {
$username = $this->request->post('username');
$password = $this->request->post('password');
$user = AdminUser::where('username', $username)->find();
if (!$user) {
return $this->error('用户不存在');
}
if (!password_verify($password, $user->password)) {
return $this->error('密码错误');
}
if ($user->status != 1) {
return $this->error('账号已被禁用');
}
// 更新登录信息
$user->login_ip = $this->request->ip();
$user->login_time = date('Y-m-d H:i:s');
$user->save();
// 保存会话
Session::set('admin_user_id', $user->id);
Session::set('admin_username', $user->username);
return $this->success('登录成功', ['url' => '/admin/index/index']);
}
return view();
}
public function logout()
{
Session::clear();
return $this->success('退出成功', ['url' => '/admin/auth/login']);
}
}
3. RBAC权限服务
<?php
// app/common/service/AuthService.php
namespace app\common\service;
use app\admin\model\AdminUser;
use think\facade\Cache;
class AuthService
{
/**
* 获取用户权限
*/
public static function getUserPermissions($userId)
{
$cacheKey = 'user_permissions_' . $userId;
return Cache::remember($cacheKey, function() use ($userId) {
$user = AdminUser::with(['roles.menus'])->find($userId);
$permissions = [];
foreach ($user->roles as $role) {
foreach ($role->menus as $menu) {
if ($menu->permission) {
$permissions[] = $menu->permission;
}
}
}
return array_unique($permissions);
}, 3600);
}
/**
* 检查权限
*/
public static function checkPermission($userId, $permission)
{
$permissions = self::getUserPermissions($userId);
return in_array($permission, $permissions);
}
/**
* 获取用户菜单树
*/
public static function getUserMenuTree($userId)
{
$cacheKey = 'user_menu_tree_' . $userId;
return Cache::remember($cacheKey, function() use ($userId) {
// 查询用户拥有的菜单
$menus = self::getUserMenus($userId);
// 构建树形结构
return self::buildMenuTree($menus);
}, 3600);
}
private static function buildMenuTree($menus, $pid = 0)
{
$tree = [];
foreach ($menus as $menu) {
if ($menu['pid'] == $pid) {
$children = self::buildMenuTree($menus, $menu['id']);
if ($children) {
$menu['children'] = $children;
}
$tree[] = $menu;
}
}
return $tree;
}
}
六、前端布局实现
1. 主布局文件
<!-- view/admin/layout/layout.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{$site_name|default='后台管理系统'}</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/admin/layui/css/layui.css">
<link rel="stylesheet" href="/static/admin/css/admin.css">
</head>
<body>
<div class="layui-layout layui-layout-admin">
<!-- 头部 -->
<div class="layui-header">
<div class="layui-logo layui-hide-xs">
<span>{$site_name|default='后台管理'}</span>
</div>
<ul class="layui-nav layui-layout-left">
<li class="layui-nav-item layadmin-flexible" lay-unselect>
<a href="javascript:;" layadmin-event="flexible" title="侧边伸缩">
<i class="layui-icon layui-icon-shrink-right"></i>
</a>
</li>
</ul>
<ul class="layui-nav layui-layout-right">
<li class="layui-nav-item" lay-unselect>
<a href="javascript:;">
<cite>{:session('admin_username')}</cite>
</a>
<dl class="layui-nav-child">
<dd><a href="/admin/user/profile">基本资料</a></dd>
<dd><a href="/admin/auth/logout">退出</a></dd>
</dl>
</li>
</ul>
</div>
<!-- 侧边菜单 -->
<div class="layui-side layui-side-menu">
<div class="layui-side-scroll">
<div class="layui-logo">
<span>后台系统</span>
</div>
<ul class="layui-nav layui-nav-tree" lay-filter="menu">
{volist name="menus" id="menu"}
<li class="layui-nav-item">
{if condition="isset($menu['children'])"}
<a href="javascript:;">
<i class="layui-icon {$menu.icon}"></i>
<cite>{$menu.title}</cite>
</a>
<dl class="layui-nav-child">
{volist name="menu.children" id="child"}
<dd>
<a href="{$child.path}" lay-id="{$child.id}">
{$child.title}
</a>
</dd>
{/volist}
</dl>
{else/}
<a href="{$menu.path}" lay-id="{$menu.id}">
<i class="layui-icon {$menu.icon}"></i>
<cite>{$menu.title}</cite>
</a>
{/if}
</li>
{/volist}
</ul>
</div>
</div>
<!-- 主体内容 -->
<div class="layui-body">
<div class="layadmin-tabsbody-item layui-show">
<iframe src="/admin/index/home" frameborder="0" class="layadmin-iframe"></iframe>
</div>
</div>
<!-- 底部 -->
<div class="layui-footer">
<p>© 2025 后台管理系统</p>
</div>
</div>
<script src="/static/admin/layui/layui.js"></script>
<script src="/static/admin/js/admin.js"></script>
</body>
</html>
2. 登录页面
<!-- view/admin/auth/login.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登录 - 后台管理系统</title>
<link rel="stylesheet" href="/static/admin/layui/css/layui.css">
<style>
.login-container {
width: 100%;
height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
justify-content: center;
align-items: center;
}
.login-box {
width: 400px;
background: #fff;
border-radius: 8px;
padding: 40px;
box-shadow: 0 15px 25px rgba(0,0,0,.2);
}
.login-title {
text-align: center;
font-size: 24px;
margin-bottom: 30px;
color: #333;
}
</style>
</head>
<body>
<div class="login-container">
<div class="login-box">
<h2 class="login-title">后台管理系统</h2>
<form class="layui-form" lay-filter="loginForm">
<div class="layui-form-item">
<label class="layui-icon layui-icon-username"></label>
<input type="text" name="username" placeholder="用户名"
autocomplete="off" class="layui-input" lay-verify="required">
</div>
<div class="layui-form-item">
<label class="layui-icon layui-icon-password"></label>
<input type="password" name="password" placeholder="密码"
autocomplete="off" class="layui-input" lay-verify="required">
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn-fluid" lay-submit lay-filter="login">
登 录
</button>
</div>
</form>
</div>
</div>
<script src="/static/admin/layui/layui.js"></script>
<script>
layui.use(['form', 'layer'], function(){
var form = layui.form;
var layer = layui.layer;
form.on('submit(login)', function(data){
$.ajax({
url: '/admin/auth/login',
type: 'POST',
data: data.field,
success: function(res) {
if (res.code === 200) {
layer.msg(res.msg, {icon: 1});
setTimeout(function(){
location.href = res.data.url;
}, 1000);
} else {
layer.msg(res.msg, {icon: 2});
}
}
});
return false;
});
});
</script>
</body>
</html>
七、开发规范
1. 命名规范
- 数据库表名:小写+下划线,如 admin_user
- 模型类名:大驼峰,如 AdminUser
- 控制器:大驼峰,如 UserController
- 方法名:小驼峰,如 getUserList
- 变量名:小驼峰,如 $userId
2. 注释规范
/**
* 获取用户列表
* @param int $page 页码
* @param int $limit 每页数量
* @return array
*/
public function getUserList($page = 1, $limit = 10)
{
// 实现代码
}
3. 接口返回规范
{
"code": 200,
"msg": "操作成功",
"data": {},
"timestamp": 1704038400
}
八、安全建议
密码加密:使用
password_hash()和password_verify()防SQL注入:使用参数绑定
XSS防护:输出时使用
htmlspecialchars()CSRF防护:使用Token验证
文件上传:限制文件类型和大小
API接口:使用JWT或签名验证
敏感操作:记录操作日志
定期备份:数据库定时备份
九、性能优化
数据库优化:合理使用索引,避免N+1查询
缓存策略:Redis缓存热点数据
静态资源:CDN加速
代码优化:使用队列处理耗时任务
日志分级:生产环境关闭调试日志
十、部署建议
# 1. 环境要求
PHP >= 8.1
MySQL >= 8.0
Redis >= 7.0
Nginx >= 1.24
# 2. 安装依赖
composer install --no-dev
# 3. 配置权限
chmod -R 755 runtime
chmod -R 755 public/uploads
# 4. 配置伪静态(Nginx)
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
}
}
# 5. 启动队列
php think queue:work
这套方案采用了2025年最新的技术标准,结合了ThinkPHP8的新特性和Layui的UI体验,可以快速构建一个现代化的后台管理系统。需要我详细展开哪个模块的实现吗?
八、安全建议 密码加密:使用 password_hash() 和 password_verify() 防SQL注入:使用参数绑定 XSS防护:输出时使用 htmlspecialchars() CSRF防护:使用Token验证 文件上传:限制文件类型和大小 API接口:使用JWT或签名验证 敏感操作:记录操作日志 定期备份:数据库定时备份 九、性能优化 数据库优化:合理使用索引,避免N+1查询 缓存策略:Redis缓存热点数据 静态资源:CDN加速 代码优化:使用队列处理耗时任务 日志分级:生产环境关闭调试日志 这些你能给出代码吗?左侧导航菜单根据后台登录账号的权限来显示。帮下一个统计的base控制器加强版,主要包括增删查改的功能增强。全局能调用,前端通用头部和脚,每个页面只要写布局就可以了。

根据您的需求,以下是针对安全建议、性能优化、权限控制、增强版Base控制器、全局通用头部和尾部的实现方案:
八、安全建议
1. 密码加密:使用 password_hash() 和 password_verify()
在用户注册时,使用 password_hash() 对密码进行加密存储;在用户登录时,使用 password_verify() 验证密码。
// 注册时
$password = 'user_password';
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
// 登录时
if (password_verify($password, $hashedPassword)) {
// 密码正确
} else {
// 密码错误
}
2. 防SQL注入:使用参数绑定
使用 ThinkPHP 的查询构建器,自动处理参数绑定,防止 SQL 注入。
// 查询用户
$user = Db::name('user')->where('id', $userId)->find();
在此示例中,$userId 会自动绑定,防止 SQL 注入。
3. XSS防护:输出时使用 htmlspecialchars()
在输出用户输入的内容时,使用 htmlspecialchars() 转义特殊字符,防止 XSS 攻击。
// 输出用户评论
echo htmlspecialchars($userComment, ENT_QUOTES, 'UTF-8');
4. CSRF防护:使用 Token 验证
在表单中添加隐藏的 Token 字段,提交时验证 Token,防止 CSRF 攻击。
// 生成 Token
$token = bin2hex(random_bytes(32));
$_SESSION['csrf_token'] = $token;
// 表单中添加隐藏字段
<input type="hidden" name="csrf_token" value="<?= $token ?>">
// 提交时验证 Token
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
// Token 无效,拒绝请求
}
5. 文件上传:限制文件类型和大小
在处理文件上传时,限制文件类型和大小,防止恶意文件上传。
// 允许的文件类型
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
// 最大文件大小(字节)
$maxSize = 2 * 1024 * 1024; // 2MB
// 上传文件
$file = request()->file('image');
if ($file) {
$info = $file->validate(['ext' => 'jpg,png,gif', 'size' => $maxSize])->move('uploads');
if ($info) {
// 上传成功
} else {
// 上传失败
echo $file->getError();
}
}
6. API接口:使用 JWT 或签名验证
使用 JWT(JSON Web Token)进行 API 接口的身份验证。
use \Firebase\JWT\JWT;
// 生成 JWT
$key = 'your_secret_key';
$payload = [
'iss' => 'your_issuer',
'aud' => 'your_audience',
'iat' => time(),
'exp' => time() + 3600, // 1小时有效期
'data' => [
'userId' => $userId,
'username' => $username,
],
];
$jwt = JWT::encode($payload, $key);
// 验证 JWT
try {
$decoded = JWT::decode($jwt, $key, ['HS256']);
// 验证通过
} catch (Exception $e) {
// 验证失败
}
请注意,使用 JWT 时需要安装 firebase/php-jwt 库。
7. 敏感操作:记录操作日志
在执行敏感操作时,记录操作日志,便于追踪和审计。
// 记录操作日志
Db::name('operation_log')->insert([
'user_id' => $userId,
'action' => 'delete_user',
'target_id' => $targetUserId,
'created_at' => date('Y-m-d H:i:s'),
]);
8. 定期备份:数据库定时备份
使用定时任务(如 cron)定期备份数据库。
# 每天凌晨2点备份数据库
0 2 * * * mysqldump -u username -p'password' database_name > /path/to/backup/database_name_$(date +\%F).sql
九、性能优化
1. 数据库优化:合理使用索引,避免 N+1 查询
确保数据库表有适当的索引,避免在循环中进行多次查询(N+1 查询问题)。
// 使用关联查询,避免 N+1 查询
$users = Db::name('user')
->alias('u')
->join('profile p', 'u.id = p.user_id')
->select();
2. 缓存策略:Redis 缓存热点数据
使用 Redis 缓存频繁访问的数据,减少数据库压力。
use think\facade\Cache;
// 设置缓存
Cache::set('user_profile_' . $userId, $profileData, 3600);
// 获取缓存
$profileData = Cache::get('user_profile_' . $userId);
if (!$profileData) {
// 缓存不存在,查询数据库并更新缓存
$profileData = Db::name('profile')->where('user_id', $userId)->find();
Cache::set('user_profile_' . $userId, $profileData, 3600);
}
3. 静态资源:CDN 加速
将静态资源(如图片、CSS、JS)托管到 CDN,提升加载速度。
<!-- 使用 CDN 加载 jQuery -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
4. 代码优化:使用队列处理耗时任务
将耗时的任务(如发送邮件、生成报告)放入队列,异步处理。
use think\queue\Job;
// 发送邮件任务
class SendEmailJob
{
public function fire(Job $job, $data)
{
// 发送邮件逻辑
// 如果发送成功,调用 $job->delete() 删除任务
// 如果失败,调用 $job->release() 重新放入队列
}
}
// 将任务推入队列
Queue::push(SendEmailJob::class, ['email' => $userEmail]);
5. 日志分级:生产环境关闭调试日志
在生产环境中,关闭调试日志,减少性能开销。
// config/log.php
return [
'default' => [
'type' => 'File',
'path' => LOG_PATH,
'level' => ['error', 'warning'],
],
];
十、权限控制:根据后台登录账号的权限显示左侧导航菜单
根据用户角色和权限动态生成左侧导航菜单。
// 获取用户角色和权限
$userRoles = Db::name('user_role')->where('user_id', $userId)->column('role_id');
$permissions = Db::name('role_permission')->whereIn('role_id', $userRoles)->column('permission');
// 获取菜单
$menus = Db::name('menu')->whereIn('permission', $permissions)->order('sort')->select();
// 构建菜单树
$menuTree = buildMenuTree($menus);
// 传递给视图
View::assign('menuTree', $menuTree);
十一、增强版 Base 控制器
提供通用的增删查改功能,方便各个控制器继承使用。
// app/admin/controller/BaseController.php
namespace app\admin\controller;
use think\Controller;
use think\Request;
use think\Db;
class BaseController extends Controller
{
protected $model;
public function __construct(Request $request)
{
parent::__construct($request);
$this->model = Db::name($this->getModelName());
}
// 获取模型名称
protected function getModelName()
{
$controller = $this->request->controller();
return strtolower(preg_replace('/Controller$/', '', $controller));
}
// 列表
public function index()
{
$data = $this->model->select();
return json(['data' => $data]);
}
// 详情
public function read($id)
{
$data = $this->model->find($id);
return json(['data' => $data]);
}
// 创建
public function create()
{
$data = $this->request->post();
$id = $this->model->insertGetId($data);
return json(['id' => $id]);
}
// 更新
public function update($id)
{
$data = $this->request->put();
$this->model->where('id', $id)->update($data);
return json(['message' => '更新成功']);
}
// 删除
public function delete($id)
{
$this->model->where('id', $id)->delete();
return json(['message' => '删除成功']);
}
}
各个控制器继承 BaseController,即可使用通用的增删查改功能。
十二、全局通用头部和尾部
在视图中引入通用的头部和尾部模板,减少重复代码。
<!-- 引入头
评论区