搜索
创建管理员, 对比这个流程走一遍!
# 一、创建数据库用户留言表 message
用户留言表 message我们在前面讲课的时候已经带领大家设计和创建了
我们一般创建一个新的栏目板块,第一步就是创建数据库表,但在创建之前,先根据业务分析一下表所需字段:
- 根据你的客户、老板勾勒出他的需求,然后根据需求设计,比如:
- 用户留言表 message 最起码需要有: 留言人(留言用户称呼)、留言用户电话(好联系他)、 留言内容、留言时间字段
- 当然还可以增加留言信息是否处理状态字段(已处理,未处理),如果你还想不到这一点,可以先不管这个字段,后期再加上去
- message 表字段设计
字段名 数据类型 描述 空 默认值
字段含义
id int(20) 主键、自增长、UNSIGNED无符号 否 无 username varchar(30) 否 留言用户称呼 tel varchar(64) 否 留言用户电话加密值 telnumber bigint(11) 否 0 留言用户电话 message text 是 NULL 用户留言内容 timestamp datetime 否 CURRENT_TIMESTAMP 用户留言时间戳 create_time datetime 否 CURRENT_TIMESTAMP 数据创建时间 update_time datetime 否 CURRENT_TIMESTAMP 数据更新时间
# 二、创建迁移文件、执行迁移命令创建数据表
在数据库创建数据表的方式很多,在上面定义了表字段之后,可以使用
phpmyAdmin、数据库插件执行sql语句创建等等方式,但是建议大家通过:创建迁移文件、执行迁移命令创建数据表。涉及的知识点:
- 章节2:egg.js基础-五、eggjs项目中sequelize模型创建mysql数据库
创建迁移文件 命令:
npx sequelize migration:generate --name=init-message创建迁移文件:
'use strict'; /** @type {import('sequelize-cli').Migration} */ module.exports = { async up (queryInterface, Sequelize) { const { INTEGER, STRING, DATE, ENUM, TEXT, BIGINT} = Sequelize; // 创建表 --- 类似我们sql语句定义表结构 await queryInterface.createTable('message', { id: { type: INTEGER(20).UNSIGNED, primaryKey: true, autoIncrement: true, comment: '留言板主键id' }, username: { type: STRING(30), allowNull: false, defaultValue: '', comment: '留言板用户称呼' }, tel: { type: STRING(64), allowNull: false, defaultValue: '' , comment: '留言用户的电话号码加密' }, telnumber : { type: BIGINT(11), allowNull: false, defaultValue: 0 , comment: '留言用户的电话号码', unique: true }, message : { type: TEXT, allowNull: true, defaultValue: '', comment: '留言用户的留言信息' }, // sex: { type: ENUM, values: ['男','女','保密'], allowNull: true, defaultValue: '保密', comment: '留言用户性别'}, timestamp : {type: DATE, allowNull: false, defaultValue:Sequelize.fn('NOW')}, create_time: {type: DATE, allowNull: false, defaultValue:Sequelize.fn('NOW')}, update_time: {type: DATE, allowNull: false, defaultValue:Sequelize.fn('NOW')} }); }, async down (queryInterface, Sequelize) { await queryInterface.dropTable('message') } };执行迁移文件命令生成数据库表:
// 升级数据库 npx sequelize db:migrate
# 三、创建留言表 message的模型
模型文件主要是用于处理数据库表的增删改查等操作
'use strict';
module.exports = app =>{
const { INTEGER, STRING, DATE, ENUM, TEXT, BIGINT} = app.Sequelize;
const Message = app.model.define('message',{
id: {
type: INTEGER(20).UNSIGNED,
primaryKey: true,
autoIncrement: true,
comment: '留言板主键id'
},
username: {
type: STRING(30),
allowNull: false,
defaultValue: '',
comment: '留言板用户称呼',
// set(val){
// let data = val + '(先生/女士)';
// this.setDataValue('username', data);
// }
},
tel: {
type: STRING(64),
allowNull: false,
defaultValue: '' ,
comment: '留言用户的电话号码加密'
},
telnumber : {
type: BIGINT(11),
allowNull: false,
defaultValue: 0 ,
comment: '留言用户的电话号码',
unique: true
},
message : {
type: TEXT,
allowNull: true,
defaultValue: '',
comment: '留言用户的留言信息'
},
// sex: { type: ENUM, values: ['男','女','保密'], allowNull: true, defaultValue: '保密', comment: '留言用户性别'},
timestamp : {
type: DATE,
allowNull: false,
defaultValue:app.Sequelize.fn('NOW'),
get(){
let data = this.getDataValue('timestamp') ;
/*
//如果想转换成年月日时分秒,可以使用moment.js库等其他时间库
//我们这里带领大家回忆一下js基础,就手动拼接一下
let year = data.getFullYear();
let month = ("0" + (data.getMonth() + 1)).slice(-2);
let day = ("0" + data.getDate()).slice(-2);
let hours = ("0" + data.getHours()).slice(-2);
let minutes = ("0" + data.getMinutes()).slice(-2);
let seconds = ("0" + data.getSeconds()).slice(-2);
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
*/
//如果想转成时间戳
return (new Date(data)).getTime();
}
},
create_time: {type: DATE, allowNull: false, defaultValue:app.Sequelize.fn('NOW')},
update_time: {type: DATE, allowNull: false, defaultValue:app.Sequelize.fn('NOW')}
// timestamp : DATE,
// create_time: DATE,
// update_time: DATE
},{
// timestamps: true,//是否自动写入时间戳
// tableName: 'message',//自定义数据表名称
});
return Message;
}
# 四、提交留言(示例)
# 创建控制器 app/controller/admin/message.js
'use strict';
let crypto = require('crypto');
//自定义IV(16位)、key(密钥(32位的'aes-256-cbc')(24位的'aes-192-cbc'))
const secret = {
iv: 'IloveYOU@520520!',// 初始化向量(iv)16位
key: 'a123456789@!*&%bcdef@123456789&&', // 32 位秘钥密钥
}
const Controller = require('egg').Controller;
class MessageController extends Controller {
//创建留言板---创建页面表单
async create() {
const { ctx } = this;
//渲染公共模版
await ctx.renderTemplate({
title: '创建留言板',//现在网页title,面包屑导航title,页面标题
tempType: 'form', //模板类型:table表格模板 ,form表单模板
form: {
//提交地址
action: "/admin/message/save",
// 字段
fields: [
{
label: '您的称呼',
type: 'text',
name: 'username',
placeholder: '请输入您的称呼',
// default:'默认值测试', //新增时候默认值,可选
},
{
label: '您的电话',
type: 'text',
name: 'telnumber',
placeholder: '请输入您的电话',
},
{
label: '您的留言',
type: 'text',
name: 'message',
}
],
},
//新增成功之后跳转到哪个页面
successUrl: '/admin/message/index',
});
}
//创建留言板提交数据
async save() {
//一般处理流程
//1.参数验证
this.ctx.validate({
username: {
type: 'string', //参数类型
required: true, //是否必须
// defValue: '',
desc: '您的称呼' //字段含义
},
telnumber: {
type: 'phone',
required: true,
// defValue: '',
desc: '您的电话'
},
});
let { username, telnumber, message } = this.ctx.request.body;
// 如果一个用户只能提交一次留言,那么可以通过电话判断,多次则拒绝
if (await this.app.model.Message.findOne({ where: { telnumber } })) {
return this.ctx.apiFail('您已经提交过留言了,我们会尽快联系您');
}
//为了满足数据库设计需要,对电话做一个加密
let tel = await this.aesEncrypt(telnumber, secret.key, secret.iv);
//否则不存在则写入数据库
await this.app.model.Message.create({
username,
telnumber,
tel,
message
});
this.ctx.apiSuccess('留言成功');
}
//对称加密
async aesEncrypt(data, key, iv) {
// 给定的算法,密钥和初始化向量(iv)创建并返回Cipher对象
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv)
// 指定要摘要的原始内容,可以在摘要被输出之前使用多次update方法来添加摘要内容
// 数据的编码 utf8 返回值的编码 hex
var crypted = cipher.update(data, 'utf8', 'hex')
crypted += cipher.final('hex')
return crypted
}
//对称解密
async aesDecrypt(data, key, iv) {
// 给定的算法,密钥和初始化向量(iv)创建并返回Cipher对象
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
// 数据的编码 hex 返回值的编码 utf8
var decrypted = decipher.update(data, 'hex', 'utf8')
decrypted += decipher.final('utf8')
return decrypted
}
}
module.exports = MessageController;
# 定义路由
app/router/admin/admin.js
// 创建留言板界面
router.get('/admin/message/create', controller.admin.message.create);
//创建留言板提交数据
router.post('/admin/message/save', controller.admin.message.save);
# 五、留言列表、修改留言、删除留言
# 控制器 app/controller/admin/message.js
'use strict';
let crypto = require('crypto');
//自定义IV(16位)、key(密钥(32位的'aes-256-cbc')(24位的'aes-192-cbc'))
const secret = {
iv: 'IloveYOU@520520!',// 初始化向量(iv)16位
key: 'a123456789@!*&%bcdef@123456789&&', // 32 位秘钥密钥
}
const Controller = require('egg').Controller;
class MessageController extends Controller {
//创建留言板列表页面
async index() {
const { ctx, app } = this;
let data = await ctx.page('Message');
//渲染公共模版
await ctx.renderTemplate({
title: '留言板列表',//现在网页title,面包屑导航title,页面标题
data,
tempType: 'table', //模板类型:table表格模板 ,form表单模板
table: {
//表格上方按钮,没有不要填buttons
buttons: [
{
url: '/admin/message/create',//新增路径
desc: '提交留言',//新增 //按钮名称
// icon: 'fa fa-plus fa-lg',//按钮图标
}
],
//表头
columns: [
{
title: '留言用户称呼',
key: 'username',
},
{
title: '留言用户电话',
key: 'telnumber',
},
{
title: '留言内容',
key: 'message',
},
{
title: '留言时间',
key: 'create_time',
width: 200,//可选
class: 'text-center',//可选
},
{
title: '操作',
class: 'text-right',//可选
action: {
//修改
edit: function (id) {
return `/admin/message/edit/${id}`;
},
//删除
delete: function (id) {
return `/admin/message/delete/${id}`;
}
}
},
],
},
});
}
//删除留言功能
async delete() {
const { ctx, app } = this;
const id = ctx.params.id;
await app.model.Message.destroy({
where: {
id
}
});
//提示
ctx.toast('留言删除成功', 'success');
//跳转
ctx.redirect('/admin/message/index');
}
//修改留言界面
async edit() {
const { ctx, app } = this;
const id = ctx.params.id;
let data = await app.model.Message.findOne({
where: {
id
}
});
if (!data) {
return ctx.pageFail('该留言不存在', 404);
}
data = JSON.parse(JSON.stringify(data));
//渲染公共模版
await ctx.renderTemplate({
id,
title: '修改留言',//现在网页title,面包屑导航title,页面标题
tempType: 'form', //模板类型:table表格模板 ,form表单模板
form: {
//修改留言提交地址
action: '/admin/message/update/' + id,
// 字段
fields: [
{
label: '您的称呼',
type: 'text',
name: 'username',
placeholder: '请输入您的称呼',
},
{
label: '您的电话',
type: 'text',
name: 'telnumber',
placeholder: '请输入您的电话',
},
{
label: '您的留言',
type: 'text',
name: 'message',
placeholder: '请输入您的留言',
},
],
//修改内容默认值
data,
},
//修改成功之后跳转到哪个页面
successUrl: '/admin/message/index',
});
}
//修改留言数据功能
async update() {
const { ctx, app } = this;
//1.参数验证
this.ctx.validate({
id:{
type: 'int',
required: true,
desc: '留言id'
},
username: {
type: 'string', //参数类型
required: true, //是否必须
// defValue: '',
desc: '您的称呼' //字段含义
},
telnumber: {
type: 'phone',
required: true,
// defValue: '',
desc: '您的电话'
},
message: {
type: 'string',
required: false,
// defValue: '',
desc: '您的留言'
},
});
// 参数
const id = ctx.params.id;
const { username, telnumber, message } = ctx.request.body;
// 查一下是否存在这个留言记录
const data = await app.model.Message.findOne({where: { id } });
if (!data) {
return ctx.pageFail('该留言记录不存在');
}
//存在,由于电话号码具有唯一性,你不能修改留言的时候,修改成存在的电话
const Op = this.app.Sequelize.Op;//拿Op,固定写法
if(await app.model.Message.findOne({
where: {
telnumber,
id:{
[Op.ne]:id
}
}
})){
return ctx.apiFail('您已经提交过留言了,我们会尽快联系您');
}
// 修改数据
data.username = username;
data.telnumber = telnumber;
if(message){
data.message = message;
}
await data.save();
// 给一个反馈
ctx.apiSuccess('修改成功');
}
}
module.exports = MessageController;
# 定义路由
app/router/admin/admin.js
//创建留言板列表页面
router.get('/admin/message/index', controller.admin.message.index);
//删除留言功能
router.get('/admin/message/delete/:id', controller.admin.message.delete);
//修改留言界面
router.get('/admin/message/edit/:id', controller.admin.message.edit);
//修改留言数据功能
router.post('/admin/message/update/:id', controller.admin.message.update);