一、准备
docker desktop
wamp(数据库)
二、docker拉取nignx
两条命令
docker pull nginx
docker run --name my-nginx -v /path/to/your/student_management_system:/usr/share/nginx/html:ro -p 8080:80 -d nginx
注意把/path/to/your/student_management_system换成自己的路径
路径是.html文件所在路径
三、数据库
打开wamp
打开phpMyAdmin网页,输入用户名root 初始登陆没有密码 回车确认
·点击“新建” → 输入数据库名:student_db
→ 创建
·选择刚创建的数据库 → 点击“SQL”标签 → 执行以下 SQL:
CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
student_id VARCHAR(50) NOT NULL UNIQUE
);
这样就创建好一个数据表
四、后端API连接(php)
文件路径:wamp64/www/student_backend/api/student.php
<?php
header("Content-Type: application/json");
$conn = new mysqli("localhost", "root", "", "student_db");
if ($conn->connect_error) {
die(json_encode(["status" => "error", "message" => "连接失败: " . $conn->connect_error]));
}
$method = $_SERVER['REQUEST_METHOD'];
switch ($method) {
case 'GET':
$result = $conn->query("SELECT * FROM students");
if (!$result) {
echo json_encode(["status" => "error", "message" => "查询失败"]);
exit;
}
$students = [];
while ($row = $result->fetch_assoc()) {
$students[] = $row;
}
echo json_encode($students);
break;
case 'POST':
$data = json_decode(file_get_contents('php://input'), true);
$name = $conn->real_escape_string($data['name']);
$student_id = $conn->real_escape_string($data['student_id']);
// 检查学号是否已存在
$check = $conn->query("SELECT * FROM students WHERE student_id = '$student_id'");
if ($check->num_rows > 0) {
echo json_encode(["status" => "error", "message" => "学号已存在"]);
exit;
}
$stmt = $conn->prepare("INSERT INTO students (name, student_id) VALUES (?, ?)");
$stmt->bind_param("ss", $name, $student_id);
if ($stmt->execute()) {
echo json_encode(["status" => "success"]);
} else {
echo json_encode(["status" => "error", "message" => "添加失败"]);
}
break;
case 'DELETE':
$data = json_decode(file_get_contents('php://input'), true);
$id = $conn->real_escape_string($data['id']);
$stmt = $conn->prepare("DELETE FROM students WHERE id = ?");
$stmt->bind_param("i", $id);
if ($stmt->execute()) {
echo json_encode(["status" => "success"]);
} else {
echo json_encode(["status" => "error", "message" => "删除失败"]);
}
break;
case 'PUT':
$data = json_decode(file_get_contents('php://input'), true);
$id = $conn->real_escape_string($data['id']);
$name = $conn->real_escape_string($data['name']);
$student_id = $conn->real_escape_string($data['student_id']);
// 检查学号是否已被占用(排除自己)
$check = $conn->query("SELECT * FROM students WHERE student_id = '$student_id' AND id != $id");
if ($check->num_rows > 0) {
echo json_encode(["status" => "error", "message" => "学号已被使用"]);
exit;
}
$stmt = $conn->prepare("UPDATE students SET name = ?, student_id = ? WHERE id = ?");
$stmt->bind_param("ssi", $name, $student_id, $id);
if ($stmt->execute()) {
echo json_encode(["status" => "success"]);
} else {
echo json_encode(["status" => "error", "message" => "更新失败"]);
}
break;
default:
echo json_encode(["status" => "error", "message" => "无效请求方法"]);
}
?>
五、html页面(html+css+js)
文件路径:student_management_system/index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>学生管理系统</title>
<style>
body {
font-family: 'Segoe UI', system-ui;
margin: 2rem auto;
max-width: 1200px;
padding: 0 20px;
background: linear-gradient(150deg, #e6f0ff 0%, #f0f7ff 100%);
}
#studentForm {
background: rgba(255,255,255,0.95);
padding: 2rem;
border-radius: 12px;
box-shadow: 0 2px 15px rgba(59,130,246,0.05);
display: flex;
gap: 1rem;
flex-wrap: wrap;
margin-bottom: 2rem;
}
label {
flex: 1;
min-width: 200px;
display: flex;
gap: 0.5rem;
align-items: center;
}
input {
padding: 0.8rem;
border: 2px solid #e2e8f0;
border-radius: 8px;
flex: 1;
transition: border-color 0.3s ease;
}
input:focus {
outline: none;
border-color: #3b82f6;
}
table {
width: 100%;
border-collapse: collapse;
background: rgba(255,255,255,0.98);
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 15px rgba(59,130,246,0.05);
}
th {
background: #1e3a8a;
color: white;
padding: 1rem;
font-weight: 600;
text-align: center;
}
td {
padding: 1rem;
border-bottom: 1px solid #e2e8f0;
transition: transform 0.2s ease;
text-align: center;
}
td:nth-child(4) {
display: flex;
gap: 0.5rem;
justify-content: center;
}
tr:nth-child(even) {
background: #f8fafc;
}
tr:hover td {
background: #eff6ff;
transform: scale(1.02);
}
button {
padding: 0.6rem 1.2rem;
border: none;
border-radius: 8px;
background: #3b82f6;
color: white;
font-weight: 500;
transition: all 0.3s ease;
display: inline-flex;
gap: 0.5rem;
align-items: center;
}
button:hover {
background: #2563eb;
box-shadow: 0 4px 6px rgba(59,130,246,0.2);
transform: translateY(-1px);
}
h1 {
text-align: center;
margin: 1rem 0 2rem;
}
/* 在body样式中添加主容器包裹 */
/* 统一注释语法 */
.main-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
/* 合并后的媒体查询 */
@media (max-width: 768px) {
.main-container {
padding: 0 10px;
}
body {
margin: 1rem;
}
#studentForm {
flex-direction: column;
padding: 1rem;
gap: 0.8rem;
}
th:nth-child(1),
td:nth-child(1) {
display: none;
}
}
</style>
</head>
<body>
<h1>学生管理系统</h1>
<form id="studentForm">
<label>姓名:<input type="text" id="name" name="name" autocomplete="name" required></label>
<label>学号:<input type="text" id="studentId" name="studentId" autocomplete="off" required></label>
<button type="submit">添加学生</button>
</form>
<table id="studentTable">
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>学号</th>
<th>操作</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script>
document.addEventListener("DOMContentLoaded", () => {
const form = document.getElementById("studentForm");
const tableBody = document.querySelector("#studentTable tbody");
function loadStudents() {
fetch("http://localhost/student_backend/api/student.php")
.then(res => res.json())
.then(students => {
tableBody.innerHTML = "";
students.forEach(student => {
const row = document.createElement("tr");
row.innerHTML = `
<td>${student.id}</td>
<td>${student.name}</td>
<td>${student.student_id}</td>
<td>
<button onclick="editStudent(${student.id}, '${student.name}', '${student.student_id}')">编辑</button>
<button onclick="deleteStudent(${student.id})">删除</button>
</td>
`;
tableBody.appendChild(row);
});
})
.catch(err => console.error("加载失败:", err));
}
form.addEventListener("submit", e => {
e.preventDefault();
const name = document.getElementById("name").value.trim();
const studentId = document.getElementById("studentId").value.trim();
if (!name || !studentId) {
alert("请输入完整信息!");
return;
}
fetch("http://localhost/student_backend/api/student.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, student_id: studentId })
})
.then(res => res.json())
.then(data => {
if (data.status === "success") {
form.reset();
loadStudents();
} else {
alert(data.message || "添加失败");
}
})
.catch(err => console.error("请求错误:", err));
});
window.deleteStudent = id => {
if (!confirm("确认删除?")) return;
fetch("http://localhost/student_backend/api/student.php", {
method: "DELETE",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ id })
})
.then(() => loadStudents());
};
window.editStudent = (id, name, studentId) => {
const newName = prompt("请输入新名字", name);
const newId = prompt("请输入新学号", studentId);
if (newName && newId) {
fetch("http://localhost/student_backend/api/student.php", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ id, name: newName, student_id: newId })
})
.then(() => loadStudents());
}
};
loadStudents();
});
</script>
</body>
</html>
六、访问地址:http://localhost:8080
实现页面:
七、问题
本文重在提供docker拉取nignx连接前后端思路,没有解决bug,即id自增的问题,如果删除对应的表中一列数据,新增一列数据只会继续叠加,不会补齐所缺id。