Refactor recent comment list.

pull/3445/head
ruibaby 2019-05-14 22:58:38 +08:00
parent 5aeec9832a
commit f2490e5384
6 changed files with 368 additions and 329 deletions

View File

@ -11,95 +11,97 @@
> >
<template slot="content"> <template slot="content">
<a-spin :spinning="loadding"> <a-spin :spinning="loadding">
<a-tabs> <div class="custom-tab-wrapper">
<a-tab-pane <a-tabs>
tab="文章" <a-tab-pane
key="1" tab="文章"
> key="1"
<a-list :dataSource="converttedPostComments"> >
<a-list-item <a-list :dataSource="converttedPostComments">
slot="renderItem" <a-list-item
slot-scope="item" slot="renderItem"
> slot-scope="item"
<a-list-item-meta> >
<a-avatar <a-list-item-meta>
style="background-color: white" <a-avatar
slot="avatar" style="background-color: white"
:src="'https://gravatar.loli.net/avatar/' + item.gavatarMd5 + '&d=mm'" slot="avatar"
size="large" :src="'https://gravatar.loli.net/avatar/' + item.gavatarMd5 + '&d=mm'"
/> size="large"
<template slot="title"> />
<a <template slot="title">
:href="item.authorUrl" <a
target="_blank" :href="item.authorUrl"
>{{ item.author }}</a><span v-html="item.content"></span> target="_blank"
</template> >{{ item.author }}</a><span v-html="item.content"></span>
<template slot="description"> </template>
{{ item.createTime | timeAgo }} <template slot="description">
</template> {{ item.createTime | timeAgo }}
</a-list-item-meta> </template>
</a-list-item> </a-list-item-meta>
</a-list> </a-list-item>
</a-tab-pane> </a-list>
<a-tab-pane </a-tab-pane>
tab="页面" <a-tab-pane
key="2" tab="页面"
> key="2"
<a-list :dataSource="converttedSheetComments"> >
<a-list-item <a-list :dataSource="converttedSheetComments">
slot="renderItem" <a-list-item
slot-scope="item" slot="renderItem"
> slot-scope="item"
<a-list-item-meta> >
<a-avatar <a-list-item-meta>
style="background-color: white" <a-avatar
slot="avatar" style="background-color: white"
:src="'https://gravatar.loli.net/avatar/' + item.gavatarMd5 + '&d=mm'" slot="avatar"
size="large" :src="'https://gravatar.loli.net/avatar/' + item.gavatarMd5 + '&d=mm'"
/> size="large"
<template slot="title"> />
<a <template slot="title">
:href="item.authorUrl" <a
target="_blank" :href="item.authorUrl"
>{{ item.author }}</a><span v-html="item.content"></span> target="_blank"
</template> >{{ item.author }}</a><span v-html="item.content"></span>
<template slot="description"> </template>
{{ item.createTime | timeAgo }} <template slot="description">
</template> {{ item.createTime | timeAgo }}
</a-list-item-meta> </template>
</a-list-item> </a-list-item-meta>
</a-list> </a-list-item>
</a-tab-pane> </a-list>
<a-tab-pane </a-tab-pane>
tab="日志" <a-tab-pane
key="3" tab="日志"
> key="3"
<a-list :dataSource="converttedJournalComments"> >
<a-list-item <a-list :dataSource="converttedJournalComments">
slot="renderItem" <a-list-item
slot-scope="item" slot="renderItem"
> slot-scope="item"
<a-list-item-meta> >
<a-avatar <a-list-item-meta>
style="background-color: white" <a-avatar
slot="avatar" style="background-color: white"
:src="'https://gravatar.loli.net/avatar/' + item.gavatarMd5 + '&d=mm'" slot="avatar"
size="large" :src="'https://gravatar.loli.net/avatar/' + item.gavatarMd5 + '&d=mm'"
/> size="large"
<template slot="title"> />
<a <template slot="title">
:href="item.authorUrl" <a
target="_blank" :href="item.authorUrl"
>{{ item.author }}</a><span v-html="item.content"></span> target="_blank"
</template> >{{ item.author }}</a><span v-html="item.content"></span>
<template slot="description"> </template>
{{ item.createTime | timeAgo }} <template slot="description">
</template> {{ item.createTime | timeAgo }}
</a-list-item-meta> </template>
</a-list-item> </a-list-item-meta>
</a-list> </a-list-item>
</a-tab-pane> </a-list>
</a-tabs> </a-tab-pane>
</a-tabs>
</div>
</a-spin> </a-spin>
</template> </template>
<span <span

View File

@ -634,6 +634,15 @@ body {
background: transparent !important; background: transparent !important;
} }
.custom-tab-wrapper {
.ant-tabs-nav {
.ant-tabs-tab {
margin: 0 24px 0 0;
padding: 12px 0;
}
}
}
.comment-content-wrapper { .comment-content-wrapper {
h1 { h1 {
font-size: 18px; font-size: 18px;

View File

@ -104,14 +104,11 @@
:bodyStyle="{ padding: 0 }" :bodyStyle="{ padding: 0 }"
> >
<div class="card-container"> <div class="card-container">
<a-tabs <a-tabs type="card">
defaultActiveKey="1" <a-tab-pane
type="card" key="1"
> tab="最近文章"
<a-tab-pane key="1"> >
<span slot="tab">
最近文章
</span>
<a-list :dataSource="postData"> <a-list :dataSource="postData">
<a-list-item <a-list-item
slot="renderItem" slot="renderItem"
@ -131,40 +128,30 @@
</a-tab-pane> </a-tab-pane>
<a-tab-pane <a-tab-pane
key="2" key="2"
forceRender tab="最近评论"
> >
<span slot="tab"> <div class="custom-tab-wrapper">
最近评论 <a-tabs>
</span> <a-tab-pane
<a-list tab="文章"
itemLayout="horizontal" key="1"
:dataSource="formmatedCommentData" >
> <recent-comment-tab type="post"></recent-comment-tab>
<a-list-item </a-tab-pane>
slot="renderItem" <a-tab-pane
slot-scope="item, index" tab="页面"
:key="index" key="2"
> >
<a-comment :avatar="'//gravatar.loli.net/avatar/'+item.gavatarMd5+'/?s=256&d=mp'"> <recent-comment-tab type="sheet"></recent-comment-tab>
<template slot="author"> </a-tab-pane>
{{ item.author }} 发表在 <a <a-tab-pane
href="javascript:void(0);" tab="日志"
target="_blank" key="3"
>{{ item.post.title }}</a> >
</template> <recent-comment-tab type="journal"></recent-comment-tab>
<template slot="actions"> </a-tab-pane>
<span @click="handleCommentReplyClick(item)"></span> </a-tabs>
</template> </div>
<p class="comment-content-wrapper" slot="content" v-html="item.content"></p>
<a-tooltip
slot="datetime"
:title="item.createTime | moment"
>
<span>{{ item.createTime | timeAgo }}</span>
</a-tooltip>
</a-comment>
</a-list-item>
</a-list>
</a-tab-pane> </a-tab-pane>
</a-tabs> </a-tabs>
</div> </div>
@ -302,42 +289,16 @@
</a-popconfirm> </a-popconfirm>
</div> </div>
</a-drawer> </a-drawer>
<a-modal
v-if="selectComment"
:title="'回复给:'+selectComment.author"
v-model="selectCommentVisible"
>
<template slot="footer">
<a-button
key="submit"
type="primary"
@click="handleReplyComment"
>
回复
</a-button>
</template>
<a-form layout="vertical">
<a-form-item>
<a-input
type="textarea"
:autosize="{ minRows: 8 }"
v-model="replyComment.content"
/>
</a-form-item>
</a-form>
</a-modal>
</page-view> </page-view>
</template> </template>
<script> <script>
import { PageView } from '@/layouts' import { PageView } from '@/layouts'
import AnalysisCard from './components/AnalysisCard' import AnalysisCard from './components/AnalysisCard'
import RecentCommentTab from './components/RecentCommentTab'
import { mixin, mixinDevice } from '@/utils/mixin.js' import { mixin, mixinDevice } from '@/utils/mixin.js'
import marked from 'marked'
import postApi from '@/api/post' import postApi from '@/api/post'
import postCommentApi from '@/api/postComment'
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'
@ -346,7 +307,8 @@ export default {
mixins: [mixin, mixinDevice], mixins: [mixin, mixinDevice],
components: { components: {
PageView, PageView,
AnalysisCard AnalysisCard,
RecentCommentTab
}, },
data() { data() {
return { return {
@ -357,25 +319,20 @@ export default {
countsLoading: true, countsLoading: true,
logDrawerVisiable: false, logDrawerVisiable: false,
postData: [], postData: [],
commentData: [],
logData: [], logData: [],
countsData: {}, countsData: {},
journal: {}, journal: {},
logs: [],
logPagination: { logPagination: {
page: 1, page: 1,
size: 50, size: 50,
sort: null sort: null
}, }
logs: [],
selectCommentVisible: false,
selectComment: null,
replyComment: {}
} }
}, },
created() { created() {
this.getCounts() this.getCounts()
this.listLatestPosts() this.listLatestPosts()
this.listLatestComments()
this.listLatestLogs() this.listLatestLogs()
}, },
computed: { computed: {
@ -397,12 +354,6 @@ export default {
log.type = this.logType[log.type].text log.type = this.logType[log.type].text
return log return log
}) })
},
formmatedCommentData() {
return this.commentData.map(comment => {
comment.content = marked(comment.content, { sanitize: true })
return comment
})
} }
}, },
methods: { methods: {
@ -412,17 +363,11 @@ export default {
this.activityLoading = false this.activityLoading = false
}) })
}, },
listLatestComments() {
postCommentApi.listLatest(5, 'PUBLISHED').then(response => {
this.commentData = response.data.data
this.activityLoading = false
this.writeLoading = false
})
},
listLatestLogs() { listLatestLogs() {
logApi.listLatest(5).then(response => { logApi.listLatest(5).then(response => {
this.logData = response.data.data this.logData = response.data.data
this.logLoading = false this.logLoading = false
this.writeLoading = false
}) })
}, },
getCounts() { getCounts() {
@ -458,21 +403,6 @@ export default {
this.listLatestLogs() this.listLatestLogs()
}) })
}, },
handleCommentReplyClick(comment) {
this.selectComment = comment
this.selectCommentVisible = true
this.replyComment.parentId = comment.id
this.replyComment.postId = comment.post.id
},
handleReplyComment() {
postCommentApi.create(this.replyComment).then(response => {
this.$message.success('回复成功!')
this.replyComment = {}
this.selectComment = {}
this.selectCommentVisible = false
this.listLatestComments()
})
},
onPaginationChange(page, pageSize) { onPaginationChange(page, pageSize) {
this.$log.debug(`Current: ${page}, PageSize: ${pageSize}`) this.$log.debug(`Current: ${page}, PageSize: ${pageSize}`)
this.logPagination.page = page this.logPagination.page = page

View File

@ -0,0 +1,96 @@
<template>
<a-list
itemLayout="horizontal"
:dataSource="formmatedCommentData"
:loading="loading"
>
<a-list-item
slot="renderItem"
slot-scope="item, index"
:key="index"
>
<a-comment :avatar="'//gravatar.loli.net/avatar/'+item.gavatarMd5+'/?s=256&d=mp'">
<template slot="author">
{{ item.author }} 发表在 <a
href="javascript:void(0);"
target="_blank"
>{{ item.post.title }}</a>
</template>
<template slot="actions">
<span>回复</span>
</template>
<p
class="comment-content-wrapper"
slot="content"
v-html="item.content"
></p>
<a-tooltip
slot="datetime"
:title="item.createTime | moment"
>
<span>{{ item.createTime | timeAgo }}</span>
</a-tooltip>
</a-comment>
</a-list-item>
</a-list>
</template>
<script>
import commentApi from '@/api/comment'
import marked from 'marked'
export default {
name: 'RecentCommentTab',
props: {
type: {
type: String,
required: false,
default: 'post',
validator: function(value) {
return ['post', 'sheet', 'journal'].indexOf(value) !== -1
}
}
},
data() {
return {
comments: [],
loading: false
}
},
computed: {
formmatedCommentData() {
return this.comments.map(comment => {
comment.content = marked(comment.content, { sanitize: true })
return comment
})
}
},
created() {
this.loadComments()
},
methods: {
loadComments() {
this.loading = true
switch (this.type) {
case 'post':
commentApi.latestPostComment(5, 'PUBLISHED').then(response => {
this.comments = response.data.data
this.loading = false
})
break
case 'sheet':
commentApi.latestSheetComment(5, 'PUBLISHED').then(response => {
this.comments = response.data.data
this.loading = false
})
break
case 'journal':
commentApi.latestJournalComment(5, 'PUBLISHED').then(response => {
this.comments = response.data.data
this.loading = false
})
break
}
}
}
}
</script>

View File

@ -110,9 +110,7 @@
:src="themeProperty.screenshots" :src="themeProperty.screenshots"
slot="cover" slot="cover"
> >
<a-card-meta <a-card-meta :description="themeProperty.description">
:description="themeProperty.description"
>
<template slot="title"> <template slot="title">
<a <a
:href="themeProperty.author.website" :href="themeProperty.author.website"
@ -256,43 +254,45 @@
:footer="null" :footer="null"
:bodyStyle="{ padding: '0 24px 24px' }" :bodyStyle="{ padding: '0 24px 24px' }"
> >
<a-tabs defaultActiveKey="1"> <div class="custom-tab-wrapper">
<a-tab-pane <a-tabs>
tab="本地上传" <a-tab-pane
key="1" tab="本地上传"
> key="1"
<upload
name="file"
multiple
accept="application/zip"
:uploadHandler="uploadHandler"
@change="handleChange"
@success="handleUploadSuccess"
> >
<p class="ant-upload-drag-icon"> <upload
<a-icon type="inbox" /> name="file"
</p> multiple
<p class="ant-upload-text">点击选择主题或将主题拖拽到此处</p> accept="application/zip"
<p class="ant-upload-hint">支持单个或批量上传仅支持 ZIP 格式的文件</p> :uploadHandler="uploadHandler"
</upload> @change="handleChange"
</a-tab-pane> @success="handleUploadSuccess"
<a-tab-pane >
tab="远程拉取" <p class="ant-upload-drag-icon">
key="2" <a-icon type="inbox" />
> </p>
<a-form layout="vertical"> <p class="ant-upload-text">点击选择主题或将主题拖拽到此处</p>
<a-form-item label="远程地址:"> <p class="ant-upload-hint">支持单个或批量上传仅支持 ZIP 格式的文件</p>
<a-input v-model="fetchingUrl" /> </upload>
</a-form-item> </a-tab-pane>
<a-form-item> <a-tab-pane
<a-button tab="远程拉取"
type="primary" key="2"
@click="handleFetching" >
>确定</a-button> <a-form layout="vertical">
</a-form-item> <a-form-item label="远程地址:">
</a-form> <a-input v-model="fetchingUrl" />
</a-tab-pane> </a-form-item>
</a-tabs> <a-form-item>
<a-button
type="primary"
@click="handleFetching"
>确定</a-button>
</a-form-item>
</a-form>
</a-tab-pane>
</a-tabs>
</div>
</a-modal> </a-modal>
</div> </div>
</template> </template>

View File

@ -415,104 +415,106 @@
<span slot="tab"> <span slot="tab">
<a-icon type="mail" />SMTP 服务 <a-icon type="mail" />SMTP 服务
</span> </span>
<a-tabs defaultActiveKey="1"> <div class="custom-tab-wrapper">
<a-tab-pane <a-tabs>
tab="发信设置" <a-tab-pane
key="1" tab="发信设置"
> key="1"
<a-form layout="vertical"> >
<a-form-item <a-form layout="vertical">
label="是否启用:" <a-form-item
:wrapper-col="wrapperCol" label="是否启用:"
> :wrapper-col="wrapperCol"
<a-switch v-model="options.email_enabled" />
</a-form-item>
<a-form-item
label="SMTP 地址:"
:wrapper-col="wrapperCol"
>
<a-input v-model="options.email_host" />
</a-form-item>
<a-form-item
label="发送协议:"
:wrapper-col="wrapperCol"
>
<a-input v-model="options.email_protocol" />
</a-form-item>
<a-form-item
label="SSL 端口:"
:wrapper-col="wrapperCol"
>
<a-input v-model="options.email_ssl_port" />
</a-form-item>
<a-form-item
label="邮箱账号:"
:wrapper-col="wrapperCol"
>
<a-input v-model="options.email_username" />
</a-form-item>
<a-form-item
label="邮箱密码:"
:wrapper-col="wrapperCol"
>
<a-tooltip
:trigger="['focus']"
placement="right"
title="部分邮箱可能是授权码"
> >
<a-input v-model="options.email_password" /> <a-switch v-model="options.email_enabled" />
</a-tooltip> </a-form-item>
</a-form-item> <a-form-item
<a-form-item label="SMTP 地址:"
label="发件人:" :wrapper-col="wrapperCol"
:wrapper-col="wrapperCol" >
> <a-input v-model="options.email_host" />
<a-input v-model="options.email_from_name" /> </a-form-item>
</a-form-item> <a-form-item
<a-form-item> label="发送协议:"
<a-button :wrapper-col="wrapperCol"
type="primary" >
@click="handleSaveOptions" <a-input v-model="options.email_protocol" />
>保存</a-button> </a-form-item>
</a-form-item> <a-form-item
</a-form> label="SSL 端口:"
</a-tab-pane> :wrapper-col="wrapperCol"
<a-tab-pane >
tab="发送测试" <a-input v-model="options.email_ssl_port" />
key="2" </a-form-item>
> <a-form-item
<a-form layout="vertical"> label="邮箱账号:"
<a-form-item :wrapper-col="wrapperCol"
label="收件人:" >
:wrapper-col="wrapperCol" <a-input v-model="options.email_username" />
> </a-form-item>
<a-input v-model="mailParam.to" /> <a-form-item
</a-form-item> label="邮箱密码:"
<a-form-item :wrapper-col="wrapperCol"
label="主题:" >
:wrapper-col="wrapperCol" <a-tooltip
> :trigger="['focus']"
<a-input v-model="mailParam.subject" /> placement="right"
</a-form-item> title="部分邮箱可能是授权码"
<a-form-item >
label="内容:" <a-input v-model="options.email_password" />
:wrapper-col="wrapperCol" </a-tooltip>
> </a-form-item>
<a-input <a-form-item
type="textarea" label="发件人:"
:autosize="{ minRows: 5 }" :wrapper-col="wrapperCol"
v-model="mailParam.content" >
/> <a-input v-model="options.email_from_name" />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<a-button <a-button
type="primary" type="primary"
@click="handleTestMailClick" @click="handleSaveOptions"
>发送</a-button> >保存</a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-tab-pane> </a-tab-pane>
</a-tabs> <a-tab-pane
tab="发送测试"
key="2"
>
<a-form layout="vertical">
<a-form-item
label="收件人:"
:wrapper-col="wrapperCol"
>
<a-input v-model="mailParam.to" />
</a-form-item>
<a-form-item
label="主题:"
:wrapper-col="wrapperCol"
>
<a-input v-model="mailParam.subject" />
</a-form-item>
<a-form-item
label="内容:"
:wrapper-col="wrapperCol"
>
<a-input
type="textarea"
:autosize="{ minRows: 5 }"
v-model="mailParam.content"
/>
</a-form-item>
<a-form-item>
<a-button
type="primary"
@click="handleTestMailClick"
>发送</a-button>
</a-form-item>
</a-form>
</a-tab-pane>
</a-tabs>
</div>
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="other"> <a-tab-pane key="other">
<span slot="tab"> <span slot="tab">