完善日志图片功能

pull/25/head
guqing 2019-06-13 14:34:50 +08:00
parent 9859fcfd74
commit 5547b3b8d9
3 changed files with 301 additions and 247 deletions

View File

@ -2,19 +2,19 @@
<div class="clearfix"> <div class="clearfix">
<a-upload <a-upload
:name="name" :name="name"
:customRequest="handleUpload" :customRequest="handleUpload"
listType="picture-card" listType="picture-card"
:fileList="fileList" :fileList="fileList"
@preview="handlePreview" @preview="handlePreview"
@change="handleChange" @change="handleChange"
> >
<div v-if="fileList.length < 9" id="plus-photo-uploadbox"> <div v-if="fileList.length < 9 && plusPhotoVisible" id="plus-photo-uploadbox">
<a-icon type="plus" /> <a-icon type="plus"/>
<div class="ant-upload-text">Upload</div> <div class="ant-upload-text">Upload</div>
</div> </div>
</a-upload> </a-upload>
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel"> <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
<img alt="example" style="width: 100%" :src="previewImage" /> <img alt="example" style="width: 100%" :src="previewImage">
</a-modal> </a-modal>
</div> </div>
</template> </template>
@ -22,79 +22,118 @@
import axios from 'axios' import axios from 'axios'
import attachmentApi from '@/api/attachment' import attachmentApi from '@/api/attachment'
export default { export default {
data () { props: {
photoList: {
type: Array,
required: false,
default: function() {
return []
}
},
plusPhotoVisible: {
type: Boolean,
required: false,
default: true
}
},
data() {
return { return {
name: 'file', name: 'file',
previewVisible: false, previewVisible: false,
previewImage: '', previewImage: '',
fileList: [], fileList: [],
uploadHandler: attachmentApi.upload uploadHandler: attachmentApi.upload
}
},
created() {
// watch
this.handlerEditPreviewPhoto(this.photoList)
},
watch: {
photoList(newValue, oldValue) {
this.handlerEditPreviewPhoto(newValue)
} }
}, },
methods: { methods: {
handleCancel () { handlerEditPreviewPhoto(data) {
//
this.fileList = []
//
if (data !== null && data !== undefined) {
for (var i = 0; i < data.length; i++) {
//
this.fileList.push({
uid: data[i].id,
name: data[i].name,
status: 'done',
url: data[i].thumbnail
})
}
}
},
handleCancel() {
this.previewVisible = false this.previewVisible = false
}, },
handlePreview (file) { handlePreview(file) {
this.previewImage = file.url || file.thumbUrl this.previewImage = file.url || file.thumbUrl
this.previewVisible = true this.previewVisible = true
}, },
handleChange ({ fileList }) { handleChange({ fileList }) {
this.fileList = fileList this.fileList = fileList
}, },
handleUpload(option) { handleUpload(option) {
this.$log.debug('Uploading option', option) this.$log.debug('Uploading option', option)
const CancelToken = axios.CancelToken const CancelToken = axios.CancelToken
const source = CancelToken.source() const source = CancelToken.source()
const data = new FormData() const data = new FormData()
data.append(this.name, option.file) data.append(this.name, option.file)
this.uploadHandler( this.uploadHandler(
data, data,
progressEvent => { progressEvent => {
if (progressEvent.total > 0) { if (progressEvent.total > 0) {
progressEvent.percent = (progressEvent.loaded / progressEvent.total) * 100 progressEvent.percent = (progressEvent.loaded / progressEvent.total) * 100
} }
this.$log.debug('Uploading percent: ', progressEvent.percent) this.$log.debug('Uploading percent: ', progressEvent.percent)
option.onProgress(progressEvent) option.onProgress(progressEvent)
}, },
source.token, source.token,
option.file option.file
) )
.then(response => { .then(response => {
this.$log.debug('Uploaded successfully', response) this.$log.debug('Uploaded successfully', response)
option.onSuccess(response, option.file) option.onSuccess(response, option.file)
this.$emit('success', response, option.file) this.$emit('success', response, option.file)
}) })
.catch(error => { .catch(error => {
this.$log.debug('Failed to upload file', error) this.$log.debug('Failed to upload file', error)
option.onError(error, error.response) option.onError(error, error.response)
this.$emit('failure', error, option.file) this.$emit('failure', error, option.file)
}) })
return { return {
abort: () => { abort: () => {
this.$log.debug('Upload operation aborted by the user') this.$log.debug('Upload operation aborted by the user')
source.cancel('Upload operation canceled by the user.') source.cancel('Upload operation canceled by the user.')
} }
} }
} }
}, }
} }
</script> </script>
<style> <style>
/* you can make up upload button and sample style by using stylesheets */ /* you can make up upload button and sample style by using stylesheets */
.ant-upload-select-picture-card i { .ant-upload-select-picture-card i {
font-size: 32px; font-size: 32px;
color: #999; color: #999;
} }
.ant-upload-select-picture-card .ant-upload-text { .ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px; margin-top: 8px;
color: #666; color: #666;
} }
.ant-upload-list-picture-card { .ant-upload-list-picture-card {
/* 将浮动恢复为默认值,避免出现纵向换行情况 */ /* 将浮动恢复为默认值,避免出现纵向换行情况 */
float: initial; float: initial;
} }
</style> </style>

View File

@ -199,27 +199,27 @@
v-model="journal.content" v-model="journal.content"
placeholder="写点什么吧..." placeholder="写点什么吧..."
/> />
</a-form-item> </a-form-item>
<!-- 日志图片上传 --> <!-- 日志图片上传 -->
<a-form-item v-show="showMoreOptions"> <a-form-item v-show="showMoreOptions">
<UploadPhoto></UploadPhoto> <UploadPhoto
<!-- <a-collapse :bordered="false"> @success="handlerPhotoUploadSuccess"
<a-collapse-panel key="1"> :photoList="photoList"
></UploadPhoto>
</a-collapse-panel> </a-form-item>
</a-collapse> -->
</a-form-item> <a-form-item>
<a-button
<a-form-item> type="primary"
<a-button @click="handleCreateJournalClick"
type="primary" >保存</a-button>
@click="handleCreateJournalClick" <a
>保存</a-button> href="javascript:;"
<a href="javascript:;" class="more-options-btn" class="more-options-btn"
type="default" type="default"
@click="handleUploadPhotoWallClick" @click="handleUploadPhotoWallClick"
>更多选项<a-icon type="down" /></a> >更多选项<a-icon type="down" /></a>
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-card> </a-card>
@ -332,7 +332,7 @@ import postApi from '@/api/post'
import logApi from '@/api/log' import logApi from '@/api/log'
import adminApi from '@/api/admin' import adminApi from '@/api/admin'
import journalApi from '@/api/journal' import journalApi from '@/api/journal'
import countTo from 'vue-count-to' import countTo from 'vue-count-to'
import UploadPhoto from '../../components/Upload/UploadPhoto.vue' import UploadPhoto from '../../components/Upload/UploadPhoto.vue'
export default { export default {
name: 'Dashboard', name: 'Dashboard',
@ -341,12 +341,13 @@ export default {
PageView, PageView,
AnalysisCard, AnalysisCard,
RecentCommentTab, RecentCommentTab,
countTo, countTo,
UploadPhoto UploadPhoto
}, },
data() { data() {
return { return {
showMoreOptions: false, photoList: [],
showMoreOptions: false,
startVal: 0, startVal: 0,
logType: logApi.logType, logType: logApi.logType,
activityLoading: true, activityLoading: true,
@ -357,7 +358,11 @@ export default {
postData: [], postData: [],
logData: [], logData: [],
countsData: {}, countsData: {},
journal: {}, journal: {
content: '',
photos: []
},
journalPhotos: [], //
logs: [], logs: [],
options: [], options: [],
keys: ['blog_url'], keys: ['blog_url'],
@ -415,7 +420,19 @@ export default {
} }
next() next()
}, },
methods: { methods: {
handlerPhotoUploadSuccess(response, file) {
var callData = response.data.data
var photo = {
name: callData.name,
url: callData.path,
thumbnail: callData.thumbPath,
suffix: callData.suffix,
width: callData.width,
height: callData.height
}
this.journalPhotos.push(photo)
},
loadOptions() { loadOptions() {
optionApi.listAll(this.keys).then(response => { optionApi.listAll(this.keys).then(response => {
this.options = response.data.data this.options = response.data.data
@ -444,15 +461,20 @@ export default {
this.$router.push({ name: 'PostEdit', query: { postId: post.id } }) this.$router.push({ name: 'PostEdit', query: { postId: post.id } })
}, },
handleCreateJournalClick() { handleCreateJournalClick() {
//
this.journal.photos = this.journalPhotos
journalApi.create(this.journal).then(response => { journalApi.create(this.journal).then(response => {
this.$message.success('发表成功!') this.$message.success('发表成功!')
this.journal = {} this.journal = {}
this.photoList = []
this.showMoreOptions = false
}) })
}, },
handleUploadPhotoWallClick(){ handleUploadPhotoWallClick() {
// //
this.showMoreOptions = !this.showMoreOptions this.showMoreOptions = !this.showMoreOptions
}, },
handleShowLogDrawer() { handleShowLogDrawer() {
this.logDrawerVisiable = true this.logDrawerVisiable = true
this.loadLogs() this.loadLogs()
@ -479,12 +501,11 @@ export default {
} }
} }
} }
</script> </script>
<style scoped="scoped"> <style scoped="scoped">
.more-options-btn{ .more-options-btn{
margin-left: 15px; margin-left: 15px;
text-decoration: none; text-decoration: none;
} }
</style> </style>

View File

@ -6,18 +6,12 @@
<div class="table-page-search-wrapper"> <div class="table-page-search-wrapper">
<a-form layout="inline"> <a-form layout="inline">
<a-row :gutter="48"> <a-row :gutter="48">
<a-col <a-col :md="6" :sm="24">
:md="6"
:sm="24"
>
<a-form-item label="关键词"> <a-form-item label="关键词">
<a-input v-model="queryParam.keyword" /> <a-input v-model="queryParam.keyword"/>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col <a-col :md="6" :sm="24">
:md="6"
:sm="24"
>
<a-form-item label="状态"> <a-form-item label="状态">
<a-select placeholder="请选择状态"> <a-select placeholder="请选择状态">
<a-select-option value="1">公开</a-select-option> <a-select-option value="1">公开</a-select-option>
@ -25,32 +19,19 @@
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col <a-col :md="6" :sm="24">
:md="6"
:sm="24"
>
<span class="table-page-search-submitButtons"> <span class="table-page-search-submitButtons">
<a-button <a-button type="primary" @click="loadJournals(true)"></a-button>
type="primary" <a-button style="margin-left: 8px;" @click="resetParam"></a-button>
@click="loadJournals(true)"
>查询</a-button>
<a-button
style="margin-left: 8px;"
@click="resetParam"
>重置</a-button>
</span> </span>
</a-col> </a-col>
</a-row> </a-row>
</a-form> </a-form>
</div> </div>
<div class="table-operator"> <div class="table-operator">
<a-button <a-button type="primary" icon="plus" @click="handleNew"></a-button>
type="primary"
icon="plus"
@click="handleNew"
>写日志</a-button>
</div> </div>
<a-divider /> <a-divider/>
<div style="margin-top:15px"> <div style="margin-top:15px">
<a-list <a-list
itemLayout="vertical" itemLayout="vertical"
@ -58,42 +39,46 @@
:dataSource="journals" :dataSource="journals"
:loading="listLoading" :loading="listLoading"
> >
<a-list-item <a-list-item slot="renderItem" slot-scope="item, index" :key="index">
slot="renderItem" <!-- 日志图片集合 -->
slot-scope="item, index" <a-card
:key="index" hoverable
> v-for="(photo, photoIndex) in item.photos"
:key="photoIndex"
class="photo-card"
@click="handlerPhotoPreview(photo)"
>
<img alt="example" :src="photo.thumbnail" slot="cover">
</a-card>
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancelPreview">
<img
:alt="previewPhoto.name + previewPhoto.description"
style="width: 100%"
:src="previewPhoto.url"
>
</a-modal>
<template slot="actions"> <template slot="actions">
<span> <span>
<a href="javascript:void(0);"> <a href="javascript:void(0);">
<a-icon <a-icon type="like-o" style="margin-right: 8px"/>
type="like-o" {{ item.likes }}
style="margin-right: 8px"
/>{{ item.likes }}
</a> </a>
</span> </span>
<span> <span>
<a <a href="javascript:void(0);" @click="handleCommentShow(item)">
href="javascript:void(0);" <a-icon type="message" style="margin-right: 8px"/>
@click="handleCommentShow(item)" {{ item.commentCount }}
>
<a-icon
type="message"
style="margin-right: 8px"
/>{{ item.commentCount }}
</a> </a>
</span> </span>
<!-- <span> <!-- <span>
From 微信 From 微信
</span> --> </span>-->
</template> </template>
<template slot="extra"> <template slot="extra">
<a <a href="javascript:void(0);" @click="handleEdit(item)"></a>
href="javascript:void(0);" <a-divider type="vertical"/>
@click="handleEdit(item)"
>编辑</a>
<a-divider type="vertical" />
<a-popconfirm <a-popconfirm
title="你确定要删除这条日志?" title="你确定要删除这条日志?"
@confirm="handleDelete(item.id)" @confirm="handleDelete(item.id)"
@ -103,13 +88,10 @@
<a href="javascript:void(0);">删除</a> <a href="javascript:void(0);">删除</a>
</a-popconfirm> </a-popconfirm>
</template> </template>
<a-list-item-meta :description="item.content"> <a-list-item-meta :description="item.content">
<span slot="title">{{ item.createTime | moment }}</span> <span slot="title">{{ item.createTime | moment }}</span>
<a-avatar <a-avatar slot="avatar" size="large" :src="user.avatar"/>
slot="avatar"
size="large"
:src="user.avatar"
/>
</a-list-item-meta> </a-list-item-meta>
</a-list-item> </a-list-item>
<div class="page-wrapper"> <div class="page-wrapper">
@ -132,39 +114,36 @@
<!-- 编辑日志弹窗 --> <!-- 编辑日志弹窗 -->
<a-modal v-model="visible"> <a-modal v-model="visible">
<template slot="title"> <template slot="title">
{{ title }} <a-tooltip {{ title }}
slot="action" <a-tooltip slot="action" title="只能输入250字">
title="只能输入250字" <a-icon type="info-circle-o"/>
>
<a-icon type="info-circle-o" />
</a-tooltip> </a-tooltip>
</template> </template>
<template slot="footer"> <template slot="footer">
<a-button <a-button key="submit" type="primary" @click="createOrUpdateJournal"></a-button>
key="submit" </template>
type="primary"
@click="createOrUpdateJournal"
>
发布
</a-button>
</template>
<a-form layout="vertical"> <a-form layout="vertical">
<a-form-item> <a-form-item>
<a-input <a-input type="textarea" :autosize="{ minRows: 8 }" v-model="journal.content"/>
type="textarea" </a-form-item>
:autosize="{ minRows: 8 }" <a-form-item v-show="showMoreOptions">
v-model="journal.content" <UploadPhoto
/> @success="handlerPhotoUploadSuccess"
</a-form-item> :photoList="photoList"
<a-form-item v-show="showMoreOptions"> :plusPhotoVisible="plusPhotoVisible"
<UploadPhoto @success="handlerPhotoUploadSuccess"></UploadPhoto> ></UploadPhoto>
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<a href="javascript:;" class="more-options-btn" <a
type="default" href="javascript:;"
@click="handleUploadPhotoWallClick" class="more-options-btn"
>更多选项<a-icon type="down" /></a> type="default"
</a-form-item> @click="handleUploadPhotoWallClick"
>
更多选项
<a-icon type="down"/>
</a>
</a-form-item>
</a-form> </a-form>
</a-modal> </a-modal>
@ -175,21 +154,11 @@
v-model="selectCommentVisible" v-model="selectCommentVisible"
> >
<template slot="footer"> <template slot="footer">
<a-button <a-button key="submit" type="primary" @click="handleReplyComment"></a-button>
key="submit"
type="primary"
@click="handleReplyComment"
>
回复
</a-button>
</template> </template>
<a-form layout="vertical"> <a-form layout="vertical">
<a-form-item> <a-form-item>
<a-input <a-input type="textarea" :autosize="{ minRows: 8 }" v-model="replyComment.content"/>
type="textarea"
:autosize="{ minRows: 8 }"
v-model="replyComment.content"
/>
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-modal> </a-modal>
@ -203,23 +172,16 @@
destroyOnClose destroyOnClose
@close="()=>this.commentVisiable = false" @close="()=>this.commentVisiable = false"
> >
<a-row <a-row type="flex" align="middle">
type="flex"
align="middle"
>
<a-col :span="24"> <a-col :span="24">
<a-comment> <a-comment>
<a-avatar <a-avatar :src="user.avatar" :alt="user.nickname" slot="avatar"/>
:src="user.avatar"
:alt="user.nickname"
slot="avatar"
/>
<p slot="content">{{ journal.content }}</p> <p slot="content">{{ journal.content }}</p>
<span slot="datetime">{{ journal.createTime | moment }}</span> <span slot="datetime">{{ journal.createTime | moment }}</span>
</a-comment> </a-comment>
</a-col> </a-col>
<a-divider /> <a-divider/>
<a-col :span="24"> <a-col :span="24">
<journal-comment-tree <journal-comment-tree
v-for="(comment,index) in comments" v-for="(comment,index) in comments"
@ -245,8 +207,17 @@ export default {
mixins: [mixin, mixinDevice], mixins: [mixin, mixinDevice],
components: { JournalCommentTree, UploadPhoto }, components: { JournalCommentTree, UploadPhoto },
data() { data() {
return { return {
showMoreOptions: false, plusPhotoVisible: true,
photoList: [], //
previewVisible: false,
showMoreOptions: false,
previewPhoto: {
//
name: '',
description: '',
url: ''
},
title: '发表', title: '发表',
listLoading: false, listLoading: false,
visible: false, visible: false,
@ -265,38 +236,46 @@ export default {
}, },
journals: [], journals: [],
comments: [], comments: [],
journal: { journal: {
id: null, id: undefined,
content: '', content: '',
photos: [] photos: []
}, },
journalPhotos: [], journalPhotos: [], //
selectComment: null, selectComment: null,
replyComment: {}, replyComment: {},
user: {}, user: {}
} }
}, },
created() { created() {
this.loadJournals() this.loadJournals()
this.loadUser() this.loadUser()
}, },
methods: { methods: {
handlerPhotoUploadSuccess(response, file){ handleCancelPreview() {
var callData = response.data.data this.previewVisible = false
var photo = { },
name: callData.name, handlerPhotoPreview(photo) {
url: callData.path, //
thumbnail: callData.thumbPath, this.previewVisible = true
suffix: callData.suffix, this.previewPhoto = photo
width: callData.width, },
height: callData.height handlerPhotoUploadSuccess(response, file) {
} var callData = response.data.data
this.journalPhotos.push(photo) var photo = {
}, name: callData.name,
handleUploadPhotoWallClick(){ url: callData.path,
// thumbnail: callData.thumbPath,
this.showMoreOptions = !this.showMoreOptions suffix: callData.suffix,
}, width: callData.width,
height: callData.height
}
this.journalPhotos.push(photo)
},
handleUploadPhotoWallClick() {
//
this.showMoreOptions = !this.showMoreOptions
},
loadJournals(isSearch) { loadJournals(isSearch) {
this.queryParam.page = this.pagination.page - 1 this.queryParam.page = this.pagination.page - 1
this.queryParam.size = this.pagination.size this.queryParam.size = this.pagination.size
@ -320,11 +299,19 @@ export default {
this.title = '新建' this.title = '新建'
this.visible = true this.visible = true
this.journal = {} this.journal = {}
//
this.plusPhotoVisible = true
this.photoList = []
}, },
handleEdit(item) { handleEdit(item) {
this.title = '编辑' this.title = '编辑'
this.journal = item this.journal = item
this.visible = true this.visible = true
// ,
this.plusPhotoVisible = false
this.photoList = item.photos
}, },
handleDelete(id) { handleDelete(id) {
journalApi.delete(id).then(response => { journalApi.delete(id).then(response => {
@ -360,10 +347,10 @@ export default {
this.handleCommentShow(this.journal) this.handleCommentShow(this.journal)
}) })
}, },
createOrUpdateJournal() { createOrUpdateJournal() {
// //
this.journal.photos = this.journalPhotos this.journal.photos = this.journalPhotos
if (this.journal.id) { if (this.journal.id) {
journalApi.update(this.journal.id, this.journal).then(response => { journalApi.update(this.journal.id, this.journal).then(response => {
this.$message.success('更新成功!') this.$message.success('更新成功!')
@ -373,6 +360,7 @@ export default {
journalApi.create(this.journal).then(response => { journalApi.create(this.journal).then(response => {
this.$message.success('发表成功!') this.$message.success('发表成功!')
this.loadJournals() this.loadJournals()
this.photoList = []
}) })
} }
this.visible = false this.visible = false
@ -389,11 +377,17 @@ export default {
} }
} }
} }
</script> </script>
<style scoped="scoped"> <style scoped="scoped">
.more-options-btn{ .more-options-btn {
margin-left: 15px; margin-left: 15px;
text-decoration: none; text-decoration: none;
} }
/* 日志图片卡片样式 */
.photo-card {
width: 104px;
display: inline-block;
margin-right: 5px;
}
</style> </style>