修改发布文章与文章列表模块

master
liuyx 2 years ago
parent 805057553b
commit 2eaf32e8d8

@ -69,7 +69,7 @@ const closeAllTab = () => {
}
const goTo = (item) => {
router.push(item)
router.push(item.path)
}
const removeTab = (item) => {
@ -149,6 +149,9 @@ watch(
border-top: 1px dotted #a8a8a8;
.tabs-content {
text-align: center;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
.tabs-content-item {
cursor: pointer;
margin-right: 5px;

@ -17,6 +17,11 @@ const routes = [
name: '发布文章',
component: () => import('@/views/article/Article.vue')
},
{
path: '/article/:id',
name: '修改文章',
component: () => import('@/views/article/Article.vue')
},
{
path: '/article-list',
name: '文章列表',

@ -1,107 +0,0 @@
<template>
<el-upload
class="avatar-uploader"
action="https://upload-z2.qiniup.com"
:show-file-list="false"
:http-request="up2qiniu"
:before-upload="beforeUpload"
>
<img
v-if="props.url"
:src="props.url"
class="avatar"
:style="'width: ' + props.width + 'px;' + 'height: ' + props.height + 'px;'"
/>
<el-icon
v-else
class="avatar-uploader-icon"
:style="'width: ' + props.width + 'px;' + 'height: ' + props.height + 'px;'"
><Plus
/></el-icon>
</el-upload>
</template>
<script setup>
import { ref } from 'vue'
import { getQiniuToken } from '../api/token'
import axios from 'axios'
import { ElMessage } from 'element-plus'
const qiniuaddr = 'rlr92qkze.hn-bkt.clouddn.com'
const imageUrl = ref('')
// url180
const props = defineProps({
url: String,
width: {
type: Number,
default: 180
},
height: {
type: Number,
default: 180
}
})
const emit = defineEmits(['upload'])
const beforeUpload = (rawFile) => {
if (rawFile.type !== 'image/jpeg' && rawFile.type !== 'image/png') {
ElMessage.error('图片格式应该是png或jpg')
return false
} else if (rawFile.size / 1024 / 1024 > 2) {
ElMessage.error('图片大小应该小于2MB')
return false
}
return true
}
/**
* 上传图片至七牛云
* @param {*} req
*/
const up2qiniu = async (req) => {
const config = {
headers: { 'Content-Type': 'multipart/form-data' }
}
const fileType = req.file.type === 'image/png' ? 'png' : 'jpg'
//
const keyname = 'blog' + new Date().getTime() + '.' + fileType
const res = await getQiniuToken()
const formdata = new FormData()
formdata.append('file', req.file)
formdata.append('token', res.data)
formdata.append('key', keyname)
//
axios.post('https://upload-z2.qiniup.com', formdata, config).then((res) => {
imageUrl.value = 'http://' + qiniuaddr + '/' + res.data.key
emit('upload', imageUrl.value) // url
})
}
</script>
<style lang="scss" scoped>
.avatar-uploader .avatar {
width: 360px;
height: 180px;
display: block;
}
.avatar-uploader :deep(.el-upload) {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader :deep(.el-upload:hover) {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 360px;
height: 180px;
text-align: center;
}
</style>

@ -0,0 +1,223 @@
<template>
<el-card>
<el-form>
<el-form-item>
<el-row :gutter="20" style="width: 100%">
<el-col :span="20">
<span style="box-shadow: 1 0 1px #c0c4cc"
><el-input v-model="article.title" placeholder="请输入博客标题"
/></span>
</el-col>
<el-col :span="4">
<el-button
color="#626aef"
style="width: 100%; height: 100%"
@click="publishDialogVisible = true"
>发布文章</el-button
>
</el-col>
</el-row>
</el-form-item>
<el-form-item>
<v-md-editor
v-model="article.content"
height="calc(100vh - 290px)"
placeholder="在vuepress主题中, 您可以使用tip功能噢~"
/>
</el-form-item>
</el-form>
<!-- 在弹窗中选择标签分类文章图片 -->
<el-dialog v-model="publishDialogVisible" title="后台权限设置" width="40%">
<el-form :model="article" label-position="left">
<!-- 文章分类 -->
<el-form-item label="文章分类">
<el-tag
type="success"
v-show="article.category"
:closable="true"
size="large"
@close="removeCategory"
>
{{ article.category }}
</el-tag>
<!-- 分类选项 -->
<el-popover
v-if="!article.category"
placement="bottom-start"
:width="400"
trigger="click"
:hide-after="50"
>
<div class="popover-title">分类</div>
<template #reference>
<el-button type="success" plain>添加分类</el-button>
</template>
<div class="popover-container">
<div
v-for="item of categoryList"
:key="item.id"
class="category-item"
@click="addCategory(item)"
>
{{ item.name }}
</div>
</div>
</el-popover>
</el-form-item>
<!-- 文章标签 -->
<el-form-item label="文章标签">
<el-tag
v-for="item in article.tagList"
:key="item.id"
:closable="true"
size="large"
style="margin-right: 8px"
@close="removeTag(item)"
>
{{ item.name }}
</el-tag>
<!-- 标签选项 -->
<el-popover
v-if="article.tagList.length < 3"
placement="bottom-start"
:width="400"
trigger="click"
:hide-after="50"
>
<template #reference>
<el-button type="primary" plain>添加标签</el-button>
</template>
<div class="popover-title">标签</div>
<div class="popover-container">
<el-tag v-for="item of tagList" :key="item.id" class="tag-item" @click="addTag(item)">
{{ item.name }}
</el-tag>
</div>
</el-popover>
</el-form-item>
<!-- 文章封面 -->
<el-form-item label="上传封面">
<Upload :url="article.cover" :width="360" :height="180" @upload="upload" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button color="#626AEF" plain @click="publishDialogVisible = false">取消</el-button>
<el-button color="#626AEF" @click="publishArticle"> </el-button>
</span>
</template>
</el-dialog>
</el-card>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import Upload from '@/components/Upload.vue'
// import axios from 'axios'
import { useRoute } from 'vue-router'
import axios from 'axios'
const route = useRoute()
const article = ref({
id: null,
cover: '',
title: '',
content: '',
tagList: [],
category: ''
})
const publishDialogVisible = ref(false) //
const categoryList = ref([
{
id: 1,
name: '工具'
},
{
id: 2,
name: 'Vue'
},
{
id: 3,
name: '面试'
}
])
const tagList = ref([
{
id: 1,
name: 'JS'
},
{
id: 2,
name: 'Linux'
},
{
id: 3,
name: 'Vite'
}
])
onMounted(() => {
if (route.params.id) {
axios.get('/api/article/' + route.params.id).then((res) => {
console.log(res)
article.value = res.data
})
}
})
const removeCategory = () => {
article.value.category = null
}
const addCategory = (item) => {
article.value.category = item.name
}
const addTag = (item) => {
if (
article.value.tagList.length < 3 &&
article.value.tagList.findIndex((it) => it.id === item.id) === -1
) {
article.value.tagList.push(item)
}
}
const removeTag = (item) => {
const idx = article.value.tagList.findIndex((it) => it.id === item.id)
article.value.tagList.splice(idx, 1)
}
const publishArticle = () => {
publishDialogVisible.value = false
console.log(article.value)
}
const upload = (url) => {
// Uploadurlarticlecover
article.value.cover = url
}
</script>
<style lang="scss" scoped>
.popover-title {
text-align: center;
margin-bottom: 10px;
}
.popover-container {
margin-top: 1rem;
height: 200px;
overflow-y: auto;
.category-item {
cursor: pointer;
padding: 0.6rem 0.5rem;
}
.category-item:hover {
background-color: #f0f9eb;
color: #67c23a;
}
.tag-item {
cursor: pointer;
margin-right: 8px;
}
}
</style>

@ -0,0 +1,144 @@
<template>
<el-card>
<el-button
style="margin-bottom: 20px"
type="danger"
plain
:disabled="isMultiple"
@click="multipleDelete"
>批量删除</el-button
>
<el-table
:data="articleList"
:border="true"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<!-- 多选 -->
<el-table-column type="selection" width="55" align="center" />
<el-table-column prop="cover" label="文章图片" align="center">
<template #default="scope">
<el-image
class="article-cover"
:src="
scope.row.cover
? scope.row.cover
: 'https://static.talkxj.com/articles/c5cc2b2561bd0e3060a500198a4ad37d.png'
"
/>
</template>
</el-table-column>
<el-table-column prop="title" label="文章标题" align="center" />
<el-table-column prop="category" label="分类" align="center">
<template #default="scope">
<el-tag type="success">{{ scope.row.category }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="tags" label="标签" align="center">
<template #default="scope">
<el-tag v-for="tag in scope.row.tagList" :key="tag.id" style="margin: 0 6px 5px 0">
{{ tag }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="views" label="浏览量" align="center" />
<el-table-column prop="createTime" label="发表时间" align="center" />
<el-table-column prop="updateTime" label="更新时间" align="center" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button type="primary" @click="updateArticle(scope.row.id)"></el-button>
<el-button type="danger" @click="deleteArticle(scope.row.id)"></el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
class="pagination-container"
v-model:current-page="paginition.currentPage"
v-model:page-size="paginition.pageSize"
:page-sizes="[10, 20]"
background
layout="total, sizes, prev, pager, next, jumper"
:total="paginition.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</el-card>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const isMultiple = ref(true)
const multipleSelection = ref([])
const router = useRouter()
const articleList = [
{
id: 123,
cover: 'https://typora-lyx.oss-cn-guangzhou.aliyuncs.com/typora/wallhaven-6dqemx.jpg',
title: '测试',
category: '分类1',
tagList: ['标签1', '标签2', '标签3'],
views: 0,
createTime: '2022-11-17',
updateTime: '2022-11-17'
},
{
id: 124,
cover: 'https://typora-lyx.oss-cn-guangzhou.aliyuncs.com/typora/wallhaven-6dqemx.jpg',
title: '测试',
category: '分类1',
tagList: ['标签1', '标签2', '标签3'],
views: 0,
createTime: '2022-11-17',
updateTime: '2022-11-17'
}
]
const paginition = ref({
currentPage: 1,
pageSize: 10,
total: 40
})
const multipleDelete = () => {
console.log(multipleSelection.value)
}
const handleSelectionChange = (selection) => {
// multipleSelectionselection
multipleSelection.value = selection
if (multipleSelection.value.length <= 0) {
isMultiple.value = true
} else {
isMultiple.value = false
}
}
const updateArticle = (id) => {
router.push({
name: '修改文章',
params: {
id
}
})
}
const deleteArticle = (id) => {
console.log(id)
}
const handleSizeChange = (val) => {
console.log(`${val} items per page`)
}
const handleCurrentChange = (val) => {
console.log(`current page: ${val}`)
}
</script>
<style lang="scss" scoped>
.pagination-container {
margin-top: 25px;
justify-content: flex-end;
}
</style>
Loading…
Cancel
Save