如何正确实现用户最后登录时间的前后端处理?含React展示需求
登录后更新并展示用户最后登录时间的前后端实现方案
后端(Node.js + Mongoose)修正方案
1. 用户Schema修正
你的Schema中lastLogin的默认值写法有问题:Date.now()会在Schema定义时就执行一次,新创建用户时不会自动生成当前时间。需要改为不带括号的Date.now,让Mongoose在创建文档时动态生成时间:
const userSchema = new Schema( { name: { type: String }, email: { type: String, unique: true}, password: { type: String }, status: {type: String, enum:["Active", "Blocked"], default:"Active"}, token: { type: String }, // 修正:去掉括号,实现动态生成当前时间 lastLogin: { type: Date, default: Date.now }, }, { timestamps: true } );
2. 登录路由逻辑修正
原登录代码存在3个核心问题:更新lastLogin的条件错误、未将修改持久化到数据库、HTTP状态码不规范。以下是修正后的代码:
userRouter.post("/login", async (req, res, next) => { try { const { email, password } = req.body; // 参数不全返回400(客户端错误),而非204 if (!(email && password)) { return res.status(400).send({ msg: "所有字段均为必填项!" }); } const user = await UsersModel.findOne({ email }); // 用户不存在返回404 if (!user) { return res.status(404).send({ msg: "该邮箱对应的用户不存在!" }); } // 密码验证失败返回401(未授权) const isPasswordValid = await bcrypt.compare(password, user.password); if (!isPasswordValid) { return res.status(401).send({ msg: "密码错误!" }); } // 生成JWT token const accessToken = await JWTAuthenticate(user); // 精准更新当前登录用户的token和lastLogin const updatedUser = await UsersModel.findByIdAndUpdate( user._id, { token: accessToken, lastLogin: new Date() }, { new: true } // 返回更新后的完整用户数据 ); // 移除敏感字段后返回前端 const safeUser = { ...updatedUser.toObject() }; delete safeUser.password; res.status(200).send(safeUser); } catch (error) { next(error); } });
关键改进点:
- 用
findByIdAndUpdate精准定位当前用户,确保lastLogin更新到正确的文档 - 移除
password字段后再返回,避免敏感信息泄露 - 规范各场景的HTTP状态码,符合RESTful规范
前端(React)展示方案
1. 登录成功后存储用户信息
登录接口调用成功后,将包含lastLogin的用户信息存储到localStorage或状态管理工具:
const handleLogin = async (email, password) => { try { const res = await fetch('/api/users/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); const data = await res.json(); if (res.ok) { localStorage.setItem('currentUser', JSON.stringify(data)); window.location.href = '/user-list'; } else { alert(data.msg); } } catch (err) { console.error('登录失败:', err); } };
2. 获取用户列表并渲染表格
在用户列表页面,调用后端接口获取所有用户数据,格式化lastLogin后渲染到表格:
import { useEffect, useState } from 'react'; const UserTable = () => { const [users, setUsers] = useState([]); useEffect(() => { const fetchUsers = async () => { try { const res = await fetch('/api/users'); const data = await res.json(); setUsers(data); } catch (err) { console.error('获取用户列表失败:', err); } }; fetchUsers(); }, []); // 格式化日期为中文可读格式 const formatLastLogin = (dateString) => { if (!dateString) return '无登录记录'; const date = new Date(dateString); return date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); }; return ( <table border="1" cellpadding="8" cellspacing="0"> <thead> <tr> <th>用户名</th> <th>邮箱</th> <th>状态</th> <th>最后登录时间</th> </tr> </thead> <tbody> {users.map(user => ( <tr key={user._id}> <td>{user.name}</td> <td>{user.email}</td> <td>{user.status}</td> <td>{formatLastLogin(user.lastLogin)}</td> </tr> ))} </tbody> </table> ); }; export default UserTable;
3. 额外注意事项
- 后端用户列表接口需确保返回
lastLogin字段,可通过UsersModel.find({}, '-password')过滤敏感字段 - 若需要更复杂的日期格式化,可使用
dayjs等第三方库简化操作 - 若使用状态管理工具(如Redux、Zustand),需同步更新用户信息,保证表格数据实时性
内容的提问来源于stack exchange,提问作者user18986944
相关产品推荐
相关产品推荐

