1.前端渲染页:index.php
<?php
session_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户管理系统</title>
<link rel="stylesheet" href="style.css">
<style>
header {
display: flex;
background-color: #333;
padding: 0.5em 1em;
width: 100%;
}
a {
color: #bbb;
text-decoration: none;
}
a:hover {
color: white;
}
header nav {
margin-left: auto;
}
</style>
</head>
<body>
<header>
<a href="#">首页</a>
<nav>
<?php if (!isset($_SESSION['email'])) : ?>
<script>
alert('请登录后再操作!');
location.href = "login.php";
</script>
<?php else : ?>
<a href="#" class="ses"><?= $_SESSION['email'] ?></a>
<a href="handle.php?action=logout">退出</a>
<?php endif ?>
</nav>
</header>
<table>
<caption>用户管理 <span class="tips" style="color:red;font-size:10px;"></span></caption>
<thead>
<tr>
<td>UID</td>
<td>用户名</td>
<td>邮箱</td>
<td>注册时间</td>
<?php if ($_SESSION['email'] === 'guest1@php.cn') : ?>
<td>操作</td>
<? endif ?>
</tr>
</thead>
<!-- 列表渲染 -->
<tbody></tbody>
</table>
<!-- 分页渲染 -->
<p></p>
<!-- 模态框编辑 -->
<div class="md">
<div class="md-drop"></div>
<div class="md-body">
<button class="close">关闭</button>
<form action="" name="editform">
<h2>编辑用户</h2>
<div class="md-login">
<label for="name">姓名:</label>
<input type="text" name="name" id="name" value="">
<label for="email">邮箱:</label>
<input type="email" name="email" id="email" value="">
<button class="save">保存</button>
</div>
</form>
</div>
</div>
<!-- 模态框样式 -->
<style>
/* 模态框初始化隐藏 */
.md {
display: none;
}
/* 遮罩层 */
.md .md-drop {
position: fixed;
background-color: rgb(0, 0, 0, .5);
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.md .md-body {
position: fixed;
background-color: lightcyan;
padding: 1em;
overflow: hidden;
max-width: 25em;
max-height: 20em;
/* 水平垂直居中 */
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
border-radius: 10px;
}
/* 关闭按钮 */
.md .md-body .close {
float: right;
height: 2.5em;
width: 3em;
border: 0;
border-radius: 0.5em;
outline: none;
background-color: rgb(1, 231, 135);
}
.md .md-login {
display: grid;
gap: 1em;
margin-top: 20px;
}
</style>
<script src="ajax.js"></script>
</body>
</html>
2. 登录页:login.php
<?php
session_start();
if(isset($_SESSION['email'])) {
echo '<script>alert("请不要重复登录");location.href="index.php";</script>';
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录</title>
<style>
form {
display: grid;
gap: .5em;
width: 15em;
margin: 2em auto;
border: 1px solid #eee;
padding: 1em 2em;
background-color: lightskyblue;
border-radius: 0.5em;
}
</style>
</head>
<body>
<form name="login">
<span>用户登录</span>
<input type="email" name="email" placeholder="请输入登录邮箱">
<input type="password" name="password" placeholder="请输入登录密码">
<!-- 此处给button类型防止默认提交 -->
<button type="button" name="submit">立即登录</button>
<button type="button" name="registers">新用户注册</button>
<span class="tips"></span>
</form>
<script>
const form = document.forms.login;
const email = form.email;
const psw = form.password;
const submitBtn = form.submit;
const xhr = new XMLHttpRequest;
const tips = document.querySelector('.tips');
const regis = form.registers;
regis.onclick = (ev) => {
location.href = 'register.php';
}
submitBtn.onclick = (ev) => {
// 非空判断
if (email.value.trim().length > 0 && psw.value.trim().length >0) {
// 请求参数
xhr.open('post','handle.php?action=login');
// 响应类型
// 设置类型为json,返回结果自动解析为js对象
xhr.responseType = 'json';
// 成功回调
xhr.onload = () => {
console.log(xhr.response);
tips.innerHTML = xhr.response.msg;
if (xhr.response.status === 1 ) {
// 登录成功进入用户管理页
setTimeout(() => location.href = 'index.php',3000);
}
}
// 失败回调
xhr.onerror = () => console.log('error!');
// 发送请求
xhr.send(new FormData(form));
} else {
tips.innerHTML = '账户信息不能为空!';
email.focus();
}
}
// 清空提示
[email,psw].forEach((item)=>item.oninput = () => tips.innerHTML = null);
</script>
</body>
</html>
3. 注册页:register.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新用户注册</title>
<style>
form {
display: grid;
gap: .5em;
width: 15em;
margin: 2em auto;
border: 1px solid #eee;
padding: 1em 2em;
background-color: lightskyblue;
border-radius: 0.5em;
}
</style>
</head>
<body>
<form name="register">
<span>新用户注册</span>
<input type="text" name="name" placeholder="请输入用户名">
<input type="email" name="email" placeholder="请输入登录邮箱">
<input type="password" name="password1" placeholder="请输入登录密码">
<input type="password" name="password2" placeholder="确认登录密码">
<!-- 此处给button类型防止默认提交 -->
<button type="button" name="submit">立即注册</button>
<span class="tips"></span>
</form>
<script>
const form = document.forms.register;
const name = form.name;
const email = form.email;
const psw1 = form.password1;
const psw2 = form.password2;
const submitBtn = form.submit;
const xhr = new XMLHttpRequest;
const tips = document.querySelector('.tips');
submitBtn.onclick = (ev) => {
// 非空判断
if (name.value.trim().length > 0 && email.value.trim().length > 0 && psw1.value.trim().length >0) {
if (psw1.value !== psw2.value) {
tips.innerHTML = '确认密码输入不一致!';
psw1.focus();
} else {
// 请求参数
xhr.open('post','handle.php?action=register');
// 响应类型
// 设置类型为json,返回结果自动解析为js对象
xhr.responseType = 'json';
// 成功回调
xhr.onload = () => {
console.log(xhr.response);
tips.innerHTML = xhr.response.msg;
if (xhr.response.status === 1 ) {
// 注册成功进入用户管理页
setTimeout(() => location.href = 'index.php',3000);
}
}
// 失败回调
xhr.onerror = () => console.log('error!');
// 确认密码不需要发送
const data = new FormData(form);
data.delete('password2');
// 发送请求
xhr.send(data);
}
} else {
tips.innerHTML = '账户信息不能为空!';
name.focus();
}
}
// 清空提示
[name,email,psw1,psw2].forEach((item)=>item.oninput = () => tips.innerHTML = null);
</script>
</body>
</html>
4. css样式表:style.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
color: #555;
}
body {
display: flex;
flex-direction: column;
align-items: center;
}
/*表格样式*/
table {
width: 90%;
border: 1px solid;
border-collapse: collapse;
text-align: center;
}
table caption {
font-size: 1.2rem;
margin: 10px;
}
table td,
table th {
border: 1px solid;
padding: 5px;
}
table tr:hover {
background-color: #eee;
}
table thead tr:only-of-type {
background-color: lightcyan;
}
table button {
width: 56px;
height: 26px;
}
table button:last-of-type {
color: red;
}
table button {
cursor: pointer;
margin: 0 3px;
}
/*分页条样式*/
body > p {
display: flex;
}
p > a {
text-decoration: none;
color: #555;
border: 1px solid #888;
padding: 5px 10px;
margin: 10px 2px;
}
.active {
background-color: seagreen;
color: white;
border: 1px solid seagreen;
}
5. js文件:ajax.js
// 页面载入完成时渲染第一页数据
window.onload = function () {
select(1);
};
// 编辑
document.querySelector('table:first-of-type tbody').addEventListener('click' , ev => {
// 获取记录id
const sid = ev.target.parentNode.parentNode.querySelector('td').textContent * 1;
const tips = document.querySelector('.tips');
// 操作类型
switch (ev.target.textContent) {
case '编辑':
// 显示模态框
document.querySelector('.md').style.display = 'block';
// 点击关闭按钮
document.querySelector('.md .close').addEventListener('click',(eve) => {
document.querySelector('.md').style.display = 'none';
});
// 点击模态框之外区域
document.querySelector('.md .md-drop').addEventListener('click',(eve) => {
document.querySelector('.md').style.display = 'none';
});
// 获取数据
let name = ev.target.parentNode.parentNode.querySelector('td:nth-of-type(2)').textContent;
let email = ev.target.parentNode.parentNode.querySelector('td:nth-of-type(3)').textContent;
// 渲染到模态框
document.getElementById('name').value = name;
document.getElementById('email').value = email;
// 编辑事件
document.querySelector('.md .save').addEventListener('click',(eve) => {
// 禁止默认提交
eve.preventDefault();
// 获取模态框数据
name = document.getElementById('name').value;
email = document.getElementById('email').value;
// 创建对象
let xhr = new XMLHttpRequest();
// 配置参数
xhr.open('post','api.php?action=update&sid=' + sid);
xhr.responseType = 'json';
// 处理请求
xhr.onload = () => {
// 更新数据写会页面
tips.innerHTML = xhr.response.msg;
if (xhr.response.status === 1 ) {
document.querySelector('.md').style.display = 'none';
ev.target.parentNode.parentNode.querySelector('td:nth-of-type(2)').textContent = name;
ev.target.parentNode.parentNode.querySelector('td:nth-of-type(3)').textContent = email;
setTimeout(() => tips.innerHTML = null,2000);
}
};
xhr.send(new FormData(document.forms.namedItem('editform')));
});
break;
case '删除':
if (confirm('确认删除UID:' + sid + '用户?')) {
// 创建对象
let xhr = new XMLHttpRequest();
// 配置参数
xhr.open('get','api.php?action=delete&sid=' + sid);
xhr.responseType = 'json';
// 处理请求
xhr.onload = () => {
tips.innerHTML = xhr.response.msg;
if (xhr.response.status === 1) {
// 删除节点
ev.target.parentNode.parentNode.remove();
setTimeout(() => tips.innerHTML = null,2000);
}
};
// 发送请求
xhr.send(null);
}
break;
}
})
function select(page = 1) {
// 创建对象
const xhr = new XMLHttpRequest();
// 配置参数
xhr.open('get', 'api.php?action=select&page=' + page);
// 处理请求
xhr.onload = () => {
// console.log(xhr.response);
let res = JSON.parse(xhr.response);
let pages = res.pages;
let users = res.users;
// 渲染数据
document.querySelector('table:first-of-type tbody').innerHTML = get_datas(users);
// 渲染分页
document.querySelector('p:first-of-type').innerHTML = pags(page,pages);
}
// 发送请求
xhr.send(null);
}
// 渲染数据
function get_datas(datas) {
const ses = document.querySelector('.ses').innerText;
let str = '';
for (let i = 0; i < datas.length; i++) {
str += '<tr>';
str += '<td>' + datas[i]['sid'] + '</td>';
str += '<td>' + datas[i]['name'] + '</td>';
str += '<td>' + datas[i]['email'] + '</td>';
str += '<td>' + datas[i]['create_at'] + '</td>';
if (ses=== 'guest1@php.cn') {
str += '<td><button>编辑</button><button>删除</button></td>';
}
str += '</tr>';
}
return str;
}
// 无刷新分页
document.querySelector('p:first-of-type').addEventListener('click',ev => {
// 禁用默认跳转
ev.preventDefault();
// 点击当前激活页,无效点击
if (ev.target.classList.contains('active')) return;
// 去掉激活样式
[...ev.currentTarget.children].forEach(ele => ele.classList.remove('active'));
// 当前页添加激活样式
ev.target.classList.add('active');
let url = ev.target.href,page;
// 获取页码
if (url.indexOf('?') !== -1) {
page = url.split('=')[1];
} else {
page = 1;
}
select(page);
})
// 分页数据
function pags (page = 1,pages) {
let pag = '';
let active = '';
// 首页和上一页
if (page <= 1) page =1;
if (page != 1) {
pag += '<a href="'+ document.URL + '?p=1">首页</a>';
pag += '<a href="'+ document.URL + '?p=' + Math.max(1,page - 1) +'">上一页</a>';
}
// 高亮分页
for (i = 1; i <= pages; i++ ) {
active = '';
if (page == i) active = 'class="active"';
pag += '<a href="' + document.URL + '?p=' + i + '"' + active + '>' + i + '</a>';
}
// 下一页和尾页
if (page >= pages) page = pages;
if (page !== pages) {
pag += '<a href="' + document.URL + '?p=' + Math.min(page + 1,pages) + '">下一页</a>'
pag += '<a href="' + document.URL + '?p=' + pages +'">尾页</a>'
}
return pag;
}
6. 文件:api.php
$config = [
'type' => 'mysql',
'host' => '127.0.0.1',
'dbname' => 'phpedu',
'username' => 'root',
'password' => '123456',
];
extract($config);
$dsn = sprintf('%s:host=%s;dbname=%s;',$type,$host,$dbname);
try {
$pdo = new PDO($dsn,$username,$password);
// 设置结果集返回类型
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC);
// var_dump($pdo,'连接成功');
} catch (PDOException $e){
die('连接失败:'. $e->getMessage());
}
// 页码通过get请求
$page = $_GET['page'] ?? 1;
$action = $_GET['action'] ?? 'select';
switch ($action) {
// 查询
case 'select':
die(get_datas($pdo,$page));
break;
// 删
case 'delete':
die(del_data($pdo,$_GET['sid'] ?? 0));
break;
// 更新
case 'update':
$sid = $_GET['sid'] ?? 0;
$name = $_POST['name'];
$email = $_POST['email'];
die(update_data($pdo,$sid,$name,$email));
break;
}
// 更新
function update_data($pdo,$sid,$name,$email) {
if ($sid) {
$sql = "UPDATE users SET name=:name, email=:email WHERE sid = :sid;";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':sid',$sid,PDO::PARAM_INT);
$stmt->bindParam(':name',$name,PDO::PARAM_STR);
$stmt->bindParam(':email',$email,PDO::PARAM_STR);
$stmt->execute();
if($stmt->rowCount() > 0) {
return json_encode(['status' => 1,'msg' => '更新成功!']);
}
}
return json_encode(['status' => 0,'msg' => '未知错误!']);
}
// 删除
function del_data($pdo,$sid = 0) {
if ($sid) {
$sql = "DELETE FROM users WHERE sid = :sid;";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':sid',$sid,PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount() > 0) {
return json_encode(['status' => 1,'msg' => '删除成功!']);
}
}
return json_encode(['status' => 0,'msg' => '未知错误!']);
}
// 获取总页数
function get_pages($pdo,$page = 1,$num = 5) {
// 总页数
$num = 5;
$offset = ($page - 1 ) * $num;
$sql = "SELECT CEIL(COUNT(1)/{$num}) total FROM users";
$pages = $pdo->query($sql)->fetch()['total'];
return $pages;
}
function get_datas($pdo,$page = 1, $num = 5) {
// 获取总页数
$pages = get_pages($pdo);
// 每页显示数据
$offset = ($page - 1) * $num;
$sql = "SELECT * FROM `users` LIMIT {$offset},{$num}";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$users = $stmt->fetchAll();
$users = $pdo->query($sql)->fetchall();
return json_encode(['pages' => $pages, 'users' => $users]);
}
7.登录验证:login.php
// 开启session会话
session_start();
// 白名单
$allurls = [
'index.php',
'login.php',
'register.php',
'api.php'
];
$requrl = basename($_SERVER['HTTP_REFERER']);
if(!isset($_SERVER['HTTP_REFERER']) || !in_array($requrl,$allurls)) {
die('<script>alert("非法访问");location.href="index.php";</script>');
}
// 连接数据库
$pdo = new PDO('mysql:dbname=phpedu','root','123456');
$action = strtolower($_GET['action']);
switch ($action) {
// 登录
case 'login':
$sql = 'SELECT * FROM user WHERE email=:email AND password=md5(:password)';
$stmt = $pdo->prepare($sql);
if ($stmt->execute($_POST)) {
if ($stmt->fetch()) {
// 登录成功就将用户信息写入session
$_SESSION['email'] = $_POST['email'];
echo json_encode(['status' => 1, 'msg' => '登录成功,3秒后跳转...']);
} else {
echo json_encode(['status' => 0, 'msg' => '账号或密码错误!']);
}
} else {
print_r($stmt->errorInfo());
}
break;
// 注册
case 'register':
// 确保邮箱的唯一性,在后端做判断,不依赖数据库索引
// 获取标中所有邮箱返回一个数组
$stmt = $pdo->prepare('SELECT email FROM user');
$stmt->bindColumn('email',$email);
$stmt->execute();
$emails = [];
while ($stmt->fetch(PDO::FETCH_BOUND)) {
$emails[] = $email;
}
// echo json_encode($emails);
if (in_array($_POST['email'], $emails)) {
echo json_encode(['status' => -1, 'msg' => '邮箱名已被占用请更换!']);
} else {
// 邮箱可用,执行插入操作
$sql = 'INSERT user SET name=:name,email=:email,password=md5(:password1)';
$stmt = $pdo->prepare($sql);
if ($stmt->execute($_POST)) {
if ($stmt->rowCount()==1) {
// 实现注册后自动登录
$_SESSION['email'] = $_POST['email'];
echo json_encode(['status' => 1, 'msg' => '注册成功,自动登录中...']);
} else {
echo json_encode(['status' => 1, 'msg' => '注册异常,请联系管理员!']);
}
} else {
print_r($stmt->errorInfo());
}
}
break;
// 退出登录
case 'logout':
// 1.清空session变量
session_unset();
// 2.删除session文件
session_destroy();
echo '<script>alert("退出成功");location.href="index.php";</script>';
break;
default:
exit('非法操作');
}