01: 使用 nodejs +(express或 koa 框架) 搭建一个本地的服务器, 定义接口
实现登录/增/删/改/查 功能(不需要连数据库, 数据存放在一个json 文件中)
数据文件 - data.json(2分)
express搭建服务器,静态资源托管文件夹为public - index.html和login.html
不需要注册 - 默认创建用户数据 - admin 123456
新增和修改为弹出层,不需要单独的文件
实现用户添加功能
实现用户修改功能
实现用户删除功能
默认首页不登录不允许显示index.html
前后端放在同一个服务器中,使用promise封装ajax发送请求
请求成功和失败使用封装好的弹出层提示
删除前询问用户是否要删除 - 使用自己封装好的弹出层询问
02: 前端使用promise 封装ajax 进行数据的请求(考虑get和post方式)用于请求后端数据
03:登录正则校验, 正则表达式 用户名(数字/字母/下划线4-10位), 密码6位数字
效果图如下
我这有一个vue+express的完整项目,可以不
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const fs = require('fs');
// 使用 body-parser 中间件解析 HTTP 请求体
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// 定义数据文件路径
const dataFilePath = './data.json';
// 默认创建用户数据 - admin 123456
let users = [
{
username: 'admin',
password: '123456'
}
]
// 登录接口
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 正则表达式 用户名(数字/字母/下划线4-10位), 密码6位数字
const usernameRegex = /^[a-zA-Z0-9_]{4,10}$/;
const passwordRegex = /^\d{6}$/;
if (!usernameRegex.test(username)) {
return res.status(400).send('用户名格式不正确');
}
if (!passwordRegex.test(password)) {
return res.status(400).send('密码格式不正确');
}
// 判断用户名和密码是否匹配
const user = users.find(item => item.username === username);
if (!user || user.password !== password) {
return res.status(401).send('用户名或密码错误');
}
res.send('登录成功');
});
// 获取所有用户信息接口
app.get('/users', (req, res) => {
res.send(users);
});
// 添加用户接口
app.post('/users', (req, res) => {
const newUser = req.body;
const index = users.findIndex(user => user.username === newUser.username);
if (index > -1) {
return res.status(400).send('用户名已存在');
}
users.push(newUser);
saveDataToFile(users);
res.send('添加成功');
});
// 修改用户信息接口
app.put('/users', (req, res) => {
const updatedUser = req.body;
const index = users.findIndex(user => user.username === updatedUser.username);
if (index === -1) {
return res.status(404).send('用户不存在');
}
users.splice(index, 1, updatedUser);
saveDataToFile(users);
res.send('修改成功');
});
// 删除用户接口
app.delete('/users/:username', (req, res) => {
const username = req.params.username;
const index = users.findIndex(user => user.username === username);
if (index === -1) {
return res.status(404).send('用户不存在');
}
// 弹出层询问是否确认删除
// ...
users.splice(index, 1);
saveDataToFile(users);
res.send('删除成功');
});
// 保存数据到文件中
function saveDataToFile(data) {
fs.writeFile(dataFilePath, JSON.stringify(data), err => {
if (err) {
console.error(err);
}
});
}
// 启动服务器
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
在前端部分,可以使用 fetch API 或者 axios 库等工具来封装 AJAX 请求,然后通过 Promise 来处理请求成功和失败的情况。例如:
javascript
// 封装 GET 请求
function get(url) {
return fetch(url)
.then(res => {
if (!res.ok) {
throw new Error(res.statusText);
}
return res.json();
})
.catch(err => {
console.error(err);
// 封装弹出层提示
alert('请求失败');
});
}
// 封装 POST 请求
function post(url, data) {
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(res => {
if (!res.ok) {
throw new Error(res.statusText);
}
return res.json();
})
.catch(err => {
console.error(err);
// 封装弹出层提示
alert('请求失败');
});
}
// 登录接口调用示例
const loginBtn = document.querySelector('#loginBtn');
loginBtn.addEventListener('click', () => {
const username = document.querySelector('#username').value;
const password = document.querySelector('#password').value;
const data = { username, password };
post('/login', data
以下回答参考GPT,并由JoseKe整理完成,希望您能采纳:javascript
const express = require('express');
const app = express();
const path = require('path');
const bodyParser = require('body-parser');
const fs = require('fs');
const { resolve } = require('path');
const { rejects } = require('assert');
const { resolve4 } = require('dns');
const dataFile = './data.json';
// 设置静态资源路径
app.use(express.static(path.join(__dirname, 'public')));
// 设置body-parser中间件
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// 登录接口
app.post('/login', (req, res) => {
const {username, password} = req.body;
const regUsername = /^[a-zA-Z0-9_]{4,10}$/;
const regPassword = /^[0-9]{6}$/;
if (!regUsername.test(username) || !regPassword.test(password)) {
res.json({code: 1, msg: '用户名或密码格式不正确'});
return;
}
if (username === 'admin' && password === '123456') {
res.json({code: 0, msg: '登录成功'});
return;
} else {
res.json({code: 1, msg: '用户名或密码错误'});
return;
}
});
// 获取用户列表
app.get('/users', (req, res) => {
fs.readFile(dataFile, 'utf-8', (err, data) => {
if (err) {
console.error(err);
res.json([]);
return;
}
res.json(JSON.parse(data));
});
});
// 添加用户
app.post('/users/add', (req, res) => {
const newUser = req.body;
fs.readFile(dataFile, 'utf-8', (err, data) => {
if (err) {
console.error(err);
res.json({code: 1, msg: '添加用户失败'});
return;
}
const users = JSON.parse(data);
users.push(newUser);
fs.writeFile(dataFile, JSON.stringify(users), err => {
if (err) {
console.error(err);
res.json({code: 1, msg: '添加用户失败'});
return;
}
res.json({code: 0, msg: '添加用户成功'});
});
});
});
// 修改用户
app.post('/users/update', (req, res) => {
const updateUser = req.body;
fs.readFile(dataFile, 'utf-8', (err, data) => {
if (err) {
console.error(err);
res.json({code: 1, msg: '修改用户失败'});
return;
}
const users = JSON.parse(data);
const index = users.findIndex(user => user.id === updateUser.id);
if (index === -1) {
res.json({code: 1, msg: '用户不存在'});
return;
}
users[index] = updateUser;
fs.writeFile(dataFile, JSON.stringify(users), err => {
if (err) {
console.error(err);
res.json({code: 1, msg: '修改用户失败'});
return;
}
res.json({code: 0, msg: '修改用户成功'});
});
});
});
// 删除用户
app.post('/users/delete', (req, res) => {
const id = req.body.id;
const confirmFlag = req.body.confirm;
if (!confirmFlag) {
res.json({code: 1, msg: '未确认删除'});
return;
}
fs.readFile(dataFile, 'utf-8', (err, data) => {
if (err) {
console.error(err);
res.json({code: 1, msg: '删除用户失败'});
return;
}
const users = JSON.parse(data);
const index = users.findIndex(user => user.id === id);
if (index === -1) {
res.json({code: 1, msg: '用户不存在'});
return;
}
users.splice(index, 1);
fs.writeFile(dataFile, JSON.stringify(users), err => {
if (err) {
console.error(err);
res.json({code: 1, msg: '删除用户失败'});
return;
}
res.json({code: 0, msg: '删除用户成功'});
});
});
});
// 启动服务
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<div>
<input type="text" id="username" placeholder="Username">
</div>
<div>
<input type="text" id="password" placeholder="Enter your password">
</div>
<div>
<button id="submitBtn">Login</button>
</div>
<script>
function ajax(options) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(options.method || 'GET', options.url);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.responseText));
} else if (xhr.status === 404) {
reject('Not Found');
} else {
reject('Error');
}
}
};
if (options.method === 'POST') {
xhr.setRequestHeader('Content-Type', 'application/json');
}
xhr.send(options.data ? JSON.stringify(options.data) : null);
});
}
const submitBtn = document.getElementById('submitBtn');
submitBtn.addEventListener('click', () => {
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
ajax({
method: 'POST',
url: '/login',
data: { username, password }
}).then(data => {
if (data.code === 0) {
alert('登录成功');
window.location.href = '/index.html';
} else {
alert(data.msg);
}
}).catch(err => {
alert(err);
});
});
</script>
</body>
</html>
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Index</title>
</head>
<body>
<table id="userTable">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>Gender</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<button id="addBtn">Add User</button>
<script>
// 获取用户列表
function getUsers() {
ajax({
url: '/users'
}).then(data => {
const userList = document.getElementById('userTable').getElementsByTagName('tbody')[0];
let html = '';
data.forEach(user => {
html += `
<tr>
<td>${user.id}</td>
<td>${user.name}</td>
<td>${user.age}</td>
<td>${user.gender}</td>
<td>
<button data-id="${user.id}" class="updateBtn">Update</button>
<button data-id="${user.id}" class="deleteBtn">Delete</button>
</td>
</tr>
`;
});
userList.innerHTML = html;
// 添加用户
const addBtn = document.getElementById('addBtn');
addBtn.addEventListener('click', () => {
showPopup({title: 'Add User', onSubmit: saveUser});
});
// 修改用户
const updateBtns = document.getElementsByClassName('updateBtn');
for (let i = 0; i < updateBtns.length; i++) {
updateBtns[i].addEventListener('click', function() {
const id = this.getAttribute('data-id');
const userToUpdate = data.find(user => user.id === id);
showPopup({title: 'Update User', onSubmit: function(formData) {
saveUser({...userToUpdate, ...formData});
}, data: userToUpdate});
});
}
// 删除用户
const deleteBtns = document.getElementsByClassName('deleteBtn');
for (let i = 0; i < deleteBtns.length; i++) {
deleteBtns[i].addEventListener('click', function() {
const id = this.getAttribute('data-id');
showPopup({title: 'Delete User', content: 'Are you sure?', onSubmit: function() {
ajax({
url: '/users/delete',
method: 'POST',
data: { id, confirm: true }
}).then(data => {
if (data.code === 0) {
alert('删除成功');
getUsers();
} else {
alert(data.msg || '删除失败');
}
}).catch(err => {
alert(err || '删除失败');
});
}});
});
}
}).catch(err => {
alert(err);
});
}
// 保存用户
function saveUser(user) {
const {id, name, age, gender} = user;
if (!name || !age || !gender) {
alert('请填写完整的用户信息');
return;
}
if (id) {
// 修改用户
ajax({
url: '/users/update',
method: 'POST',
data: user
}).then(data => {
if (data.code === 0) {
alert('修改成功');
getUsers();
} else {
alert(data.msg || '修改失败');
}
}).catch(err => {
alert(err || '修改失败');
});
} else {
// 添加用户
ajax({
url: '/users/add',
method: 'POST',
data: user
}).then(data => {
if (data.code === 0) {
alert('添加成功');
getUsers();
} else {
alert(data.msg || '添加失败');
}
}).catch(err => {
alert(err || '添加失败');
});
}
}
// 显示弹出层
function showPopup({title, content, onSubmit, data}) {
const popupDiv = document.createElement('div');
popupDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
popupDiv.style.position = 'fixed';
popupDiv.style.left = 0;
popupDiv.style.top = 0;
popupDiv.style.width = '100%';
popupDiv.style.height = '100%';
popupDiv.style.zIndex = 100;
const form = document.createElement('form');
form.style.position = 'absolute';
form.style.top = '50%';
form.style.left = '50%';
form.style.transform = 'translate(-50%, -50%)';
form.style.backgroundColor = '#fff';
form.style.padding = '20px';
form.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)';
form.style.textAlign = 'center';
form.innerHTML = `
<div style="font-size: 20px">${title}</div>
<hr>
<div>
<label>Name:</label>
<input type="text" name="name" value="${data ? data.name : ''}">
</div>
<div>
<label>Age:</label>
<input type="text" name="age" value="${data ? data.age : ''}">
</div>
<div>
<label>Gender:</label>
<select name="gender">
<option value="">--Please Select--</option>
<option value="male" ${data && data.gender === 'male' ? 'selected' : ''}>Male</option>
<option value="female" ${data && data.gender === 'female' ? 'selected' : ''}>Female</option>
</select>
</div>
<div>
${content ? content : ''}
</div>
<hr>
<div>
<button type="submit">Submit</button>
<button type="button" onclick="closePopup()">Close</button>
</div>
`;
document.body.appendChild(popupDiv);
popupDiv.appendChild(form);
form.addEventListener('submit', event => {
event.preventDefault();
const formData = {
name: form.name.value,
age: form.age.value,
gender: form.gender.value
};
onSubmit(formData);
closePopup();
});
}
// 关闭弹出层
function closePopup() {
const popupDiv = document.querySelector('div[style*="rgba(0, 0, 0, 0.5)"]');
popupDiv.parentNode.removeChild(popupDiv);
}
// 发送AJAX请求
function ajax(options) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(options.method || 'GET', options.url);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(JSON.parse(xhr.responseText));
} else if (xhr.status === 404) {
reject('Not Found');
} else {
reject('Error');
}
}
};
if (options.method === 'POST') {
xhr.setRequestHeader('Content-Type', 'application/json');
}
xhr.send(options.data ? JSON.stringify(options.data) : null);
});
}
// 初始化页面
getUsers();
</script>
</body>
</html>