mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-06-06 01:57:34 +08:00
feat: menu
This commit is contained in:
@@ -1,11 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div class="info-content-container" :id="'comment-' + comment.id" :style="{
|
||||||
class="info-content-container"
|
|
||||||
:id="'comment-' + comment.id"
|
|
||||||
:style="{
|
|
||||||
...(level > 0 ? { /*borderLeft: '1px solid #e0e0e0', */borderBottom: 'none' } : {})
|
...(level > 0 ? { /*borderLeft: '1px solid #e0e0e0', */borderBottom: 'none' } : {})
|
||||||
}"
|
}">
|
||||||
>
|
|
||||||
<!-- <div class="user-avatar-container">
|
<!-- <div class="user-avatar-container">
|
||||||
<div class="user-avatar-item">
|
<div class="user-avatar-item">
|
||||||
<img class="user-avatar-item-img" :src="comment.avatar" alt="avatar" />
|
<img class="user-avatar-item-img" :src="comment.avatar" alt="avatar" />
|
||||||
@@ -13,9 +9,18 @@
|
|||||||
</div> -->
|
</div> -->
|
||||||
<div class="info-content">
|
<div class="info-content">
|
||||||
<div class="info-content-header">
|
<div class="info-content-header">
|
||||||
|
<div class="info-content-header-left">
|
||||||
<div class="user-name">{{ comment.userName }}</div>
|
<div class="user-name">{{ comment.userName }}</div>
|
||||||
<div class="post-time">{{ comment.time }}</div>
|
<div class="post-time">{{ comment.time }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="info-content-header-right">
|
||||||
|
<DropdownMenu :items="commentMenuItems">
|
||||||
|
<template #trigger>
|
||||||
|
<i class="fas fa-ellipsis-vertical action-menu-icon"></i>
|
||||||
|
</template>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="info-content-text" v-html="renderMarkdown(comment.text)"></div>
|
<div class="info-content-text" v-html="renderMarkdown(comment.text)"></div>
|
||||||
<div class="article-footer-container">
|
<div class="article-footer-container">
|
||||||
<ReactionsGroup v-model="comment.reactions" content-type="comment" :content-id="comment.id">
|
<ReactionsGroup v-model="comment.reactions" content-type="comment" :content-id="comment.id">
|
||||||
@@ -28,25 +33,16 @@
|
|||||||
</ReactionsGroup>
|
</ReactionsGroup>
|
||||||
</div>
|
</div>
|
||||||
<CommentEditor v-if="showEditor" @submit="submitReply" :loading="isWaitingForReply" />
|
<CommentEditor v-if="showEditor" @submit="submitReply" :loading="isWaitingForReply" />
|
||||||
<div
|
<div v-if="comment.reply && comment.reply.length" class="reply-toggle" @click="toggleReplies">
|
||||||
v-if="comment.reply && comment.reply.length"
|
|
||||||
class="reply-toggle"
|
|
||||||
@click="toggleReplies"
|
|
||||||
>
|
|
||||||
<i v-if="showReplies" class="fas fa-chevron-up reply-toggle-icon"></i>
|
<i v-if="showReplies" class="fas fa-chevron-up reply-toggle-icon"></i>
|
||||||
<i v-else class="fas fa-chevron-down reply-toggle-icon"></i>
|
<i v-else class="fas fa-chevron-down reply-toggle-icon"></i>
|
||||||
|
|
||||||
{{ comment.reply.length }}条回复
|
{{ comment.reply.length }}条回复
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showReplies" class="reply-list">
|
<div v-if="showReplies" class="reply-list">
|
||||||
<BaseTimeline :items="comment.reply" >
|
<BaseTimeline :items="comment.reply">
|
||||||
<template #item="{ item }">
|
<template #item="{ item }">
|
||||||
<CommentItem
|
<CommentItem :key="item.id" :comment="item" :level="level + 1" :default-show-replies="item.openReplies" />
|
||||||
:key="item.id"
|
|
||||||
:comment="item"
|
|
||||||
:level="level + 1"
|
|
||||||
:default-show-replies="item.openReplies"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</BaseTimeline>
|
</BaseTimeline>
|
||||||
<!-- <CommentItem
|
<!-- <CommentItem
|
||||||
@@ -71,6 +67,7 @@ import BaseTimeline from './BaseTimeline.vue'
|
|||||||
import { API_BASE_URL, toast } from '../main'
|
import { API_BASE_URL, toast } from '../main'
|
||||||
import { getToken } from '../utils/auth'
|
import { getToken } from '../utils/auth'
|
||||||
import ReactionsGroup from './ReactionsGroup.vue'
|
import ReactionsGroup from './ReactionsGroup.vue'
|
||||||
|
import DropdownMenu from './DropdownMenu.vue'
|
||||||
const CommentItem = {
|
const CommentItem = {
|
||||||
name: 'CommentItem',
|
name: 'CommentItem',
|
||||||
props: {
|
props: {
|
||||||
@@ -104,6 +101,11 @@ const CommentItem = {
|
|||||||
const toggleEditor = () => {
|
const toggleEditor = () => {
|
||||||
showEditor.value = !showEditor.value
|
showEditor.value = !showEditor.value
|
||||||
}
|
}
|
||||||
|
const commentMenuItems = ref([
|
||||||
|
{ text: '删除评论', color: 'red', onClick: () => deleteComment() }
|
||||||
|
])
|
||||||
|
const deleteComment = () => {
|
||||||
|
}
|
||||||
const submitReply = async (text) => {
|
const submitReply = async (text) => {
|
||||||
if (!text.trim()) return
|
if (!text.trim()) return
|
||||||
isWaitingForReply.value = true
|
isWaitingForReply.value = true
|
||||||
@@ -162,10 +164,12 @@ const CommentItem = {
|
|||||||
toast.success('已复制')
|
toast.success('已复制')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return { showReplies, toggleReplies, showEditor, toggleEditor, submitReply, copyCommentLink, renderMarkdown, isWaitingForReply }
|
return { showReplies, toggleReplies, showEditor, toggleEditor, submitReply, copyCommentLink, renderMarkdown, isWaitingForReply, commentMenuItems, deleteComment }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CommentItem.components = { CommentItem, CommentEditor, BaseTimeline, ReactionsGroup }
|
|
||||||
|
CommentItem.components = { CommentItem, CommentEditor, BaseTimeline, ReactionsGroup, DropdownMenu }
|
||||||
|
|
||||||
export default CommentItem
|
export default CommentItem
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -176,8 +180,7 @@ export default CommentItem
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reply-list {
|
.reply-list {}
|
||||||
}
|
|
||||||
|
|
||||||
.comment-reaction {
|
.comment-reaction {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
@@ -196,8 +199,12 @@ export default CommentItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes highlight {
|
@keyframes highlight {
|
||||||
from { background-color: yellow; }
|
from {
|
||||||
to { background-color: transparent; }
|
background-color: yellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ export default {
|
|||||||
const iconMap = {
|
const iconMap = {
|
||||||
POST_VIEWED: 'fas fa-eye',
|
POST_VIEWED: 'fas fa-eye',
|
||||||
COMMENT_REPLY: 'fas fa-reply',
|
COMMENT_REPLY: 'fas fa-reply',
|
||||||
POST_REVIEWED: 'fas fa-check',
|
POST_REVIEWED: 'fas fa-shield-alt',
|
||||||
POST_REVIEW_REQUEST: 'fas fa-gavel',
|
POST_REVIEW_REQUEST: 'fas fa-gavel',
|
||||||
POST_UPDATED: 'fas fa-comment-dots',
|
POST_UPDATED: 'fas fa-comment-dots',
|
||||||
USER_ACTIVITY: 'fas fa-user',
|
USER_ACTIVITY: 'fas fa-user',
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<i class="fas fa-user-minus"></i>
|
<i class="fas fa-user-minus"></i>
|
||||||
取消订阅
|
取消订阅
|
||||||
</div>
|
</div>
|
||||||
<DropdownMenu v-if="isAdmin && status === 'PENDING'" :items="reviewMenuItems">
|
<DropdownMenu :items="articleMenuItems">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<i class="fas fa-ellipsis-vertical action-menu-icon"></i>
|
<i class="fas fa-ellipsis-vertical action-menu-icon"></i>
|
||||||
</template>
|
</template>
|
||||||
@@ -138,7 +138,8 @@ export default {
|
|||||||
const loggedIn = computed(() => authState.loggedIn)
|
const loggedIn = computed(() => authState.loggedIn)
|
||||||
const isAdmin = computed(() => authState.role === 'ADMIN')
|
const isAdmin = computed(() => authState.role === 'ADMIN')
|
||||||
const isAuthor = computed(() => authState.username === author.value.username)
|
const isAuthor = computed(() => authState.username === author.value.username)
|
||||||
const reviewMenuItems = [
|
const articleMenuItems = [
|
||||||
|
{ text: '删除文章', color: 'red', onClick: () => deletePost() },
|
||||||
{ text: '通过审核', onClick: () => approvePost() },
|
{ text: '通过审核', onClick: () => approvePost() },
|
||||||
{ text: '驳回', color: 'red', onClick: () => rejectPost() }
|
{ text: '驳回', color: 'red', onClick: () => rejectPost() }
|
||||||
]
|
]
|
||||||
@@ -339,6 +340,9 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deletePost = async () => {
|
||||||
|
}
|
||||||
|
|
||||||
const rejectPost = async () => {
|
const rejectPost = async () => {
|
||||||
const token = getToken()
|
const token = getToken()
|
||||||
if (!token) return
|
if (!token) return
|
||||||
@@ -415,7 +419,7 @@ export default {
|
|||||||
currentIndex,
|
currentIndex,
|
||||||
totalPosts,
|
totalPosts,
|
||||||
postReactions,
|
postReactions,
|
||||||
reviewMenuItems,
|
articleMenuItems,
|
||||||
postId,
|
postId,
|
||||||
postComment,
|
postComment,
|
||||||
onSliderInput,
|
onSliderInput,
|
||||||
|
|||||||
Reference in New Issue
Block a user