nodejs结合expres

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位数字

效果图如下

img

img

img

img

我这有一个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整理完成,希望您能采纳:
好的,这是一个关于使用Node.js和Express框架搭建本地服务器的需求,并通过一个叫做data.json的文件实现基本的增删改查功能。同时,还需要实现登录功能并进行正则校验,新增和修改功能需要弹出层实现,且需要自己封装一个询问框用于删除操作。以下为代码示例:

1. 服务端代码(app.js)

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');
});


2. 客户端代码(login.html)

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>


3. 客户端代码(index.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>