主要实现登录退出功能,用户模块的增删改查功能,分页功能是layui表单自带功能
效果图
左侧的菜单栏我没有写对应的页面,需要的自己添加上就行,把菜单弄出来主要是为了好看一点
目录结构
thinkphp6+layui
layui实现后台布局
中间件和session判断用户是否登录
用到think-template模板引擎,安装完tp框架后需要自己安装
composer create-project topthink/think=6.0.x-dev tp
composer require topthink/think-view
ajax请求数据
msyql数据库
登录页面,相关的请求方法都写在了页面中
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录页面title>
<link rel="stylesheet" href="/layui/css/layui.css">
<script src="/layui/layui.js">script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Arial', sans-serif;
background-color: #f0f2f5;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.login-container {
width: 450px;
padding: 2rem;
background-color: #ffffff;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h1 {
color: #333333;
text-align: center;
margin-bottom: 1.5rem;
}
label {
color: #333333;
margin-bottom: 0.5rem;
}
input.layui-input {
height: 40px;
padding: 0 1rem;
margin-bottom: 1.5rem;
border: 1px solid #d9d9d9;
border-radius: 5px;
}
button.layui-btn {
height: 40px;
color: #ffffff;
background-color: #3498db;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
}
button.layui-btn:hover {
background-color: #2980b9;
}
style>
head>
<body>
<div class="login-container">
<h1>登录h1>
<form class="layui-form" action="/admin/index" method="post">
<div class="layui-form-item">
<label for="username" class="layui-form-label">用户名:label>
<div class="layui-input-block">
<input type="text" id="username" name="username" placeholder="请输入用户名" required lay-verify="required" autocomplete="off" class="layui-input">
div>
div>
<div class="layui-form-item">
<label for="password" class="layui-form-label">密码:label>
<div class="layui-input-block">
<input type="password" id="password" name="password" placeholder="请输入密码" required lay-verify="required" autocomplete="off" class="layui-input">
div>
div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="login">登录button>
div>
div>
form>
div>
DOCTYPE html>
<script>
layui.use(['form', 'layer'], function () {
var form = layui.form;
var layer = layui.layer;
form.on('submit(login)', function(data){
console.log(data);
});
});
script>
body>
html>
后台布局,layui.js和layui.css改成自己的
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Layuititle>
<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, maximum-scale=1">
<link rel="stylesheet" href="/layui/css/layui.css" media="all">
head>
<body>
<table class="layui-hide" id="test" lay-filter="test">table>
<div id="edit-form" style="display:none;">
<form class="layui-form" action="" lay-filter="" id="${id}">
<div class="layui-form-item">
<label class="layui-form-label">Idlabel>
<div class="layui-input-block">
<input type="text" name="id" required lay-verify="required" autocomplete="off" class="layui-input" value="..."
disabled>
div>
div>
<div class="layui-form-item">
<label class="layui-form-label">用户名label>
<div class="layui-input-block">
<input type="text" name="username" required lay-verify="required" autocomplete="off" class="layui-input"
value="...">
div>
div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱label>
<div class="layui-input-block">
<input type="text" name="email" required lay-verify="required" autocomplete="off" class="layui-input"
value="...">
div>
div>
<div class="layui-form-item">
<label class="layui-form-label">地址label>
<div class="layui-input-block">
<input type="text" name="address" required lay-verify="required" autocomplete="off" class="layui-input"
value="...">
div>
div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="editSubmit">修改button>
<button type="reset" class="layui-btn layui-btn-primary">重置button>
div>
div>
form>
div>
<div id="add-form" style="display:none;">
<form class="layui-form" action="">
<div class="layui-form-item">
<label class="layui-form-label">用户名label>
<div class="layui-input-block">
<input type="text" name="username" lay-verify="required" placeholder="请输入用户名" autocomplete="off"
class="layui-input">
div>
div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱label>
<div class="layui-input-block">
<input type="text" name="email" lay-verify="required|email" placeholder="请输入邮箱" autocomplete="off"
class="layui-input">
div>
div>
<div class="layui-form-item">
<label class="layui-form-label">地址label>
<div class="layui-input-block">
<input type="text" name="address" lay-verify="required" placeholder="请输入地址" autocomplete="off"
class="layui-input">
div>
div>
<div class="layui-form-item">
div>
form>
div>
<script type="text/html" id="toolbarDemo">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-sm" lay-event="getCheckData">获取选中行数据</button>
<button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="getCheckLength">获取选中数目</button>
<button class="layui-btn layui-btn-sm layui-btn-warm" lay-event="isAll">验证是否全选</button>
<button class="layui-btn layui-btn-sm layui-btn-normal" lay-event="add">添加用户</button>
</div>
script>
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
script>
<script src="/layui/layui.js" charset="utf-8">script>
<script>
var userListData = JSON.parse('{:json_encode($userList)}');
layui.use('table', function () {
var table = layui.table;
var $ = layui.jquery;
table.render({
elem: '#test'
, data: userListData
, toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板
, defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可
title: '提示'
, layEvent: 'LAYTABLE_TIPS'
, icon: 'layui-icon-tips'
}]
, title: '用户数据表'
, cols: [[
{ type: 'checkbox', fixed: 'left' },
{ field: 'id', title: 'ID', width: 80, fixed: 'left', unresize: true, sort: true, align: 'center' },
{ field: 'username', title: '用户名', align: 'center', width: 120 },
{ field: 'email', title: '邮箱', align: 'center' },
{ field: 'address', title: '地址', align: 'center' },
{ fixed: 'right', title: '操作', toolbar: '#barDemo', align: 'center' }
]]
, page: true
});
//头工具栏事件
table.on('toolbar(test)', function (obj) {
var checkStatus = table.checkStatus(obj.config.id);
switch (obj.event) {
case 'getCheckData':
var data = checkStatus.data;
layer.alert(JSON.stringify(data));
break;
case 'getCheckLength':
var data = checkStatus.data;
layer.msg('选中了:' + data.length + ' 个');
break;
case 'isAll':
layer.msg(checkStatus.isAll ? '全选' : '未全选');
break;
case 'add':
layer.open({
type: 1,
title: '新增用户',
content: $('#add-form').html(), // 从页面中获取表单内容
area: ['500px', '320px'],
btn: ['提交', '取消'],
yes: function (index, layero) {
// 点击“提交”按钮时的回调函数
var data = layero.find('form').serialize();
// 发送表单数据到后端
$.post('/admin/addUser', data, function (res) {
if (res.success) {
layer.msg(res.message);
// 关闭弹出层
layer.close(index);
// 重新加载数据表格
setTimeout(function () {
window.location.reload();
}, 2000);
table.reload('test', {});
} else {
layer.msg(res.message);
}
}).fail(function () {
layer.msg('请求失败,请重试');
});
}
});
};
});
//监听行工具事件,删除事件
table.on('tool(test)', function (obj) {
var data = obj.data;
if (obj.event === 'del') {
var id = data.id;
// 弹出确认框
layer.confirm('确定要删除该用户吗?', function (index) {
// 用户点击了确定按钮,关闭确认框
layer.close(index);
// 使用Layui的内置jQuery发送POST请求
$.post('/admin/deleteUserById', { id: id }, function (res) {
if (res.success) {
obj.del(); // 如果删除成功,从表格中删除行
} else {
layer.msg('删除失败');
}
}).fail(function () {
layer.msg('请求失败,请重试');
});
});
} else {
// 弹出编辑层
layer.open({
type: 1,
title: '编辑用户信息',
content: $('#edit-form').html(), // 从页面中获取表单内容
area: ['500px', '320px'],
success: function (layero, index) {
// 将用户数据填充到表单元素中
layero.find('input[name="id"]').val(data.id);
layero.find('input[name="username"]').val(data.username);
layero.find('input[name="email"]').val(data.email);
layero.find('input[name="address"]').val(data.address);
}
});
}
});
// 监听编辑表单提交事件
layui.form.on('submit(editSubmit)', function (data) {
// 发送表单数据到后端
$.post('/admin/updateUserById', data.field, function (res) {
console.log(res);
if (res.success) {
layer.msg(res.message);
// 关闭弹出层
layer.closeAll('page');
// 刷新页面重新加载表格
setTimeout(function () {
window.location.reload();
}, 2000);
} else {
layer.msg('更新失败');
}
}).fail(function () {
layer.msg('请求失败,请重试');
});
return false; // 阻止表单提交
});
});
script>
body>
html>
用户列表
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Layuititle>
<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, maximum-scale=1">
<link rel="stylesheet" href="/layui/css/layui.css" media="all">
head>
<body>
<table class="layui-hide" id="test" lay-filter="test">table>
<div id="edit-form" style="display:none;">
<form class="layui-form" action="" lay-filter="" id="${id}">
<div class="layui-form-item">
<label class="layui-form-label">Idlabel>
<div class="layui-input-block">
<input type="text" name="id" required lay-verify="required" autocomplete="off" class="layui-input" value="..."
disabled>
div>
div>
<div class="layui-form-item">
<label class="layui-form-label">用户名label>
<div class="layui-input-block">
<input type="text" name="username" required lay-verify="required" autocomplete="off" class="layui-input"
value="...">
div>
div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱label>
<div class="layui-input-block">
<input type="text" name="email" required lay-verify="required" autocomplete="off" class="layui-input"
value="...">
div>
div>
<div class="layui-form-item">
<label class="layui-form-label">地址label>
<div class="layui-input-block">
<input type="text" name="address" required lay-verify="required" autocomplete="off" class="layui-input"
value="...">
div>
div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="editSubmit">修改button>
<button type="reset" class="layui-btn layui-btn-primary">重置button>
div>
div>
form>
div>
<div id="add-form" style="display:none;">
<form class="layui-form" action="">
<div class="layui-form-item">
<label class="layui-form-label">用户名label>
<div class="layui-input-block">
<input type="text" name="username" lay-verify="required" placeholder="请输入用户名" autocomplete="off"
class="layui-input">
div>
div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱label>
<div class="layui-input-block">
<input type="text" name="email" lay-verify="required|email" placeholder="请输入邮箱" autocomplete="off"
class="layui-input">
div>
div>
<div class="layui-form-item">
<label class="layui-form-label">地址label>
<div class="layui-input-block">
<input type="text" name="address" lay-verify="required" placeholder="请输入地址" autocomplete="off"
class="layui-input">
div>
div>
<div class="layui-form-item">
div>
form>
div>
<script type="text/html" id="toolbarDemo">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-sm" lay-event="getCheckData">获取选中行数据</button>
<button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="getCheckLength">获取选中数目</button>
<button class="layui-btn layui-btn-sm layui-btn-warm" lay-event="isAll">验证是否全选</button>
<button class="layui-btn layui-btn-sm layui-btn-normal" lay-event="add">添加用户</button>
</div>
script>
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
script>
<script src="/layui/layui.js" charset="utf-8">script>
<script>
var userListData = JSON.parse('{:json_encode($userList)}');
layui.use('table', function () {
var table = layui.table;
var $ = layui.jquery;
table.render({
elem: '#test'
, data: userListData
, toolbar: '#toolbarDemo' //开启头部工具栏,并为其绑定左侧模板
, defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可
title: '提示'
, layEvent: 'LAYTABLE_TIPS'
, icon: 'layui-icon-tips'
}]
, title: '用户数据表'
, cols: [[
{ type: 'checkbox', fixed: 'left' },
{ field: 'id', title: 'ID', width: 80, fixed: 'left', unresize: true, sort: true, align: 'center' },
{ field: 'username', title: '用户名', align: 'center', width: 120 },
{ field: 'email', title: '邮箱', align: 'center' },
{ field: 'address', title: '地址', align: 'center' },
{ fixed: 'right', title: '操作', toolbar: '#barDemo', align: 'center' }
]]
, page: true
});
//头工具栏事件
table.on('toolbar(test)', function (obj) {
var checkStatus = table.checkStatus(obj.config.id);
switch (obj.event) {
case 'getCheckData':
var data = checkStatus.data;
layer.alert(JSON.stringify(data));
break;
case 'getCheckLength':
var data = checkStatus.data;
layer.msg('选中了:' + data.length + ' 个');
break;
case 'isAll':
layer.msg(checkStatus.isAll ? '全选' : '未全选');
break;
case 'add':
layer.open({
type: 1,
title: '新增用户',
content: $('#add-form').html(), // 从页面中获取表单内容
area: ['500px', '320px'],
btn: ['提交', '取消'],
yes: function (index, layero) {
// 点击“提交”按钮时的回调函数
var data = layero.find('form').serialize();
// 发送表单数据到后端
$.post('/admin/addUser', data, function (res) {
if (res.success) {
layer.msg(res.message);
// 关闭弹出层
layer.close(index);
// 重新加载数据表格
setTimeout(function () {
window.location.reload();
}, 2000);
table.reload('test', {});
} else {
layer.msg(res.message);
}
}).fail(function () {
layer.msg('请求失败,请重试');
});
}
});
};
});
//监听行工具事件,删除事件
table.on('tool(test)', function (obj) {
var data = obj.data;
if (obj.event === 'del') {
var id = data.id;
// 弹出确认框
layer.confirm('确定要删除该用户吗?', function (index) {
// 用户点击了确定按钮,关闭确认框
layer.close(index);
// 使用Layui的内置jQuery发送POST请求
$.post('/admin/deleteUserById', { id: id }, function (res) {
if (res.success) {
obj.del(); // 如果删除成功,从表格中删除行
} else {
layer.msg('删除失败');
}
}).fail(function () {
layer.msg('请求失败,请重试');
});
});
} else {
// 弹出编辑层
layer.open({
type: 1,
title: '编辑用户信息',
content: $('#edit-form').html(), // 从页面中获取表单内容
area: ['500px', '320px'],
success: function (layero, index) {
// 将用户数据填充到表单元素中
layero.find('input[name="id"]').val(data.id);
layero.find('input[name="username"]').val(data.username);
layero.find('input[name="email"]').val(data.email);
layero.find('input[name="address"]').val(data.address);
}
});
}
});
// 监听编辑表单提交事件
layui.form.on('submit(editSubmit)', function (data) {
// 发送表单数据到后端
$.post('/admin/updateUserById', data.field, function (res) {
console.log(res);
if (res.success) {
layer.msg(res.message);
// 关闭弹出层
layer.closeAll('page');
// 刷新页面重新加载表格
setTimeout(function () {
window.location.reload();
}, 2000);
} else {
layer.msg('更新失败');
}
}).fail(function () {
layer.msg('请求失败,请重试');
});
return false; // 阻止表单提交
});
});
script>
body>
html>
后端代码
Index.php
这个文件没有什么好说的,就是访问index/index的时候渲染登录页面
namespace app\controller;
use app\BaseController;
use think\facade\View;
class Index extends BaseController
{
public function index()
{
return View::fetch();
}
public function hello($name = 'ThinkPHP6')
{
return 'hello,' . $name;
}
}
Admin.php控制器
这个控制器中,首先index登录页面请求index方法判断用户名密码,用户名密码正确后渲染后台主页
用户名密码不正确重定向到登录页面
同时增删改查功能也是在这个控制器内完成的,但这些功能都需要经过中间件CheckLogin判断session是否存在,就是用户是否登录
namespace app\controller;
use app\BaseController;
use think\facade\View;
use think\facade\Request;
use app\model\User;
use think\facade\Session;
use app\middleware\CheckLogin;
use app\model\UserList;
class admin extends BaseController
{
protected $middleware = [CheckLogin::class => ['except' => ['index']]]; //当执行admin控制器的时候就会调用CheckLogin中间件
public function index()
{
$username = Request::post('username');
$password = Request::post('password');
$res = User::where('username', $username)->find();
// 判断用户是否存在,以及密码是否正确
if ($res && $res->password == md5($password)) {
// 存储用户信息到session中
Session::set('res', $res);
View::assign('res', $res);
return View::fetch();
} else {
// 密码不正确,重定向到登录页面
return redirect('../Index/index')->with('error', '用户名或密码错误');
}
}
public function logout()
{
session_destroy();
return redirect('../Index/index')->with('error', '退出成功');
}
public function userList()
{
$list = UserList::select();
// 分配数据给模板
View::assign('userList', $list);
// 渲染模板并返回
return View::fetch();
}
public function deleteUserById()
{
$id = Request::post('id');
$res = UserList::destroy($id);
if ($res) {
return json(['success' => true, 'message' => '删除成功']);
} else {
return json(['success' => false, 'message' => '删除失败']);
}
}
public function updateUserById(){
$id = Request::post('id');
$username = Request::post('username');
$email = Request::post('email');
$address = Request::post('address');
$res = UserList::update(['username'=>$username,'email'=>$email,'address'=>$address,'id' => $id]);
try {
$res = UserList::update(['username'=>$username,'email'=>$email,'address'=>$address,'id' => $id]);
if ($res) {
return json(['success' => true, 'message' => '更新成功']);
} else {
return json(['success' => false, 'message' => '更新失败']);
}
} catch (\Exception $e) {
return json(['success' => false, 'message' => $e->getMessage()]);
}
}
public function addUser(){
$res = UserList::create([
'username'=>Request::post('username'),
'email'=>Request::post('email'),
'address'=>Request::post('address')
]);
if ($res) {
return json(['success' => true, 'message' => '添加成功']);
} else {
return json(['success' => false, 'message' => '添加失败']);
}
}
}
中间件代码CheckLogin.php代码
//判断用户是否登录的中间件
namespace app\middleware;
use think\facade\Session;
class CheckLogin
{
public function handle($request,$next)
{
// 判断session是否存在
// if (Session::has('user')) { //设置的时候就设置了res,不要来读的时候就干个user在上面
if (Session::has('res')) {
// 如果session存在,继续执行后续请求
return $next($request);
} else {
// 如果session不存在,重定向到登录页
return redirect('../Index/index');
}
}
}
模型类,在这个案例中我们定义了两个模型类
一个是User模型类,就是管理员数据,另一个是UserList类就是展示在页面上的数据,我们增删改查需要操作的数据
User模型
namespace app\model;
use think\Model;
class User extends Model{
protected $name = 'user';
protected $pk = 'id';
}
UserList模型
namespace app\model;
use think\Model;
class UserList extends Model{
protected $name = 'user_list';
protected $pk = 'id';
}
这个案例并没有用到路由模块,有需要用路由的自己去配置即可,router/app.php中
数据库就两个表
user和user_list
使用tp操作数据库前请先确保配置了数据库连接,开发环境跟目录下.env文件
生产环境config/database.php如果不知道是开发环境还是生产环境两个都改一下
表的结构
完结!