# 大事件综合项目实战
# 1. 初始化环境
大事件为综合实战项目,但是我们只关注前端的实现,数据库与后端相关内容用老师提供的即可。
# 1.1 数据库初始化
执行初始化数据库脚本前,需要确保已经创建bignews
数据库
// 登录数据库后,可以执行下面命令创建
create database bignews
# 1.2 执行初始化数据库脚本
执行脚本之前,需要修改配置文件config/index.js
,把数据库密码修改为自己的密码。
module.exports ={
// 数据库名
database:'bignews',
// 用户名
username:'root',
// 密码
password:'123456',
host:'127.0.0.1',
port:8080,
baseUrl:'http://localhost'
}
修改完毕后,双击根目录的初始化数据.bat
文件把初始数据导入数据库中。
# 1.3 启动服务端
因为页面需要请求服务器数据,在开发时需要确保服务端已经启动,双击根目录下的开始.bat
启动即可
# 2. 项目结构
# 3.登录页面
页面路径:/admin/login.html
逻辑路径:/admin/js/login.js
💡知识点一:token处理,为了保存用户登录状态,需要把token在登录成功时保存到本地缓存
💡知识点二:模态框显示与隐藏, 浏览器自带的alert提示框太简陋,可以集成bootstrap的模态框插件更友好的提示信息
# 3.1 登录功能实现
// 1、用户登录
function login() {
// 1.1 获取用户名和密码,并且去除空格
const username = $('.input_txt').val().trim();
const password = $('.input_pass').val().trim();
// 1.2 判断用户名或者密码是否为空
if (username === '' || password === '') {
// 显示模态框
$('.modal-body').text('用户名和密码不能为空');
$('#loginModal').modal('show')
// 阻止后面代码的执行
return;
}
// 1.3 发送用户名和密码到服务端
$.post('http://localhost:8080/api/v1/admin/user/login', { username, password }, (res) => {
// code等于200表示登录成功
if (res.code === 200) {
// 1.4 把服务端返回的token记录到本地存储
window.localStorage.setItem('bignews_token', res.token);
// 1.5 跳转到首页
window.location.href = './index.html'
} else {
// 1.6 登录失败,使用模态框显示错误信息
$('.modal-body').text(res.msg);
$('#loginModal').modal('show')
}
})
}
# 3.2 模态框提示信息
login.html加入模态框代码片段
<!-- 模态框 -->
<div class="modal fade" id="loginModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">友情提示</h4>
</div>
<div class="modal-body">
<p></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">朕知道了</button>
</div>
</div>
</div>
</div>
login.js控制模态框显示状态与文本
// 设置模态框文本内容
$('.modal-body').text('提示内容');
// 弹出模态框
$('#loginModal').modal('show')
# 4. 首页
页面路径:/admin/index.html
逻辑路径:/admin/js/index.js
💡知识点一:iframe的使用,首页通过点击侧边栏,中间区域切换显示不同内容
# 4.1 显示个人信息
因为个人信息接口需要登录后才能访问,所以我们把登录成功后得到的token放到请求头中
$.ajax({
type: 'get',
url: 'http://localhost:8080/api/v1/admin/user/info',
headers: {
// 记得把token放在请求头,否则会出现权限问题
Authorization: window.localStorage.getItem('bignews_token'),
},
success: (res) => {
if (res.code == 200) {
// 返回数据后,把昵称头像等信息放到页面上
$('.user_info > span').html('欢迎 ' + res.data.nickname);
$('.user_info > img').attr('src', res.data.userPic);
$('.user_center_link > img').attr('src', res.data.userPic);
}
},
error: (err) => {
// 如果服务端返回403的壮体,说明没有访问权限,跳转到登录页
if (err.status === 403) {
window.location.href = './login.html';
}
},
});
# 4.2 利用iframe实现页面切换
首先在div中插入iframe
,并设置name
属性,name
属性可以让a
标签找到它,设置宽高为100%
同时把src
属性设置为./main_count.html
<!-- 右侧主体内容 -->
<div class="main" id="main_body">
<iframe name="main_frame" src="./main_count.html" frameborder="0" width="100%" height="100%"></iframe>
</div>
把侧边栏a
标签的src
属性设置为不同页面,下面是html文件对应关系
main_count.html 首页
article_list.html 文章列表
article_release.html 发表文章
article_category.html 文章类别管理
comment_list.html 评论管理
user.html 个人中心
# 4.3 侧边栏点击效果
1、实现点击一级分类显示激活状态
2、实现点击“文章管理”分类展开二级分类
// 点击侧边栏切换成激活状态
$('.level01').on('click', function(e) {
// 1.1 把已经选中的元素先删除active状态
$('.level01.active').removeClass('active')
// 1.2 把点击的元素增加active的类名
$(this).addClass('active');
// 2.1 如果点击的是“文章管理”分类,展开二级分类
if($(this).html().indexOf('文章管理') > -1) {
// 2.2 展开子分类
$('.level02').slideToggle();
// 2.3 把箭头旋转
$(this).find('b').toggleClass('rotate0')
}
})
3、点击二级分类,二级分类显示激活状态
// 把二级分类设置点击显示激活状态
$('.level02>li').on('click',function(){
$('.level02>li.active').removeClass('active')
$(this).addClass('active')
});
# 5. 个人中心
页面路径:/admin/user.html
逻辑路径:/admin/js/user.js
# 5.1 显示个人信息到输入框
// 进入页面,获取用户信息
$.ajax({
type: 'get',
url: 'http://localhost:8080/api/v1/admin/user/detail',
headers: {
// 记得把token放在请求头,否则会出现权限问题
Authorization: window.localStorage.getItem('bignews_token'),
},
success: (res) => {
if (res.code == 200) {
// 用户名
$('#username').val(res.data.username);
// 昵称
$('#nickname').val(res.data.nickname);
// 邮箱
$('#email').val(res.data.email);
// 密码
$('#password').val(res.data.password);
// 头像
$('.user_pic').attr('src', res.data.userPic);
}
},
error: (err) => {
// 如果服务端返回403的壮体,说明没有访问权限,跳转到登录页
if (err.status === 403) {
window.location.href = './login.html';
}
},
});
# 5.2 封装网络层
因为发送ajax请求时,都需要在发送前获取token放在请求头中,如果服务端响应403错误码都要跳转到登录页面,这些相同的处理会出现大量重复代码,所以我们需要把代码进行封装
http.js文件代码
const http = { };
// 基础URL
const BASE_URL = 'http://localhost:8080/api/v1'
/**
* get请求方法
* @param {*} url 请求的地址
* @param {*} data 请求参数
* @param {*} success 成功回调
*/
http.request = function(type ,url, data, success) {
$.ajax({
type: type,
url: BASE_URL + url,
data: data,
headers: {
// 记得把token放在请求头,否则会出现权限问题
Authorization: window.localStorage.getItem('bignews_token'),
},
success: (res) => {
success(res)
},
error: (err) => {
// 如果服务端返回403的壮体,说明没有访问权限,跳转到登录页
if (err.status === 403) {
window.location.href = './login.html';
}
},
});
}
那么刚才获取用户信息的请求就可以改成下面代码
http.request('get', '/admin/user/detail', {}, (res) => {
if (res.code == 200) {
// 用户名
$('#username').val(res.data.username);
// 昵称
$('#nickname').val(res.data.nickname);
// 邮箱
$('#email').val(res.data.email);
// 密码
$('#password').val(res.data.password);
// 头像
$('.user_pic').attr('src', res.data.userPic);
}
})
# 5.3 预览上传图片
预览图片上传最核心是使用了URL.createObjectURL
方法创建图片URL,然后把URL放到img
标签中
// 2、图片预览
// 2.1 监听onchange事件
$('#exampleInputFile').on('change', () => {
// 2.2 获取file对象
const file = $('#exampleInputFile')[0].files[0];
// 2.3 使用createObjectURL方法创建临时URL
const url = URL.createObjectURL(file);
// 2.4 把临时图片URL放回image标签的src属性
$('.user_pic').attr('src', url);
})
# 5.4 修改个人信息
$('.btn-edit').on('click', (e) => {
e.preventDefault();
// 3、收集编辑信息并提交给服务端
// 3.1 服务端需要使用FromData的数据类型,那我们就可以利用FromData对象自动收集表单数据了
const myform = $('#form')[0]; // 把jq对象转换为普通对象
// 3.2 创建formdata对象,把表单作为参数参数,会自动收集具有name属性的input字段
const formdata = new FormData(myform);
// 3.3 发送请求
http.request('post', '/admin/user/edit', formdata, (res) => {
if(res.code === 200) {
alert(res.msg);
}
})
});
⚠️注意,因为上面封装的http.request方法不支持FormData类型数据发送,所以在调用该方法前需要先进行类型判断,加入processData
和contentType
属性设置
http.request = function(type ,url, data, success) {
// 如果是FormData对象,需要设置processData为false,contentType为false
const isFormData = (data instanceof FormData);
$.ajax({
processData: isFormData? false: true,
contentType: isFormData? false: 'application/x-www-form-urlencoded',
});
}
# 6. 文章管理--分类模块
页面路径:/admin/article_category.html
逻辑路径:/admin/js/article_category.js
# 6.1 获取所有分类
接口地址 /admin/category/list
/admin/js/article_category.js
// 1、获取所有分类
function getAll() {
http.request('get', '/admin/category/list', {}, (res) => {
if (res.code === 200) {
// 使用artTemplate渲染数据
const renderResult = template('categoryTemplate', res);
$('tbody').html(renderResult);
}
})
}
getAll();
/admin/article_category.html
<script id='categoryTemplate' type="text/html">
{{each data}}
<tr>
<td>{{$value.name}}</td>
<td>{{$value.slug}}</td>
<td class="text-center">
<a href="javascript:void(0)" data-toggle="modal" class=" btn btn-info btn-xs">编辑</a>
<a href="javascript:void(0)" class="btn btn-danger btn-xs">删除</a>
</td>
</tr>
{{/each}}
</script>
# 6.2 删除分类
/admin/js/article_category.js
// 2、实现删除分类
function deleteCategory(id) {
http.request('post', '/admin/category/delete', { id }, (res) => {
if (res.code === 204) {
alert(res.msg);
this.getAll();
}
})
}
/admin/article_category.html
<!-- 加入删除方法的调用 -->
<a href="javascript:void(0)" class="btn btn-danger btn-xs" onclick="deleteCategory({{$value.id}})">删除</a>
# 6.3 编辑分类
点击编辑按钮的时,传入data数据,data数据表示当前编辑的分类,将数据还原到输入框中
⚠️注意,当前分类id因为发送请求的时候需要用到,我们把它保存在this中
function editCategory(data) {
// 3.1 显示编辑分类窗
$('.add_category_wraper').show();
// 3.2 data为当前编辑的分类数据,需要获取data的数据还原到输入框上
$('#name').val(data.name);
$('#slug').val(data.slug);
this.id = data.id;
}
点击保存时,要注意因为新增和编辑都是用同一个按钮,可以通过this.id是否有值判断是否为编辑操作
function saveCategory() {
const id = this.id;
const name = $('#name').val();
const slug = $('#slug').val();
// 如果有id值,说明是在编辑状态
if (id) {
http.request('post', '/admin/category/edit', { id, name, slug }, (res) => {
alert(res.msg);
// 隐藏分类窗
this.hideCategory();
this.getAll();
})
} else {
// 新增状态
http.request('post', '/admin/category/add', { name, slug }, (res) => {
alert(res.msg);
this.hideCategory();
this.getAll();
})
}
}
# 6.4 新增操作
点击新增按钮,只要把输入框弹出即可
function showCategory() {
$('.add_category_wraper').show();
}
点击保存的时候,发送ajax请求
function saveCategory() {
const id = this.id;
const name = $('#name').val();
const slug = $('#slug').val();
// 如果有id值,说明是在编辑状态
if (id) {
http.request('post', '/admin/category/edit', { id, name, slug }, (res) => {
alert(res.msg);
// 隐藏分类窗
this.hideCategory();
this.getAll();
})
} else {
// 新增状态
http.request('post', '/admin/category/add', { name, slug }, (res) => {
alert(res.msg);
this.hideCategory();
this.getAll();
})
}
}
# 6.5 修复数据显示的bug
当点击编辑后,数据会还原到输入框,当再次点击新增会导致输入框内有上次编辑的内容,为了修复这个问题,可以在隐藏编辑框的时候清空数据
function hideCategory() {
$('.add_category_wraper').hide();
// 为了修复点击编辑后再点击新增,导致数据显示问题,所以每次隐藏的时候,清空数据
this.id = null;
$('#name').val('');
$('#slug').val('');
}
# 7.文章管理
页面路径:/admin/article_list.html
逻辑路径:/admin/js/article_list.js
# 7.1 获取所有分类
/admin/js/article_list.js
function getAllCategory() {
http.request('get', '/admin/category/list', {}, (res) => {
if (res.code === 200) {
const renderResult = template('categoryTemplate', res)
$('#selCategory').html(renderResult);
}
})
}
getAllCategory();
/admin/article_list.html
<script id="categoryTemplate" type="text/html">
<option value="">所有分类</option>
{{each data}}
<option value="{{$value.id}}">{{$value.name}}</option>
{{/each}}
</script>
# 7.2 获取文章列表
/admin/js/article_list.js
function getArticle() {
// 筛选分类
const type = $('#selCategory').val();
// 文章状态,草稿或者已发布
const state = $('#selStatus').val();
http.request('get', '/admin/article/query', {type, state}, (res) => {
const renderResult = template('articleTemplate', res.data)
$('tbody').html(renderResult);
});
}
/admin/article_list.html
<!-- 文章列表模版 -->
<script id="articleTemplate" type="text/html">
{{each data}}
<tr>
<td>{{$value.title}}</td>
<td>{{$value.author}}</td>
<td>{{$value.category}}</td>
<td class="text-center">{{$value.daate}}</td>
<td class="text-center">{{$value.state}}</td>
<td class="text-center">
<a href="article_edit.html?id={{$value.id}}" class="btn btn-default btn-xs">编辑</a>
<a href="javascript:void(0);" class="btn btn-danger btn-xs delete">删除</a>
</td>
</tr>
{{/each}}
</script>
# 7.3 删除文章
// 3、删除文章
function deleteArticle(id) {
http.request('post', '/admin/article/delete', {id}, (res) => {
if (res.code === 204) {
alert('删除成功')
this.getArticle();
} else {
alert(res.msg);
}
})
}
# 7.4 文章分页
由于文章数据较多,一次请求所有文章会导致访问非常缓慢,所以当碰到较多数据时,往往通过分页来实现分批获取数据。
分页中常出现的字段:
- totalCount:文章的总条数
- perpage:每页显示条数
- totalPage:文章的总页数,该字段和每页显示的条数有关联关系,例如totalCount为10,perpage为2条,那totalPage就是5。
- page:当前页
分页功能我们可以借助jquery的插件完成,简化实现的过程,当然你也可以自己实现,也不是很困难。
使用twbsPagination插件实现分页步骤:
1、引入twbsPagination插件
2、初始化分页插件
首先要在页面增加一个元素,用于显示分页HTML
<ul id="pagination"></ul>
通过js初始化分页插件
$('#pagination').twbsPagination({
totalPages: total, // 总的页数
visiblePages: 5, // 显示多少页
first:'首页',
last:'末页',
prev:'上一页',
next:'下一页',
// 当点击页码获取对应页面数据
onPageClick: (event, page) => {
this.getArticle(page);
}
});
根据页码获取文章:
function getArticle(page) {
// 筛选分类
const type = $('#selCategory').val();
// 文章状态,草稿或者已发布
const state = $('#selStatus').val();
http.request('get', '/admin/article/query', { type, state, page }, (res) => {
const renderResult = template('articleTemplate', res.data);
$('tbody').html(renderResult);
// 初始化分页组件
this.initPagination(res.data.totalPage);
});
}
# 7.5 文章编辑
准备知识:jedate时间插件,tinyMCE富文本编辑插件
# 7.5.1 jedate的使用
文章编辑模块有一个发布时间输入框用于获取文章的发布时间,如果管理员手工输入时间,会比较麻烦而且容易出错,所以我们需要一个时间插件让用户选择时间。
下面是最简单的使用代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- 1、引入jedate插件资源 -->
<link rel="stylesheet" href="./jedate/css/jedate.css" />
<script src="./jedate/js/jedate.js"></script>
<title>Document</title>
</head>
<body>
<!-- 2、页面定义input用户选择时间 -->
<input id="myDate" type="text" placeholder="请选择" readonly>
</body>
<script>
// 3、初始化日期插件
jeDate('#myDate', {
format: 'YYYY-MM-DD', // 显示格式
});
</script>
</html>
# 7.5.2 tinyMCE使用
在编写文章时,往往需要对文字进行加粗,加斜体之类的格式,但是网页不像word那样可以随意设置格式,html中不同格式需要相应的标签进行包裹,例如加粗<strong>文章标题</strong>
,为了实现网页能像word一样编辑文字,需要用到富文本编辑器tinyMCE
。
tinyMCE使用代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>富文本</title>
<!-- 1、引入资源 -->
<script src="./tinymce/tinymce.min.js"></script>
</head>
<body>
<!-- 2、定义富文本元素 -->
<div id="richText"></div>
</body>
<!-- 3、初始化 -->
<script>
tinymce.init({
selector: "#richText"
})
</script>
</html>
# 7.5.3 整合时间插件和富文本插件
/admin/article_edit.html
1、头部引入资源
<!-- 引入时间插件 -->
<script src="./libs/jedate/js/jedate.js"></script>
<link rel="stylesheet" href="./libs/jedate/css/jedate.css">
<!-- 引入富文本插件 -->
<script src="./libs/tinymce/tinymce.min.js"></script>
2、页面加入必要元素
<div class="col-sm-4">
<!-- 时间选择框 -->
<input id="articleDate" name='date' class="jeinput" type="text" placeholder="请选择发布日期" readonly>
</div>
<div class="col-sm-10">
<!-- 富文本编辑区域 -->
<textarea id="articleContent">请输入文章内容</textarea>
</div>
/admin/js/article_edit.js
// 1、初始化时间插件和富文本插件
function initPlugin() {
// 初始化日期插件
jeDate('#articleDate', {
format: 'YYYY-MM-DD', // 显示格式
});
// 初始化富文本插件
tinymce.init({
selector: "#articleContent",
language: 'zh_CN',
})
}
// 页面进入即初始化插件
initPlugin();
# 7.5.4 获取文章分类
/admin/js/article_edit.js
// 1、获取分类
function getCategory() {
http.request('get' ,'/admin/category/list', {} ,(res) => {
const renderResult = template('categoryTemplate', res);
console.log(renderResult)
$('#category').html(renderResult);
})
}
getCategory();
/admin/article_edit.html
<script id="categoryTemplate" type="text/html">
{{each data}}
<option value="{{$value.id}}">{{$value.name}}</option>
{{/each}}
</script>
# 7.6.5 封装把url参数转换为对象方法
从列表页跳转到编辑页面,需要把当前编辑文章的id传递给当前页面,一般使用url进行传值,例如
http://127.0.0.1:3000/article_edit.html?id=1
可以通过window.location.search
获取请求参数?id=1
,再通过=
作为标记获取id的值,但是这样操作非常麻烦。我们需要把这种操作封装到一个公共方法中。
1、新建common.js
2、代码如下
const itcast = {
// 动态的添加项目中需要的功能函数
getArguments:function(){ //?id=2&name=jack
const str = window.location.search;
let obj = {}
// 1.去除?
str = str.substring(1) // id=2&name=jack
// 2.将str以&符合进行分隔
let arr = str.split('&') // ["id=2","name=jack"]
// 3.循环,并以=做为分隔符对数组中的元素再次分隔,将分隔的结构一个做为键,一个做为值
for(let i=0;i<arr.length;i++){
// 第一次:id=2
let temp = arr[i].split('=') // ["id",2]
// 生成对象
obj[temp[0]] = temp[1]
}
return obj
}
}
# 7.5.6文章数据回显到输入框
// 3、获取文章详情
function getArticle() {
// 3.1 获取url上的id值
const id = window.location.search.split('=')[1];
// 3.2 获取文章数据
http.request('get', '/admin/article/search', { id }, (res) => {
if (res.code === 200) {
$('#inputTitle').val(res.data.title);
// 下拉列表
$('#category').val(res.data.categoryId);
// 文章封面
$('.article_cover').attr('src', res.data.cover);
// 发布时间
$('#articleDate').val(res.data.date);
// 富文本框
$('#articleContent').val(res.data.content);
}
});
}
getArticle();
# 7.5.7 实现更改封面图片回显
// 4、实现数据回显
function changeCoverImage() {
// 1.获取图片对象
let myfile = $('#inputCover')[0].files[0];
// 2.根据图片对象创建一个url
let url = URL.createObjectURL(myfile);
// 3.将url赋值给img标签
$('.article_cover').attr('src', url);
}
# 7.5.8 修改文章
⚠️注意,因为编辑接口需要提交FormData类型数据,所以提交数据时需要利用FormData对象收集表单数据,富文本插件数据需要用过tinymce.activeEditor.getContent()
方法获取,再通过append
方法添加到formdata中。
/**
* 保存文章
* @param {*} state 已发布 或者 草稿
*/
function saveArticle(state) {
let myform = new FormData($('form')[0]);
// 获取富文本内容
const content = tinymce.activeEditor.getContent();
// 获取文章id
const id = window.location.search.split('=')[1];
myform.append('content', content);
myform.append('id', id);
myform.append('state', state);
// 发送请求,把数据传递给服务器
http.request('post', '/admin/article/edit', myform, (res) => {
if (res.code === 200) {
alert(res.msg);
window.location.href = "./article_list.html"
}
})
// 阻止表单自动跳转
return false;
}
# 7.6 发表新文章
页面地址:/admin/article_release.html
逻辑地址:/admin/js/article_release.js
发表新文章代码基本和编辑相同,可以复制编辑功能代码或者对编辑代码进行封装适配新增功能
新增功能和编辑功能不同点:
1、新增不需要还原数据
2、保存数据的时候,不需要提交id给服务端,请求地址也不同。
# 8、首页图表
# 8.1 eCharts快速入门
1、引入 ECharts
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- 引入 ECharts 文件 -->
<script src="echarts.min.js"></script>
</head>
</html>
2、绘制一个简单的图表
在绘图前我们需要为 ECharts 准备一个具备高宽的 DOM 容器。
<body>
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="main" style="width: 600px;height:400px;"></div>
</body>
然后就可以通过 echarts.init 方法初始化一个 echarts 实例并通过 setOption 方法生成一个简单的柱状图,下面是完整代码。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ECharts</title>
<!-- 引入 echarts.js -->
<script src="echarts.min.js"></script>
</head>
<body>
<!-- 为ECharts准备一个具备大小(宽高)的Dom -->
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var option = {
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
legend: {
data:['销量']
},
xAxis: {
data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>
这样你的第一个图表就诞生了!
# 9、评论管理
页面地址:/admin/comment_list.html
逻辑地址:/admin/js/comment_list.js
# 9.1 显示评论列表
/admin/comment_list.html
<script id="commentTemplate" type="text/html">
{{each data item index}}
<tr>
<td>{{item.author}}</td>
<td>{{item.content}}</td>
<td>{{item.title}}</td>
<td>{{item.date}}</td>
<td>{{item.state}}</td>
<td class="text-center">
<a href="javascript:void(0);;" class="btn btn-warning btn-xs">拒绝</a>
<a href="javascript:void(0);;" class="btn btn-danger btn-xs">删除</a>
</td>
</tr>
{{/each}}
</script>
/admin/js/comment_list.js
获取评论数据并调用template
方法渲染模版
// 1、获取评论列表数据
function getCommentList(page) {
http.request('get', '/admin/comment/search', { page, perpage: 10 }, (res) => {
if (res.code === 200) {
// 使用art-template渲染数据
const renderResult = template('commentTemplate', res.data);
$('tbody').html(renderResult);
// 2.1 初始化分页插件
initPagination(res.data.totalPage, 1);
}
})
}
getCommentList(1);
# 9.2 实现分页
1、引入jquery分页插件
<script src="./libs/jquery.twbsPagination.js"></script>
2、分页插件初始化
// 2、实现分页
function initPagination(totalPages) {
$('#pagination').twbsPagination({
totalPages, // 总的页数
visiblePages: 5, // 显示多少页
first:'首页',
last:'末页',
prev:'上一页',
next:'下一页',
onPageClick: (event, page) => {
this.getCommentList(page);
}
});
}
# 9.3 批准评论
// 3、批准评论
$('tbody').on('click', '.btnAccept', (e) =>{
const id = $(e.target).attr('data-id');
http.request('post', '/admin/comment/pass', { id }, (res) => {
if (res.code === 200) {
// 刷新页面数据
this.getCommentList();
} else {
alert(res.msg);
}
})
})
# 9.4 拒绝评论
// 4、拒绝评论
$('tbody').on('click', '.btnReject', (e) =>{
const id = $(e.target).attr('data-id');
http.request('post', '/admin/comment/reject', { id }, (res) => {
if (res.code === 200) {
// 刷新页面数据
this.getCommentList();
} else {
alert(res.msg);
}
})
})
# 9.5 删除评论
// 5、删除评论
$('tbody').on('click', '.btnDelete', (e) =>{
const id = $(e.target).attr('data-id');
http.request('post', '/admin/comment/delete', { id }, (res) => {
if (res.code === 200) {
// 刷新页面数据
this.getCommentList();
} else {
alert(res.msg);
}
})
})