Merge remote-tracking branch 'origin/master'

master
dsl 6 months ago
commit 482517d231

@ -1,52 +1,73 @@
<template>
<el-card class="main-card">
<!-- 页面标题使用当前路由名称 -->
<div class="title">{{ this.$route.name }}</div>
<!-- 操作区域包含全选功能和批量操作按钮 -->
<div class="operation">
<div class="all-check">
<!-- 全选复选框indeterminate表示半选状态 -->
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">
全选
</el-checkbox>
<!-- 显示已选择的照片数量 -->
<div class="check-count">已选择{{ selectPhotoIds.length }}</div>
</div>
<!-- 批量恢复按钮将选中照片从回收站恢复选择为空时禁用 -->
<el-button
type="success"
@click="updatePhotoDelete(null)"
:disabled="selectPhotoIds.length == 0"
size="small"
icon="el-icon-deleteItem">
type="success"
@click="updatePhotoDelete(null)"
:disabled="selectPhotoIds.length == 0"
size="small"
icon="el-icon-deleteItem">
批量恢复
</el-button>
<!-- 批量删除按钮彻底删除选中照片选择为空时禁用 -->
<el-button
type="danger"
@click="batchDeletePhoto = true"
:disabled="selectPhotoIds.length == 0"
size="small"
icon="el-icon-deleteItem">
type="danger"
@click="batchDeletePhoto = true"
:disabled="selectPhotoIds.length == 0"
size="small"
icon="el-icon-deleteItem">
批量删除
</el-button>
</div>
<!-- 照片列表容器加载状态时显示loading -->
<el-row class="photo-container" :gutter="10" v-loading="loading">
<!-- 当回收站为空时显示空状态 -->
<el-empty v-if="photos.length == 0" description="暂无照片" />
<!-- 复选框组用于选择照片进行批量操作 -->
<el-checkbox-group v-model="selectPhotoIds" @change="handleCheckedPhotoChange">
<!-- 遍历照片列表生成照片项 -->
<el-col :md="4" v-for="item of photos" :key="item.id">
<el-checkbox :label="item.id">
<div class="photo-item">
<!-- 照片显示支持预览 -->
<el-image fit="cover" class="photo-img" :src="item.photoSrc" :preview-photoSrc-list="photos" />
<!-- 照片名称 -->
<div class="photo-name">{{ item.photoName }}</div>
</div>
</el-checkbox>
</el-col>
</el-checkbox-group>
</el-row>
<!-- 分页组件 -->
<el-pagination
:hide-on-single-page="true"
class="pagination-container"
@size-change="sizeChange"
@current-change="currentChange"
:current-page="current"
:page-size="size"
:total="count"
layout="prev, pager, next" />
:hide-on-single-page="true"
class="pagination-container"
@size-change="sizeChange"
@current-change="currentChange"
:current-page="current"
:page-size="size"
:total="count"
layout="prev, pager, next" />
<!-- 批量删除确认弹窗 -->
<el-dialog :visible.sync="batchDeletePhoto" width="30%">
<div class="dialog-title-container" slot="title"><i class="el-icon-warning" style="color: #ff9900" />提示</div>
<div style="font-size: 1rem">是否删除选中照片</div>
@ -60,97 +81,115 @@
<script>
export default {
//
created() {
this.listPhotos()
},
data: function () {
return {
loading: true,
batchDeletePhoto: false,
isIndeterminate: false,
checkAll: false,
photos: [],
photoIds: [],
selectPhotoIds: [],
current: 1,
size: 18,
count: 0
loading: true, //
batchDeletePhoto: false, //
isIndeterminate: false, //
checkAll: false, //
photos: [], //
photoIds: [], // ID
selectPhotoIds: [], // ID
current: 1, //
size: 18, //
count: 0 //
}
},
methods: {
//
listPhotos() {
this.axios
.get('/api/admin/photos', {
params: {
current: this.current,
size: this.size,
isDelete: 1
}
})
.then(({ data }) => {
this.photos = data.data.records
this.count = data.data.count
this.loading = false
})
.get('/api/admin/photos', {
params: {
current: this.current, //
size: this.size, //
isDelete: 1 // 1
}
})
.then(({ data }) => {
this.photos = data.data.records //
this.count = data.data.count //
this.loading = false //
})
},
//
sizeChange(size) {
this.size = size
this.listPhotos()
this.listPhotos() //
},
//
currentChange(current) {
this.current = current
this.listPhotos()
this.listPhotos() //
},
//
updatePhotoDelete(id) {
var param = {}
if (id == null) {
param = { ids: this.selectPhotoIds, isDelete: 0 }
// 使ID
param = { ids: this.selectPhotoIds, isDelete: 0 } // isDelete=0
} else {
// 使ID
param = { ids: [id], isDelete: 0 }
}
this.axios.put('/api/admin/photos/delete', param).then(({ data }) => {
if (data.flag) {
//
this.$notify.success({
title: '成功',
message: data.message
})
this.listPhotos()
this.listPhotos() //
} else {
//
this.$notify.error({
title: '失败',
message: data.message
})
}
})
this.batchDeletePhoto = false
this.batchDeletePhoto = false //
},
//
deletePhotos() {
this.axios.delete('/api/admin/photos', { data: this.selectPhotoIds }).then(({ data }) => {
if (data.flag) {
//
this.$notify.success({
title: '成功',
message: data.message
})
this.listPhotos()
this.listPhotos() //
} else {
//
this.$notify.error({
title: '失败',
message: data.message
})
}
})
this.batchDeletePhoto = false
this.batchDeletePhoto = false //
},
// /
handleCheckAllChange(val) {
// ID
this.selectPhotoIds = val ? this.photoIds : []
this.isIndeterminate = false
this.isIndeterminate = false //
},
//
handleCheckedPhotoChange(value) {
let checkedCount = value.length
const checkedCount = value.length
//
this.checkAll = checkedCount === this.photoIds.length
// 0
this.isIndeterminate = checkedCount > 0 && checkedCount < this.photoIds.length
}
},
// photosID
watch: {
photos() {
this.photoIds = []
@ -163,34 +202,40 @@ export default {
</script>
<style scoped>
/* 操作区域样式 */
.operation {
display: flex;
justify-content: flex-end;
margin-top: 2.25rem;
margin-bottom: 2rem;
}
/* 全选区域样式 */
.all-check {
display: inline-flex;
align-items: center;
margin-right: 1rem;
}
/* 已选数量样式 */
.check-count {
margin-left: 1rem;
font-size: 12px;
}
/* 照片项样式 */
.photo-item {
position: relative;
cursor: pointer;
margin-bottom: 1rem;
}
/* 照片图片样式 */
.photo-img {
width: 100%;
height: 7rem;
border-radius: 4px;
}
/* 照片名称样式 */
.photo-name {
font-size: 14px;
margin-top: 0.3rem;
text-align: center;
}
</style>
</style>

@ -1,103 +1,139 @@
<template>
<el-card class="main-card">
<!-- 页面标题使用当前路由名称 -->
<div class="title">{{ this.$route.name }}</div>
<!-- 相册信息区域 -->
<div class="album-info">
<!-- 相册封面图片 -->
<el-image fit="cover" class="album-cover" :src="albumInfo.albumCover" />
<!-- 相册详情信息 -->
<div class="album-detail">
<div style="margin-bottom: 0.6rem">
<!-- 相册名称 -->
<span class="album-name">{{ albumInfo.albumName }}</span>
<!-- 照片数量 -->
<span class="photo-count">{{ albumInfo.photoCount }}</span>
</div>
<div>
<!-- 相册描述存在时显示 -->
<span v-if="albumInfo.albumDesc" class="album-desc">
{{ albumInfo.albumDesc }}
</span>
<!-- 上传照片按钮点击打开上传弹窗 -->
<el-button icon="el-icon-picture" type="primary" size="small" @click="uploadPhoto = true">
上传照片
</el-button>
</div>
</div>
<!-- 操作区域全选和批量操作按钮 -->
<div class="operation">
<div class="all-check">
<!-- 全选复选框indeterminate表示半选状态 -->
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">
全选
</el-checkbox>
<!-- 显示已选择的照片数量 -->
<div class="check-count">已选择{{ selectphotoIds.length }}</div>
</div>
<!-- 批量移动按钮将选中照片移动到其他相册选择为空时禁用 -->
<el-button
type="success"
@click="movePhoto = true"
:disabled="selectphotoIds.length == 0"
size="small"
icon="el-icon-deleteItem">
type="success"
@click="movePhoto = true"
:disabled="selectphotoIds.length == 0"
size="small"
icon="el-icon-deleteItem">
移动到
</el-button>
<!-- 批量删除按钮将选中照片移至回收站选择为空时禁用 -->
<el-button
type="danger"
@click="batchDeletePhoto = true"
:disabled="selectphotoIds.length == 0"
size="small"
icon="el-icon-deleteItem">
type="danger"
@click="batchDeletePhoto = true"
:disabled="selectphotoIds.length == 0"
size="small"
icon="el-icon-deleteItem">
批量删除
</el-button>
</div>
</div>
<!-- 照片列表容器加载状态时显示loading -->
<el-row class="photo-container" :gutter="10" v-loading="loading">
<!-- 当相册为空时显示空状态 -->
<el-empty v-if="photos.length == 0" description="暂无照片" />
<!-- 复选框组用于选择照片进行批量操作 -->
<el-checkbox-group v-model="selectphotoIds" @change="handleCheckedPhotoChange">
<!-- 遍历照片列表生成照片项 -->
<el-col :md="4" v-for="item of photos" :key="item.id">
<el-checkbox :label="item.id">
<div class="photo-item">
<!-- 照片操作菜单更多按钮 -->
<div class="photo-opreation">
<el-dropdown @command="handleCommand">
<i class="el-icon-more" style="color: #fff" />
<el-dropdown-menu slot="dropdown">
<!-- 编辑照片信息的下拉项 -->
<el-dropdown-item :command="JSON.stringify(item)">
<i class="el-icon-edit" />编辑
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<!-- 照片显示支持预览 -->
<el-image fit="cover" class="photo-img" :src="item.photoSrc" :preview-photoSrc-list="photos" />
<!-- 照片名称 -->
<div class="photo-name">{{ item.photoName }}</div>
</div>
</el-checkbox>
</el-col>
</el-checkbox-group>
</el-row>
<!-- 分页组件 -->
<el-pagination
:hide-on-single-page="true"
class="pagination-container"
@current-change="currentChange"
:current-page="current"
:page-size="size"
:total="count"
layout="prev, pager, next" />
:hide-on-single-page="true"
class="pagination-container"
@current-change="currentChange"
:current-page="current"
:page-size="size"
:total="count"
layout="prev, pager, next" />
<!-- 上传照片弹窗 -->
<el-dialog :visible.sync="uploadPhoto" width="70%" top="10vh">
<div class="dialog-title-container" slot="title">上传照片</div>
<div class="upload-container">
<!-- 已选择文件列表模式当有文件时显示 -->
<el-upload
v-show="uploads.length > 0"
action="/api/admin/photos/upload"
list-type="picture-card"
:file-list="uploads"
multiple
:headers="headers"
:before-upload="beforeUpload"
:on-success="upload"
:on-remove="handleRemove">
<i class="el-icon-plus" />
</el-upload>
<div class="upload">
<el-upload
v-show="uploads.length == 0"
drag
v-show="uploads.length > 0"
action="/api/admin/photos/upload"
list-type="picture-card"
:file-list="uploads"
multiple
:headers="headers"
:before-upload="beforeUpload"
:on-success="upload"
:show-file-list="false">
:on-remove="handleRemove">
<i class="el-icon-plus" />
</el-upload>
<!-- 拖拽上传模式当无文件时显示 -->
<div class="upload">
<el-upload
v-show="uploads.length == 0"
drag
action="/api/admin/photos/upload"
multiple
:headers="headers"
:before-upload="beforeUpload"
:on-success="upload"
:show-file-list="false">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">支持上传jpg/png文件</div>
@ -106,6 +142,7 @@
</div>
<div slot="footer">
<div class="upload-footer">
<!-- 显示已上传的照片数量 -->
<div class="upload-count">共上传{{ uploads.length }}张照片</div>
<div style="margin-left: auto">
<el-button @click="uploadPhoto = false"> </el-button>
@ -114,6 +151,8 @@
</div>
</div>
</el-dialog>
<!-- 编辑照片信息弹窗 -->
<el-dialog :visible.sync="editPhoto" width="30%">
<div class="dialog-title-container" slot="title">修改信息</div>
<el-form label-width="80px" size="medium" :model="photoForm">
@ -129,6 +168,8 @@
<el-button type="primary" @click="updatePhoto"> </el-button>
</div>
</el-dialog>
<!-- 批量删除确认弹窗 -->
<el-dialog :visible.sync="batchDeletePhoto" width="30%">
<div class="dialog-title-container" slot="title"><i class="el-icon-warning" style="color: #ff9900" />提示</div>
<div style="font-size: 1rem">是否删除选中照片</div>
@ -137,13 +178,19 @@
<el-button type="primary" @click="updatePhotoDelete(null)"> </el-button>
</div>
</el-dialog>
<!-- 移动照片弹窗选择目标相册 -->
<el-dialog :visible.sync="movePhoto" width="30%">
<div class="dialog-title-container" slot="title">移动照片</div>
<!-- 当没有其他相册时显示空状态 -->
<el-empty v-if="albumList.length < 2" description="暂无其他相册" />
<!-- 相册选择表单当存在其他相册时显示 -->
<el-form v-else label-width="80px" size="medium" :model="photoForm">
<el-radio-group v-model="albumId">
<div class="album-check-item">
<template v-for="item of albumList">
<!-- 排除当前相册只显示其他相册选项 -->
<el-radio v-if="item.id != albumInfo.id" :key="item.id" :label="item.id" style="margin-bottom: 1rem">
<div class="album-check">
<el-image fit="cover" class="album-check-cover" :src="item.albumCover" />
@ -163,163 +210,186 @@
</template>
<script>
//
import * as imageConversion from 'image-conversion'
export default {
//
created() {
// ID
this.albumId = this.$route.params.albumId
//
if (this.albumId == this.$store.state.pageState.photo.albumId) {
this.current = this.$store.state.pageState.photo.current
} else {
this.current = 1
//
this.$store.commit('updatePhotoPageState', {
albumId: this.$route.params.albumId,
current: this.current
})
}
//
this.getAlbumInfo()
this.listAlbums()
this.listPhotos()
},
data: function () {
return {
loading: true,
checkAll: false,
isIndeterminate: false,
uploadPhoto: false,
editPhoto: false,
movePhoto: false,
batchDeletePhoto: false,
uploads: [],
photos: [],
photoIds: [],
selectphotoIds: [],
albumList: [],
albumInfo: {
loading: true, //
checkAll: false, //
isIndeterminate: false, //
uploadPhoto: false, //
editPhoto: false, //
movePhoto: false, //
batchDeletePhoto: false, //
uploads: [], //
photos: [], //
photoIds: [], // ID
selectphotoIds: [], // ID
albumList: [], //
albumInfo: { //
id: null,
albumName: '',
albumDesc: '',
albumCover: '',
photoCount: 0
},
photoForm: {
photoForm: { //
id: null,
photoName: '',
photoDesc: ''
},
albumId: null,
current: 1,
size: 18,
count: 0,
headers: { Authorization: 'Bearer ' + sessionStorage.getItem('token') }
albumId: null, // ID
current: 1, //
size: 18, //
count: 0, //
headers: { Authorization: 'Bearer ' + sessionStorage.getItem('token') } //
}
},
methods: {
//
getAlbumInfo() {
this.axios.get('/api/admin/photos/albums/' + this.$route.params.albumId + '/info').then(({ data }) => {
this.albumInfo = data.data
})
},
//
listAlbums() {
this.axios.get('/api/admin/photos/albums/info').then(({ data }) => {
this.albumList = data.data
})
},
//
listPhotos() {
this.axios
.get('/api/admin/photos', {
params: {
current: this.current,
size: this.size,
albumId: this.$route.params.albumId,
isDelete: 0
}
})
.then(({ data }) => {
this.photos = data.data.records
this.count = data.data.count
this.loading = false
})
.get('/api/admin/photos', {
params: {
current: this.current, //
size: this.size, //
albumId: this.$route.params.albumId, // ID
isDelete: 0 // 0
}
})
.then(({ data }) => {
this.photos = data.data.records //
this.count = data.data.count //
this.loading = false //
})
},
//
currentChange(current) {
this.current = current
//
this.$store.commit('updatePhotoPageState', {
albumId: this.$route.params.albumId,
current: this.current
})
this.listPhotos()
this.listPhotos() //
},
//
savePhotos() {
var photoUrls = []
// URL
this.uploads.forEach((item) => {
photoUrls.push(item.url)
})
this.axios
.post('/api/admin/photos', {
albumId: this.$route.params.albumId,
photoUrls: photoUrls
})
.then(({ data }) => {
if (data.flag) {
this.$notify.success({
title: '成功',
message: data.message
})
this.uploads = []
this.listPhotos()
this.getAlbumInfo()
} else {
this.$notify.error({
title: '失败',
message: data.message
})
}
})
this.uploadPhoto = false
.post('/api/admin/photos', {
albumId: this.$route.params.albumId, // ID
photoUrls: photoUrls // URL
})
.then(({ data }) => {
if (data.flag) {
//
this.$notify.success({
title: '成功',
message: data.message
})
this.uploads = [] //
this.listPhotos() //
this.getAlbumInfo() //
} else {
//
this.$notify.error({
title: '失败',
message: data.message
})
}
})
this.uploadPhoto = false //
},
//
updatePhoto() {
//
if (this.photoForm.photoName.trim() == '') {
this.$message.error('照片名称不能为空')
return false
}
this.axios.put('/api/admin/photos', this.photoForm).then(({ data }) => {
if (data.flag) {
//
this.$notify.success({
title: '成功',
message: data.message
})
this.listPhotos()
this.listPhotos() //
} else {
//
this.$notify.error({
title: '失败',
message: data.message
})
}
this.editPhoto = false
this.editPhoto = false //
})
},
//
updatePhotoAlbum() {
this.axios
.put('/api/admin/photos/album', {
albumId: this.albumId,
photoIds: this.selectphotoIds
})
.then(({ data }) => {
if (data.flag) {
this.$notify.success({
title: '成功',
message: data.message
})
this.getAlbumInfo()
this.listPhotos()
} else {
this.$notify.error({
title: '失败',
message: data.message
})
}
this.movePhoto = false
})
.put('/api/admin/photos/album', {
albumId: this.albumId, // ID
photoIds: this.selectphotoIds // ID
})
.then(({ data }) => {
if (data.flag) {
//
this.$notify.success({
title: '成功',
message: data.message
})
this.getAlbumInfo() //
this.listPhotos() //
} else {
//
this.$notify.error({
title: '失败',
message: data.message
})
}
this.movePhoto = false //
})
},
//
handleRemove(file) {
this.uploads.forEach((item, index) => {
if (item.url == file.url) {
@ -327,57 +397,75 @@ export default {
}
})
},
//
upload(response) {
this.uploads.push({ url: response.data })
this.uploads.push({ url: response.data }) // URL
},
//
beforeUpload(file) {
return new Promise((resolve) => {
//
if (file.size / 1024 < this.config.UPLOAD_SIZE) {
resolve(file)
} else {
//
imageConversion.compressAccurately(file, this.config.UPLOAD_SIZE).then((res) => {
resolve(res)
})
}
imageConversion.compressAccurately(file, this.config.UPLOAD_SIZE).then((res) => {
resolve(res)
})
})
},
// /
handleCheckAllChange(val) {
// ID
this.selectphotoIds = val ? this.photoIds : []
this.isIndeterminate = false
this.isIndeterminate = false //
},
//
handleCheckedPhotoChange(value) {
let checkedCount = value.length
const checkedCount = value.length
//
this.checkAll = checkedCount === this.photoIds.length
// 0
this.isIndeterminate = checkedCount > 0 && checkedCount < this.photoIds.length
},
//
handleCommand(command) {
//
this.photoForm = JSON.parse(command)
this.editPhoto = true
},
//
updatePhotoDelete(id) {
var param = {}
if (id == null) {
// 使IDisDelete=1
param = { ids: this.selectphotoIds, isDelete: 1 }
} else {
// 使IDisDelete=1
param = { ids: [id], isDelete: 1 }
}
this.axios.put('/api/admin/photos/delete', param).then(({ data }) => {
if (data.flag) {
//
this.$notify.success({
title: '成功',
message: data.message
})
this.listPhotos()
this.getAlbumInfo()
this.listPhotos() //
this.getAlbumInfo() //
} else {
//
this.$notify.error({
title: '失败',
message: data.message
})
}
})
this.batchDeletePhoto = false
this.batchDeletePhoto = false //
}
},
// photosID
watch: {
photos() {
this.photoIds = []
@ -390,86 +478,104 @@ export default {
</script>
<style scoped>
/* 相册信息区域样式 */
.album-info {
display: flex;
margin-top: 2.25rem;
margin-bottom: 2rem;
}
/* 相册封面样式 */
.album-cover {
border-radius: 4px;
width: 5rem;
height: 5rem;
}
/* 相册选择项中的封面样式 */
.album-check-cover {
border-radius: 4px;
width: 4rem;
height: 4rem;
}
/* 相册详情区域样式 */
.album-detail {
padding-top: 0.4rem;
margin-left: 0.8rem;
}
/* 相册描述样式 */
.album-desc {
font-size: 14px;
margin-right: 0.8rem;
}
/* 操作按钮区域样式 */
.operation {
padding-top: 1.5rem;
margin-left: auto;
}
/* 全选区域样式 */
.all-check {
display: inline-flex;
align-items: center;
margin-right: 1rem;
}
/* 已选数量样式 */
.check-count {
margin-left: 1rem;
font-size: 12px;
}
/* 相册名称样式 */
.album-name {
font-size: 1.25rem;
}
/* 照片数量样式 */
.photo-count {
font-size: 12px;
margin-left: 0.5rem;
}
/* 照片项样式 */
.photo-item {
width: 100%;
position: relative;
cursor: pointer;
margin-bottom: 1rem;
}
/* 照片图片样式 */
.photo-img {
width: 100%;
height: 7rem;
border-radius: 4px;
}
/* 照片名称样式 */
.photo-name {
font-size: 14px;
margin-top: 0.3rem;
text-align: center;
}
/* 上传容器样式 */
.upload-container {
height: 400px;
}
/* 拖拽上传区域样式 */
.upload {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
/* 上传弹窗底部样式 */
.upload-footer {
display: flex;
align-items: center;
}
/* 照片操作菜单样式 */
.photo-opreation {
position: absolute;
z-index: 1000;
top: 0.3rem;
right: 0.5rem;
}
/* 相册选择项样式 */
.album-check {
display: flex;
align-items: center;
}
</style>
</style>

@ -1,8 +1,12 @@
<template>
<!-- 文章编辑页面主卡片组件 -->
<el-card class="main-card">
<!-- 页面标题取自路由名称 -->
<div class="title">{{ this.$route.name }}</div>
<div class="article-title-container">
<!-- 文章标题输入区域 -->
<el-input v-model="article.articleTitle" size="medium" placeholder="输入文章标题" />
<!-- 保存草稿按钮仅在文章未保存或状态为草稿时显示 -->
<el-button
type="danger"
size="medium"
@ -11,13 +15,19 @@
v-if="article.id == null || article.status == 3">
保存草稿
</el-button>
<!-- 发布文章按钮点击打开发布配置弹窗 -->
<el-button type="danger" size="medium" @click="openModel" style="margin-left: 10px"> 发布文章 </el-button>
</div>
<!-- Markdown编辑器用于编辑文章内容绑定图片上传事件 -->
<mavon-editor ref="md" v-model="article.articleContent" @imgAdd="uploadImg" style="height: calc(100vh - 260px)" />
<!-- 发布文章配置弹窗 -->
<el-dialog :visible.sync="addOrEdit" width="40%" top="3vh">
<div class="dialog-title-container" slot="title">发布文章</div>
<!-- 发布配置表单 -->
<el-form label-width="80px" size="medium" :model="article">
<el-form-item label="文章分类">
<!-- 已选分类标签可关闭 -->
<el-tag
type="success"
v-show="article.categoryName"
@ -26,6 +36,7 @@
@close="removeCategory">
{{ article.categoryName }}
</el-tag>
<!-- 分类选择弹窗未选择分类时显示 -->
<el-popover placement="bottom-start" width="460" trigger="click" v-if="!article.categoryName">
<div class="popover-title">分类</div>
<el-autocomplete
@ -39,7 +50,9 @@
<template slot-scope="{ item }">
<div>{{ item.categoryName }}</div>
</template>
<!-- 分类搜索框支持回车添加自定义分类 -->
</el-autocomplete>
<!-- 分类列表点击选择分类 -->
<div class="popover-container">
<div v-for="item of categorys" :key="item.id" class="category-item" @click="addCategory(item)">
{{ item.categoryName }}
@ -48,7 +61,9 @@
<el-button type="success" plain slot="reference" size="small"> 添加分类 </el-button>
</el-popover>
</el-form-item>
<!-- 文章标签选择 -->
<el-form-item label="文章标签">
<!-- 已选标签列表可关闭 -->
<el-tag
v-for="(item, index) of article.tagNames"
:key="index"
@ -57,8 +72,10 @@
@close="removeTag(item)">
{{ item }}
</el-tag>
<!-- 标签选择弹窗标签数量小于3时显示 -->
<el-popover placement="bottom-start" width="460" trigger="click" v-if="article.tagNames.length < 3">
<div class="popover-title">标签</div>
<!-- 标签搜索框支持回车添加自定义标签 -->
<el-autocomplete
style="width: 100%"
v-model="tagName"
@ -71,6 +88,7 @@
<div>{{ item.tagName }}</div>
</template>
</el-autocomplete>
<!-- 标签列表点击选择标签 -->
<div class="popover-container">
<div style="margin-bottom: 1rem">添加标签</div>
<el-tag v-for="(item, index) of tagList" :key="index" :class="tagClass(item)" @click="addTag(item)">
@ -80,14 +98,17 @@
<el-button type="primary" plain slot="reference" size="small"> 添加标签 </el-button>
</el-popover>
</el-form-item>
<!-- 文章类型选择 -->
<el-form-item label="文章类型">
<el-select v-model="article.type" placeholder="请选择类型">
<el-option v-for="item in typeList" :key="item.type" :label="item.desc" :value="item.type" />
</el-select>
</el-form-item>
<!-- 原文地址非原创类型时显示 -->
<el-form-item label="原文地址" v-if="article.type != 1">
<el-input v-model="article.originalUrl" placeholder="请填写原文链接" />
</el-form-item>
<!-- 封面上传 -->
<el-form-item label="上传封面">
<el-upload
class="upload-cover"
@ -102,6 +123,7 @@
<img v-else :src="article.articleCover" width="360px" height="180px" />
</el-upload>
</el-form-item>
<!-- 置顶设置 -->
<el-form-item label="置顶">
<el-switch
v-model="article.isTop"
@ -110,6 +132,7 @@
:active-value="1"
:inactive-value="0" />
</el-form-item>
<!-- 推荐设置 -->
<el-form-item label="推荐">
<el-switch
v-model="article.isFeatured"
@ -118,19 +141,23 @@
:active-value="1"
:inactive-value="0" />
</el-form-item>
<!-- 发布形式选择 -->
<el-form-item label="发布形式">
<el-radio-group v-model="article.status">
<el-radio :label="1">公开</el-radio>
<el-radio :label="2">密码</el-radio>
</el-radio-group>
</el-form-item>
<!-- 访问密码密码形式发布时显示 -->
<el-form-item label="访问密码" v-if="article.status == 2">
<el-input v-model="article.password" placeholder="请填写文章访问密码" />
</el-form-item>
<!-- 文章摘要 -->
<el-form-item label="文章摘要">
<el-input type="textarea" autosize="true" v-model="article.articleAbstract" placeholder="默认取文章前500个字符" />
</el-form-item>
</el-form>
<!-- 弹窗底部按钮 -->
<div slot="footer">
<el-button @click="addOrEdit = false"> </el-button>
<el-button type="danger" @click="saveOrUpdateArticle"> </el-button>
@ -140,34 +167,42 @@
</template>
<script>
//
import * as imageConversion from 'image-conversion'
export default {
//
created() {
// ID
const path = this.$route.path
const arr = path.split('/')
const articleId = arr[2]
// ID
if (articleId) {
this.axios.get('/api/admin/articles/' + articleId).then(({ data }) => {
this.article = data.data
})
} else {
// 稿
const article = sessionStorage.getItem('article')
if (article) {
this.article = JSON.parse(article)
}
}
},
// 稿
destroyed() {
this.autoSaveArticle()
},
//
data: function () {
return {
addOrEdit: false,
autoSave: true,
categoryName: '',
tagName: '',
categorys: [],
tagList: [],
addOrEdit: false,//
autoSave: true,//
categoryName: '',//
tagName: '',//
categorys: [],//
tagList: [],//
//
typeList: [
{
type: 1,
@ -182,50 +217,63 @@ export default {
desc: '翻译'
}
],
//
article: {
id: null,
articleTitle: this.$moment(new Date()).format('YYYY-MM-DD'),
articleContent: '',
articleAbstract: '',
articleCover: '',
categoryName: null,
tagNames: [],
isTop: 0,
type: 1,
status: 1
articleContent: '',//
articleAbstract: '', //
articleCover: '', //
categoryName: null,//
tagNames: [], //
isTop: 0,// 0-1-
type: 1,// 1-2-3-
status: 1// 1-2-3-稿
},
// token
headers: { Authorization: 'Bearer ' + sessionStorage.getItem('token') }
}
},
//
methods: {
//
listCategories() {
this.axios.get('/api/admin/categories/search').then(({ data }) => {
this.categorys = data.data
})
},
//
listTags() {
this.axios.get('/api/admin/tags/search').then(({ data }) => {
this.tagList = data.data
})
},
//
openModel() {
//
if (this.article.articleTitle.trim() == '') {
this.$message.error('文章标题不能为空')
return false
}
//
if (this.article.articleContent.trim() == '') {
this.$message.error('文章内容不能为空')
return false
}
//
this.listCategories()
this.listTags()
//
this.addOrEdit = true
},
//
uploadCover(response) {
this.article.articleCover = response.data
},
//
beforeUpload(file) {
return new Promise((resolve) => {
//
if (file.size / 1024 < this.config.UPLOAD_SIZE) {
resolve(file)
}
@ -234,11 +282,14 @@ export default {
})
})
},
// Markdown
uploadImg(pos, file) {
var formdata = new FormData()
//
if (file.size / 1024 < this.config.UPLOAD_SIZE) {
formdata.append('file', file)
this.axios.post('/api/admin/articles/images', formdata).then(({ data }) => {
// URL
this.$refs.md.$img2Url(pos, data.data)
})
} else {
@ -250,18 +301,24 @@ export default {
})
}
},
// 稿
saveArticleDraft() {
//
if (this.article.articleTitle.trim() == '') {
this.$message.error('文章标题不能为空')
return false
}
//
if (this.article.articleContent.trim() == '') {
this.$message.error('文章内容不能为空')
return false
}
// 稿
this.article.status = 3
//
this.axios.post('/api/admin/articles', this.article).then(({ data }) => {
if (data.flag) {
//
if (this.article.id === null) {
this.$store.commit('removeTab', '发布文章')
} else {

Loading…
Cancel
Save