(五)项目功能的实现之用户信息修改
用户修改和添加用户类似,区别在于会把id传回编辑页面并显示用户的Id
BLOG -- 源码目录
└── model -- 数据库操作
├── public -- 静态资源
└── route -- 路由
└── admin --博客管理
├── user-modify.js --用户修改功能路由
└── user-edit.js --用户编辑功能路由
└── admin.js --博客管理页面路由
└── views -- 模板
└── admin --博客管理页面art模板
├── user-edit.art --用户编辑页面
└── user.art --用户列表页
└── app.js -- 创建网站服务
user.art
- 赋值id参数在地址栏来区分添加和修改/admin/user-edit?id={{@$value._id}}
···
<tbody>
{{each users}}
<tr>
<td>{{@$value._id}}</td>
<td>{{$value.username}}</td>
<td>{{$value.email}}</td>
<td>{{$value.role == 'admin' ? '超级管理员': '普通用户'}}</td>
<td>{{$value.state == 0 ? '启用': '禁用'}}</td>
<td>
<a href="/admin/user-edit?id={{@$value._id}}" class="glyphicon glyphicon-edit"></a>
<i class="glyphicon glyphicon-remove delete" data-toggle="modal" data-target=".confirm-modal" data-id="{{@$value._id}}"></i>
</td>
</tr>
{{/each}}
</tbody>
···
user-edit.js
- 获取地址栏中的id参数,如果存在则是修改操作
- 引入用户的集合构造函数,根据findOne来查找到这个用户,并将用户的信息渲染到用户的编辑页面
- 区分表单的提交地址,添加和修改不同的Link,按钮也是
const { User } = require('../../model/user');
module.exports = async (req, res) => {
// 获取到地址栏中的id参数
const { message, id } = req.query;
// 如果当前传递了id参数
if (id) {
// 修改操作
let user = await User.findOne({_id: id});
// 渲染用户编辑页面(修改)
res.render('admin/user-edit', {
message: message,
user: user,
link: '/admin/user-modify?id=' + id,
button: '修改'
});
}else {
// 添加操作
res.render('admin/user-edit', {
message: message,
link: '/admin/user-edit',
button: '添加'
});
}
}
user-edit.art
- 对于用户名添加value值为user.username
- 如果是添加操作的话因为没有渲染user会报错,所以user&&user.username的短路特性来避免出错
- 对于邮箱、角色,状态,进行类似的操作添加value值
- 区分表单的提交地址,添加和修改不同的Link,按钮也是
- 对于分类标题的Id也根据Button来区分是否显示用户id
{{extend './common/layout.art'}}
{{block 'main'}}
{{include './common/header.art'}}
<!-- /头部 -->
<!-- 主体内容 -->
<div class="content">
{{include './common/aside.art'}}
<div class="main">
<!-- 分类标题 -->
<div class="title">
<h4 style="display: {{button == '修改' ? 'block' : 'none'}}">{{@user && user._id}}</h4>
<p class="tips">{{message}}</p>
</div>
<!-- /分类标题 -->
<form class="form-container" action="{{link}}" method="post">
<div class="form-group">
<label>用户名</label>
<input name="username" type="text" class="form-control" placeholder="请输入用户名" value="{{user && user.username}}">
</div>
<div class="form-group">
<label>邮箱</label>
<input type="email" class="form-control" placeholder="请输入邮箱地址" name="email" value="{{user && user.email}}">
</div>
<div class="form-group">
<label>密码</label>
<input type="password" class="form-control" placeholder="请输入密码" name="password">
</div>
<div class="form-group">
<label>角色</label>
<select class="form-control" name="role">
<option value="normal" {{user && user.role == 'normal' ? 'selected' : ''}}>普通用户</option>
<option value="admin" {{user && user.role == 'admin' ? 'selected' : ''}}>超级管理员</option>
</select>
</div>
<div class="form-group">
<label>状态</label>
<select class="form-control" name="state">
<option value="0" {{user && user.state == '0' ? 'selected' : ''}}>启用</option>
<option value="1" {{user && user.state == '1' ? 'selected' : ''}}>禁用</option>
</select>
</div>
<div class="buttons">
<input type="submit" class="btn btn-primary" value="{{button}}">
</div>
</form>
</div>
</div>
{{/block}}
admin.js
- 添加用户修改路由
// 引用expess框架
const express = require('express');
// 创建博客展示页面路由
const admin = express.Router();
// 渲染登录页面
admin.get('/login', require('./admin/loginPage'));
// 实现登录功能
admin.post('/login', require('./admin/login'));
// 创建用户列表路由
admin.get('/user', require('./admin/userPage'));
// 实现退出功能
admin.get('/logout', require('./admin/logout'));
// 创建用户编辑页面路由
admin.get('/user-edit', require('./admin/user-edit'));
// 创建实现用户添加功能路由
admin.post('/user-edit', require('./admin/user-edit-fn'));
// 用户修改功能路由
admin.post('/user-modify', require('./admin/user-modify'));
// 将路由对象做为模块成员进行导出
module.exports = admin;
user-modify.js
- 接受客户端传过来的请求参数(post)和要修改的用户的id(get)
- 导入用户集合构造函数,通过findOne来根据id查询变量的密码
- 密码加密过了所以要导入bcrypt模块,同时通过bcrypt.compare进行明文密码和数据库密码进行比对,返回一个布尔值
- 如果密码比对失败则触发中间件,将页面跳转到user-edit,并出现提示的错误信息
- next接受字符串
- 如果比对成功,则通过UpdateOne来更新修改之后的用户信息,密码是不能修改的所以不能写密码。通过一个const结构然后就不用了重复书写req.body
- 将页面重定向到用户列表页面
const { User } = require('../../model/user');
const bcrypt = require('bcrypt');
module.exports = async (req, res, next) => {
// 接收客户端传递过来的请求参数
const { username, email, role, state, password } = req.body;
// 即将要修改的用户id
const id = req.query.id;
// 根据id查询用户信息
let user = await User.findOne({_id: id});
// 密码比对
const isValid = await bcrypt.compare(password, user.password);
// 密码比对成功
if (isValid) {
// res.send('密码比对成功');
// 将用户信息更新到数据库中
await User.updateOne({_id: id}, {
username: username,
email: email,
role: role,
state: state
});
// 将页面重定向到用户列表页面
res.redirect('/admin/user');
}else {
// 密码比对失败
let obj = {path: '/admin/user-edit', message: '密码比对失败,不能进行用户信息的修改', id: id}
next(JSON.stringify(obj));
}
// 密码比对
// res.send(user);
}
app.js
- 对于错误处理的中间件,如果密码比对不成功,我们希望是跳转地址带有?message&和id,这种情况下我们可以通过遍历和字符串拼接的方式来实现,例如params.push params.join方法
// 引用expess框架
const express = require('express');
// 处理路径
const path = require('path');
// 引入body-parser模块 用来处理post请求参数
const bodyPaser = require('body-parser');
// 导入express-session模块
const session = require('express-session');
// 导入art-tempate模板引擎
const template = require('art-template');
// 创建网站服务器
const app = express();
// 数据库连接
require('./model/connect');
// 处理post请求参数
app.use(bodyPaser.urlencoded({extended: false}));
// 配置session
app.use(session({
secret: 'secret key',
saveUninitialized: false,
cookie: {
maxAge: 24 * 60 * 60 * 1000
}
}));
// 告诉express框架模板所在的位置
app.set('views', path.join(__dirname, 'views'));
// 告诉express框架模板的默认后缀是什么
app.set('view engine', 'art');
// 当渲染后缀为art的模板时 所使用的模板引擎是什么
app.engine('art', require('express-art-template'));
// 开放静态资源文件
app.use(express.static(path.join(__dirname, 'public')));
// 引入路由模块
const home = require('./route/home');
const admin = require('./route/admin');
// 拦截请求 判断用户登录状态
app.use('/admin', require('./middleware/loginGuard'));
// 为路由匹配请求路径
app.use('/home', home);
app.use('/admin', admin);
app.use((err, req, res, next) => {
// 将字符串对象转换为对象类型
// JSON.parse()
const result = JSON.parse(err);
// {path: '/admin/user-edit', message: '密码比对失败,不能进行用户信息的修改', id: id}
let params = [];
for (let attr in result) {
if (attr != 'path') {
params.push(attr + '=' + result[attr]);
}
}
res.redirect(`${result.path}?${params.join('&')}`);
})
// 监听端口
app.listen(80);
console.log('网站服务器启动成功, 请访问localhost')
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。