Node — 第八天 (大事件项目接口实现二)

如何处理MySQL的错误

MySQL的错误信息,可以通过err来获取。这是没有问题的。

但是,我们加入了Promise,Promise中的错误,在外部是获取不到的,只能使用Promise相关方法来获取错误信息。

解决方法一

使用 JS原生的 try … catch …

try {
    let r = await db('insert into user set ?', req.body);
    res.json({
        status: 0,
        message: '注册成功'
    });
} catch (err) {
    console.log(err.message); // 输出这个信息,是为了程序员排错
    res.json({
        status: 1,
        message: '注册失败'
    });
}

解决方法二

使用Promise的catch方法

let r = await db('inssert into user set ?', req.body).catch(err => {
    console.log(err.message);
});
console.log(r); // 如果有错误,r===undefined。否则r是一个数组或对象
if (r) {
    res.json({
        status: 0,
        message: '注册成功'
    });
} else {
    res.json({
        status: 1,
        message: '注册失败'
    });
}

解决方法三

在封装的db中,使用catch方法

/***               db.js  */
....
....
....
// 下面是修改的部分
return new Promise((resolve, reject) => {
        conn.connect();
        conn.query(sql, params, (err, result) => {
            err ? reject(err) : resolve(result);
        });
        conn.end();
    }).catch(err => {
        console.log(err.message);
    });

上述做法的可行性分析:

在这里插入图片描述

后续还是直接使用db方法即可。比如注册:

let r = await db('insert into user set ?', req.body);
    // console.log(r); // 如果有错误,r===undefined。否则r是一个数组或对象
if (r) {
    res.json({
        status: 0,
        message: '注册成功'
    });
} else {
    res.json({
        status: 1,
        message: '注册失败'
    });
}

解决登陆账号不能重复的问题

  • 首先,需要把重复的账号删除掉

  • 第二,添加唯一索引
    在这里插入图片描述

添加唯一索引之后,username字段的值不允许重复了。

如果再次添加重复的账号,则会报 Duplicate entry 'admin' for key 'username'

完成登录接口

思路:

执行查询SQL语句,使用账号密码当做条件。如果能够查询到结果,表示账号密码正确。

// 登录的接口
router.post('/login', async (req, res) => {
    // 假设账号是 admin,密码是 111111
    // 判断账号密码是否正确。
    // if (req.body.username === 'admin' && req.body.password === '111111') {
    let r = await db('select * from user where username=? and password=?', [req.body.username, req.body.password]);
    // 如果账号密码正确,r是一个非空数组;如果错误,是一个空数组
    // console.log(r);
    if (r && r.length > 0) {
        // 登录成功
        res.json({
            status: 0,
            message: '登录成功',
            // token: 'Bearer ' + jwt.sign(要保存的信息, 秘钥, 配置项)
            // 生成的token前面必须有Bearer,还有一个空格。否则一会token不能正常的解密
            token: 'Bearer ' + jwt.sign({ username: 'hahaha', age: 21 }, 'bigevent-9760', { expiresIn: '1h' })
        });
    } else {
        res.json({
            status: 1,
            message: '登录失败'
        });
    }
        
    // }
});

密码使用md5加密

修改user表

  • 我们一会使用md5加密
  • md5加密后的字符串长度始终是 32位
  • 所以修改user表中的 password字段为char类型,长度为32

在这里插入图片描述

图片的大小类型可以设置为 : longtext
//----------------------------------------------------------------------------------------
更改头像的时候,如果提示 ”Data too long for column ‘user_pic’ at row 1“,说明你的base64太大了,而text类型只能存 65535个字符。
解决办法一:使用一个小图片,从新生成base64格式
解决办法二:把数据表中的 user_pic 设置为 longtext 类型(可存42亿个字符)或 mediumtext (可存 1600万个字符)

使用 utility 第三方模块对密码进行加密

  • 下载安装 utility
  • login.js 中加载模块
  • 注册的时候,使用 utility.md5(req.body.password) 对密码进行加密

获取用户信息

登录成功,在token中存放正确的username或者id

/**         login.js  */
// 登录成功之后,token中要保存 username 或者 id
res.json({
    status: 0,
    message: '登录成功',
    // token: 'Bearer ' + jwt.sign(要保存的信息, 秘钥, 配置项)
    // 生成的token前面必须有Bearer,还有一个空格。否则一会token不能正常的解密
    token: 'Bearer ' + jwt.sign({ username: req.body.username, id: r[0].id }, 'bigevent-9760', { expiresIn: '1h' })
});

获取用户信息接口

/*****     user.js    */
// 获取用户信息
router.get('/userinfo', async (req, res) => {
    // 查询条件,可以使用username,也可以使用id
    let r = await db('select * from user where username=?', req.user.username);
    // console.log(r);
    if (r && r.length > 0) {
        res.json({
            status: 0,
            message: '获取用户基本信息成功',
            data: r[0]
        });
    } else {
        res.json({
            status: 1,
            message: '获取用户信息失败'
        });
    }
});

回顾:如何获取客户端携带的请求参数

请求方式 参数类型 服务端如何获取 谁控制的
POST 查询字符串 req.body app.use(express.urlencoded({extended: false}))
POST FormData req.body/req.file multer中间件(目前没学呢)
GET 查询字符串 req.query express 封装的属性
GET 动态参数 req.params express 封装的属性
GET/POST token req.user express-jwt 中间件控制的

服务端获取到的数据都是对象类型

更新密码接口

  • 判断原密码和新密码是否相同
  • 查询一下,原密码是否正确
  • 更新密码
/*****          user.js   */
// 重置密码
router.post('/updatepwd', async (req, res) => {
    // 判断两次密码是否一致
    if (req.body.oldPwd === req.body.newPwd) {
        return res.json({
            status: 1,
            message: '新密码不能和原密码相同'
        });
    }
    // 先根据用户名和原来的密码查询。如果查询到信息,说明原密码正确,是本人操作
    let a = await db('select * from user where username=? and password=?', [req.user.username, utility.md5(req.body.oldPwd)]);
    if (a === undefined || a.length === 0) {
        // 说明没有查到信息,说明原密码不对,不是本人操作
        return res.json({
            status: 1,
            message: '原密码不对'
        });
    }
    // 原密码正确,而且新密码和原密码也不一样,下面进行更新操作
    let arr = [
        utility.md5(req.body.newPwd), 
        req.user.username
    ];
    let r = await db('update user set password=? where username=?', arr);
    if (r && r.affectedRows > 0) {
        res.json({
            status: 0,
            message: '更新密码成功'
        });
    } else {
        res.json({
            status: 1,
            message: '更新密码失败'
        });
    }
});

更换头像接口

  • 需要自己生成一个base64格式的字符串,用于测试
    • https://www.css-js.com/tools/base64.html
// 更换头像
router.post('/update/avatar', async (req, res) => {
    let arr = [
        req.body.avatar,
        req.user.username
    ];
    let r = await db('update user set user_pic=? where username=?', arr);
    if (r && r.affectedRows > 0) {
        res.json({
            status: 0,
            message: '更新头像成功'
        });
    } else {
        res.json({
            status: 1,
            message: '更新头像失败'
        });
    }
});

文章类别

设置文章分类表

在这里插入图片描述

获取文章分类列表

// ### 获取文章分类列表
router.get('/cates', async (req, res) => {
    let r = await db('select * from category');
    // 只要查询到了,哪怕是空数组,也做出响应
    if (r) {
        res.json({
            status: 0, 
            message: '获取分类成功',
            data: r
        });
    } else {
        res.json({
            status: 1,
            message: '获取分类失败'
        });
    }
});

新增文章分类

// ### 新增文章分类
router.post('/addcates', async (req, res) => {
    let r = await db('insert into category set ?', req.body);
    if (r && r.affectedRows > 0) {
        res.json({
            status: 0,
            message: '添加分类成功'
        })
    } else {
        res.json({
            status: 1,
            message: '添加分类失败'
        })
    }
});

根据Id删除文章分类

  • 前端渲染 category.html 的时候,使用的是 {{val.Id}}
    • 修改办法1:打开前端的 /article/category.html ,把模板中的id修改成 {{val.id}}
    • 修改办法2:修改数据库的字段(老师用的这个办法)
// ### 根据Id删除文章分类
router.get('/deletecate/:id', async (req, res) => {
    // 获取id
    let id = req.params.id; // 获取动态参数id
    let r = await db('delete from category where id=?', id);
    if (r && r.affectedRows > 0) {
        res.json({
            status: 0,
            message: '删除分类成功'
        })
    } else {
        res.json({
            status: 1,
            message: '删除分类失败'
        })
    }
});

根据Id获取文章分类数据

这个接口没有用到,所以不写了

根据Id更新文章分类数据

  • SQL语句中有两个 ? ,所以需要传递一个数组
  • SQL中第一个 ?表示 “字段=值,…”,所以需要为其传递一个对象
  • SQL中第二个 ?表示 Id,需要使用 req.body.Id 来获取Id,因为客户端使用的就是大写的 Id
// ### 根据Id更新文章分类数据
router.post('/updatecate', async (req, res) => {
    console.log(req.body);
    let params = [
        {
            name: req.body.name,
            alias: req.body.alias
        },
        req.body.Id // 这里必须是大写的Id,否则不能接受到客户端提交的Id
    ];
    let r = await db('update category set ? where Id=?', params);
    if (r && r.affectedRows > 0) {
        res.json({
            status: 0,
            message: '修改分类成功'
        })
    } else {
        res.json({
            status: 1,
            message: '修改分类失败'
        })
    }
});

猜你喜欢

转载自blog.csdn.net/weixin_44694682/article/details/106000898