mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-08-13 14:51:00 +00:00
Merge pull request #92 from nagisa77/codex/update-commenteditor.vue-with-loading-and-disabled-state
This commit is contained in:
@@ -2,13 +2,24 @@
|
|||||||
<div class="comment-editor-container">
|
<div class="comment-editor-container">
|
||||||
<div :id="editorId" ref="vditorElement"></div>
|
<div :id="editorId" ref="vditorElement"></div>
|
||||||
<div class="comment-bottom-container">
|
<div class="comment-bottom-container">
|
||||||
<div class="comment-submit" @click="submit">发布评论</div>
|
<div
|
||||||
|
class="comment-submit"
|
||||||
|
:class="{ disabled: isDisabled }"
|
||||||
|
@click="submit"
|
||||||
|
>
|
||||||
|
<template v-if="!loading">
|
||||||
|
发布评论
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<i class="fa-solid fa-spinner fa-spin"></i> 发布中...
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted, computed } from 'vue'
|
||||||
import Vditor from 'vditor'
|
import Vditor from 'vditor'
|
||||||
import 'vditor/dist/index.css'
|
import 'vditor/dist/index.css'
|
||||||
|
|
||||||
@@ -19,17 +30,24 @@ export default {
|
|||||||
editorId: {
|
editorId: {
|
||||||
type: String,
|
type: String,
|
||||||
default: () => 'editor-' + Math.random().toString(36).slice(2)
|
default: () => 'editor-' + Math.random().toString(36).slice(2)
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const vditorInstance = ref(null)
|
const vditorInstance = ref(null)
|
||||||
|
const text = ref('')
|
||||||
|
|
||||||
|
const isDisabled = computed(() => props.loading || !text.value.trim())
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
if (!vditorInstance.value) return
|
if (!vditorInstance.value || isDisabled.value) return
|
||||||
const text = vditorInstance.value.getValue()
|
const value = vditorInstance.value.getValue()
|
||||||
if (!text.trim()) return
|
emit('submit', value)
|
||||||
emit('submit', text)
|
|
||||||
vditorInstance.value.setValue('')
|
vditorInstance.value.setValue('')
|
||||||
|
text.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -60,11 +78,14 @@ export default {
|
|||||||
'link',
|
'link',
|
||||||
'image'
|
'image'
|
||||||
],
|
],
|
||||||
toolbarConfig: { pin: true }
|
toolbarConfig: { pin: true },
|
||||||
|
input(value) {
|
||||||
|
text.value = value
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return { submit }
|
return { submit, isDisabled }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -89,6 +110,14 @@ export default {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
.comment-submit.disabled {
|
||||||
|
background-color: var(--primary-color-disabled);
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
.comment-submit.disabled:hover {
|
||||||
|
background-color: var(--primary-color-disabled);
|
||||||
|
}
|
||||||
.comment-submit:hover {
|
.comment-submit:hover {
|
||||||
background-color: var(--primary-color-hover);
|
background-color: var(--primary-color-hover);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<CommentEditor v-if="showEditor" @submit="submitReply" />
|
<CommentEditor v-if="showEditor" @submit="submitReply" :loading="isWaitingForReply" />
|
||||||
<div v-if="comment.reply && comment.reply.length" class="reply-toggle" @click="toggleReplies">
|
<div v-if="comment.reply && comment.reply.length" class="reply-toggle" @click="toggleReplies">
|
||||||
{{ comment.reply.length }}条回复
|
{{ comment.reply.length }}条回复
|
||||||
</div>
|
</div>
|
||||||
@@ -77,6 +77,7 @@ const CommentItem = {
|
|||||||
setup(props) {
|
setup(props) {
|
||||||
const showReplies = ref(false)
|
const showReplies = ref(false)
|
||||||
const showEditor = ref(false)
|
const showEditor = ref(false)
|
||||||
|
const isWaitingForReply = ref(false)
|
||||||
const toggleReplies = () => {
|
const toggleReplies = () => {
|
||||||
showReplies.value = !showReplies.value
|
showReplies.value = !showReplies.value
|
||||||
}
|
}
|
||||||
@@ -85,9 +86,11 @@ const CommentItem = {
|
|||||||
}
|
}
|
||||||
const submitReply = async (text) => {
|
const submitReply = async (text) => {
|
||||||
if (!text.trim()) return
|
if (!text.trim()) return
|
||||||
|
isWaitingForReply.value = true
|
||||||
const token = getToken()
|
const token = getToken()
|
||||||
if (!token) {
|
if (!token) {
|
||||||
toast.error('请先登录')
|
toast.error('请先登录')
|
||||||
|
isWaitingForReply.value = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -120,13 +123,15 @@ const CommentItem = {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast.error('回复失败')
|
toast.error('回复失败')
|
||||||
|
} finally {
|
||||||
|
isWaitingForReply.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const copyCommentLink = () => {
|
const copyCommentLink = () => {
|
||||||
const link = `${location.origin}${location.pathname}#comment-${props.comment.id}`
|
const link = `${location.origin}${location.pathname}#comment-${props.comment.id}`
|
||||||
navigator.clipboard.writeText(link)
|
navigator.clipboard.writeText(link)
|
||||||
}
|
}
|
||||||
return { showReplies, toggleReplies, showEditor, toggleEditor, submitReply, copyCommentLink, renderMarkdown }
|
return { showReplies, toggleReplies, showEditor, toggleEditor, submitReply, copyCommentLink, renderMarkdown, isWaitingForReply }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CommentItem.components = { CommentItem, CommentEditor }
|
CommentItem.components = { CommentItem, CommentEditor }
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CommentEditor @submit="postComment" />
|
<CommentEditor @submit="postComment" :loading="isWaitingPostingComment" />
|
||||||
|
|
||||||
<div class="comments-container">
|
<div class="comments-container">
|
||||||
<CommentItem v-for="comment in comments" :key="comment.id" :comment="comment" :level="0" ref="postItems" />
|
<CommentItem v-for="comment in comments" :key="comment.id" :comment="comment" :level="0" ref="postItems" />
|
||||||
@@ -112,6 +112,7 @@ export default {
|
|||||||
const tags = ref([])
|
const tags = ref([])
|
||||||
const comments = ref([])
|
const comments = ref([])
|
||||||
const isWaitingFetchingPost = ref(false);
|
const isWaitingFetchingPost = ref(false);
|
||||||
|
const isWaitingPostingComment = ref(false);
|
||||||
const postTime = ref('')
|
const postTime = ref('')
|
||||||
const postItems = ref([])
|
const postItems = ref([])
|
||||||
const mainContainer = ref(null)
|
const mainContainer = ref(null)
|
||||||
@@ -169,9 +170,11 @@ export default {
|
|||||||
|
|
||||||
const postComment = async (text) => {
|
const postComment = async (text) => {
|
||||||
if (!text.trim()) return
|
if (!text.trim()) return
|
||||||
|
isWaitingPostingComment.value = true
|
||||||
const token = getToken()
|
const token = getToken()
|
||||||
if (!token) {
|
if (!token) {
|
||||||
toast.error('请先登录')
|
toast.error('请先登录')
|
||||||
|
isWaitingPostingComment.value = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -188,6 +191,8 @@ export default {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast.error('评论失败')
|
toast.error('评论失败')
|
||||||
|
} finally {
|
||||||
|
isWaitingPostingComment.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +232,8 @@ export default {
|
|||||||
onScroll: updateCurrentIndex,
|
onScroll: updateCurrentIndex,
|
||||||
copyPostLink,
|
copyPostLink,
|
||||||
renderMarkdown,
|
renderMarkdown,
|
||||||
isWaitingFetchingPost
|
isWaitingFetchingPost,
|
||||||
|
isWaitingPostingComment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user