持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情
首先在article.js文件中修改一下根据id获取文章的接口地址。
export function getArticleById(id){
return request({
url: '/article/getArticle/' + id,
method: 'get'
})
}
还有之前我们点击发布文章之后,没有返回到列表页,现在我们先添加上这个功能,只要在之前写的方法里添加上跳转的地址即可。添加这一句话:this.$router.push("/articles/list");
var body = this.article;
addArticle(body).then(res => {
if(res.code === 200) {
this.$notify({
title: "文章发表成功",
message: `文章《${this.article.title}》发表成功!`,
type: "success",
});
this.$router.push("/articles/list");
} else {
this.$notify({
title: "文章发表失败",
message: `文章《${this.article.title}》发表失败!`,
type: "error",
});
}
this.showDialog = false;
})
同时在发布草稿的方法里也要加上这一句。
// ------- 保存草稿
saveDraft() {
this.article.artStatus = 3;
if (this.article.title.trim() == "") {
this.$message.error("文章标题不能为空");
return false;
}
if (this.article.content.trim() == "") {
this.$message.error("文章内容不能为空");
return false;
}
var body = this.article;
addArticle(body).then(res => {
if(res.code === 200) {
this.$message({
type: 'success',
message: '保存草稿成功!'
});
this.$router.push("/articles/list");
} else {
this.$message({
type: 'error',
message: '保存草稿失败!'
});
}
})
},
列表页面
页面和其他的列表差不多,这里我按照模块展示。
我先将return方法里的参数写出来。
data() {
return {
list: null,
listLoading: true,
count: 0,
listQuery: {
pageNum: 1,
pageSize: 10,
categoryId: null,
artStatus: null,
title: null
},
categoryId: null,
categoryList: [],
tagId: null,
tagList: [],
title: null,
typeList: [
{
value: 1,
label: "发布"
},
{
value: 2,
label: "仅我可见"
},
{
value: 3,
label: "草稿"
}
],
artStatus: null,
views: null,
totalWords: null,
description: null
}
},
然后将接口导入进来
import { articleList, deleteArticle } from '@/api/article'
import { getCategory } from '@/api/category'
import { getTag } from '@/api/tag'
接着写页面功能。
<!-- 设置标题文章管理 -->
<div slot="header" class="clearfix">
<span>文章列表</span>
</div>
分类查询
废话不多说直接上代码,完整代码再最后,可直接跳过看完整代码。
<!-- 文章分类 -->
<el-select
clearable
size="small"
v-model="categoryId"
filterable
placeholder="请选择分类"
style="margin-right:1rem"
>
<el-option
v-for="item in categoryList"
:key="item.id"
:label="item.categoryName"
:value="item.categoryId"
/>
</el-select>
这里遍历了categoryList,而这个list则是查询全部分类获取的,所以我们要写一个方法来查询分类,还要在页面初始的时候就要查询出来。接口还是那个添加文章的分类下拉的。
getCategoriesList() {
var categoryName = "";
getCategory({categoryName}).then(response => {
this.categoryList = response.data;
})
},
现在是有值了,然后再初始化页面的时候就加载完成。
created() {
this.getList();
this.getCategoriesList();
},
好啦,这时候可以看一下页面:
4.2.2、文章类型查询
接下来我们再继续写文章的类型查询。
<!-- 文章类型 -->
<el-select
clearable
v-model="artStatus"
placeholder="请选择文章类型"
size="small"
style="margin-right:1rem"
>
<el-option
v-for="item in typeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
typeList这个数据就是data方法中的数组,在上边已经列出来了
typeList: [
{
value: 1,
label: "发布"
},
{
value: 2,
label: "仅我可见"
},
{
value: 3,
label: "草稿"
}
],
同样也要在页面加载的时候一起加载数据,将方法也要放到created中
created() {
this.getList();
this.getCategoriesList();
this.getTagsList();
},
文章标题查询
还有一个标题的搜索和点击搜索的按钮,当点击搜索的按钮触发查询的接口。
<!-- 文章名 -->
<el-input
clearable
v-model="title"
prefix-icon="el-icon-search"
size="small"
placeholder="请输入文章名"
style="width:200px"
@keyup.enter.native="searchArticles"
/>
<el-button
type="primary"
size="small"
icon="el-icon-search"
style="margin-left:1rem"
@click="searchArticles"
>
搜索
</el-button>
这里用到了一个方法:searchArticles
searchArticles() {
this.getList();
},
这里面又调用了getList方法
getList() {
this.listLoading = true
this.listQuery.categoryId = this.categoryId;
this.listQuery.title = this.title;
this.listQuery.artStatus = this.artStatus;
var body = this.listQuery;
articleList({body}).then(response => {
this.list = response.data.result
this.count = response.data.totalSize
this.listLoading = false
})
},
下面可以写数据展示的表格了,这个没什么好说的,直接上代码
<el-table v-loading="listLoading" :data="list" fit highlight-current-row style="width: 98%; margin-top:30px;">
<el-table-column align="center" label="ID" >
<template slot-scope="scope">
<span>{{ scope.row.id }}</span>
</template>
</el-table-column>
<el-table-column label="文章封面" width="180" align="center">
<template slot-scope="scope">
<img
class="article-cover"
:src=" scope.row.imageUrl" />
</template>
</el-table-column>
<!-- 文章标题 -->
<el-table-column prop="title" label="标题" align="center" />
<!-- 文章分类 -->
<el-table-column prop="categoryName" label="分类" width="110" align="center"/>
<!-- 文章标签 -->
<el-table-column prop="tagList" label="标签" width="170" align="center">
<template slot-scope="scope">
<el-tag
v-for="item of scope.row.tagList"
:key="item.id"
style="margin-right:0.2rem;margin-top:0.2rem"
>
{{ item.tagName }}
</el-tag>
</template>
</el-table-column>
<!-- 文章浏览量 -->
<el-table-column
prop="views"
label="浏览量"
width="70"
align="center"
>
<template slot-scope="scope">
<span v-if="scope.row.views">
{{ scope.row.views }}
</span>
<span v-else>0</span>
</template>
</el-table-column>
<!-- 文章总字数 -->
<el-table-column
prop="totalWords"
label="总字数"
width="70"
align="center"
>
<template slot-scope="scope">
<span v-if="scope.row.totalWords">
{{ scope.row.totalWords }}
</span>
<span v-else>0</span>
</template>
</el-table-column>
<!-- 文章描述 -->
<el-table-column prop="description" label="描述" align="center" />
<el-table-column align="center" label="操作" width="180">
<template slot-scope="scope">
<el-button type="primary" size="mini" icon="el-icon-edit" @click="editArticle(scope.row.id)">编辑</el-button>
<el-button type="danger" size="small" icon="el-icon-delete" @click="deleteArticleById(scope.row.id)" >删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
class="pagination-container"
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="this.listQuery.pageNum"
:page-size="this.listQuery.pageSize"
:total="count"
:page-sizes="[10, 20, 30]"
layout="total, sizes, prev, pager, next, jumper"
/>
方法:
handleSizeChange(pageSize) {
this.listQuery.pageSize = pageSize
this.getList()
},
handleCurrentChange(pageNum) {
this.listQuery.pageNum = pageNum
this.getList()
},
以上就是展示的功能,下面我们来写删除和编辑的,这个就比较简单了,和之前的基本上一样。
5、删除
删除后端的接口传的参数格式做了修改,我记得没有写。这里我先写出来,大家如果没有更改就修改一下,如果修改了就过掉。
/**
* 删除文章
* @return
*/
@ApiOperation(value = "删除文章")
@DeleteMapping("/delete")
@OperationLogSys(desc = "删除文章", operationType = OperationType.DELETE)
public JsonResult<Object> articleDelete(@RequestParam(value = "id") int id) {
articleService.deleteArticle(id);
return JsonResult.success();
}
前端接口:
export function deleteArticle(id) {
return request({
url: '/article/delete',
method: 'delete',
params: { id }
})
}
删除的方法:
deleteArticleById (id) {
this.$confirm('此操作将永久删除该文章, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteArticle(id).then(response => {
this.$message({
type: 'success',
message: '删除成功!'
})
this.getList()
}).catch(() => {
console.log('error')
})
}).catch(() => {
this.$message({
type: 'error',
message: '你已经取消删除该文章!'
})
})
},
这里没啥好说的,和之前的删除操作基本上一样。
6、修改功能
修改功能稍微做了一点的改变,我们看一下表格的操作栏的编辑按钮
<el-button type="primary" size="mini" icon="el-icon-edit" @click="editArticle(scope.row.id)">编辑</el-button>
点击时间绑定了一个方法,我们要传入文章的id
editArticle(id) {
this.$router.push({ name: 'Addrticles', params: { id: id }});
},
这个和之前的公告差不多,只是将这个跳转提取到了方法内实现。
相对应的,在add页面中进行接收。
created() {
const id = this.$route.params.id;
if(id) {
getArticleById(id).then((res) => {
console.log(res.data)
this.article = res.data;
});
}
},
这是编辑的功能也修改好了。
看着还可以,大家可以自己美化一下页面,到这里文章的所有功能基本上全部完成了。
以下是列表的全部代码:
<template>
<el-card class="box-card">
<!-- 设置标题文章管理 -->
<div slot="header" class="clearfix">
<span>文章列表</span>
</div>
<!-- 文章按条件查找 -->
<div style="margin-left:auto">
<!-- 文章分类 -->
<el-select
clearable
size="small"
v-model="categoryId"
filterable
placeholder="请选择分类"
style="margin-right:1rem"
>
<el-option
v-for="item in categoryList"
:key="item.id"
:label="item.categoryName"
:value="item.categoryId"
/>
</el-select>
<!-- 文章类型 -->
<el-select
clearable
v-model="artStatus"
placeholder="请选择文章类型"
size="small"
style="margin-right:1rem"
>
<el-option
v-for="item in typeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<!-- 文章名 -->
<el-input
clearable
v-model="title"
prefix-icon="el-icon-search"
size="small"
placeholder="请输入文章名"
style="width:200px"
@keyup.enter.native="searchArticles"
/>
<el-button
type="primary"
size="small"
icon="el-icon-search"
style="margin-left:1rem"
@click="searchArticles"
>
搜索
</el-button>
</div>
<el-table v-loading="listLoading" :data="list" fit highlight-current-row style="width: 98%; margin-top:30px;">
<el-table-column align="center" label="ID" >
<template slot-scope="scope">
<span>{{ scope.row.id }}</span>
</template>
</el-table-column>
<el-table-column label="文章封面" width="180" align="center">
<template slot-scope="scope">
<img
class="article-cover"
:src=" scope.row.imageUrl" />
</template>
</el-table-column>
<!-- 文章标题 -->
<el-table-column prop="title" label="标题" align="center" />
<!-- 文章分类 -->
<el-table-column prop="categoryName" label="分类" width="110" align="center"/>
<!-- 文章标签 -->
<el-table-column prop="tagList" label="标签" width="170" align="center">
<template slot-scope="scope">
<el-tag
v-for="item of scope.row.tagList"
:key="item.id"
style="margin-right:0.2rem;margin-top:0.2rem"
>
{{ item.tagName }}
</el-tag>
</template>
</el-table-column>
<!-- 文章浏览量 -->
<el-table-column
prop="views"
label="浏览量"
width="70"
align="center"
>
<template slot-scope="scope">
<span v-if="scope.row.views">
{{ scope.row.views }}
</span>
<span v-else>0</span>
</template>
</el-table-column>
<!-- 文章总字数 -->
<el-table-column
prop="totalWords"
label="总字数"
width="70"
align="center"
>
<template slot-scope="scope">
<span v-if="scope.row.totalWords">
{{ scope.row.totalWords }}
</span>
<span v-else>0</span>
</template>
</el-table-column>
<!-- 文章描述 -->
<el-table-column prop="description" label="描述" align="center" />
<el-table-column align="center" label="操作" width="180">
<template slot-scope="scope">
<el-button type="primary" size="mini" icon="el-icon-edit" @click="editArticle(scope.row.id)">编辑</el-button>
<el-button type="danger" size="small" icon="el-icon-delete" @click="deleteArticleById(scope.row.id)" >删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
class="pagination-container"
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="this.listQuery.pageNum"
:page-size="this.listQuery.pageSize"
:total="count"
:page-sizes="[10, 20, 30]"
layout="total, sizes, prev, pager, next, jumper"
/>
</el-card>
</template>
<script>
import { articleList, deleteArticle } from '@/api/article'
import { getCategory } from '@/api/category'
import { getTag } from '@/api/tag'
export default {
name: 'articleList',
created() {
this.getList();
this.getCategoriesList();
this.getTagsList();
},
data() {
return {
list: null,
listLoading: true,
count: 0,
listQuery: {
pageNum: 1,
pageSize: 10,
categoryId: null,
artStatus: null,
title: null
},
categoryId: null,
categoryList: [],
tagId: null,
tagList: [],
title: null,
typeList: [
{
value: 1,
label: "发布"
},
{
value: 2,
label: "仅我可见"
},
{
value: 3,
label: "草稿"
}
],
artStatus: null,
views: null,
totalWords: null,
description: null
}
},
methods: {
getList() {
this.listLoading = true
this.listQuery.categoryId = this.categoryId;
this.listQuery.title = this.title;
this.listQuery.artStatus = this.artStatus;
var body = this.listQuery;
articleList({body}).then(response => {
this.list = response.data.result
this.count = response.data.totalSize
this.listLoading = false
})
},
editArticle(id) {
this.$router.push({ name: 'Addrticles', params: { id: id }});
},
getCategoriesList() {
var categoryName = "";
getCategory({categoryName}).then(response => {
this.categoryList = response.data;
})
},
getTagsList() {
var tagName = "";
getTag({tagName}).then(response => {
this.tagList = response.data;
})
},
searchArticles() {
this.getList();
},
handleSizeChange(pageSize) {
this.listQuery.pageSize = pageSize
this.getList()
},
handleCurrentChange(pageNum) {
this.listQuery.pageNum = pageNum
this.getList()
},
deleteArticleById (id) {
this.$confirm('此操作将永久删除该文章, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteArticle(id).then(response => {
this.$message({
type: 'success',
message: '删除成功!'
})
this.getList()
}).catch(() => {
console.log('error')
})
}).catch(() => {
this.$message({
type: 'error',
message: '你已经取消删除该文章!'
})
})
},
},
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.pagination-container {
float: right;
margin-top: 1.25rem;
margin-bottom: 1.25rem;
}
.box-card {
width: 98%;
margin: 1%;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
.clearfix span {
font-weight: 600;
}
.article-cover {
position: relative;
width: 100%;
height: 90px;
border-radius: 4px;
}
.article-cover::after {
content: "";
background: rgba(0, 0, 0, 0.3);
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>