Browse Source

feat(component): collapse comments longer than 4 lines

main
Mohan 1 month ago
parent
commit
372ab9d293
  1. 61
      src/components/CommentSection.vue

61
src/components/CommentSection.vue

@ -32,6 +32,29 @@ const authorName = ref('')
const authorEmail = ref('') const authorEmail = ref('')
const content = ref('') const content = ref('')
const quotedComment = ref<CommentResponse | null>(null) const quotedComment = ref<CommentResponse | null>(null)
const overflowIds = ref<Set<number>>(new Set())
const expandedIds = ref<Set<number>>(new Set())
function measureComment(id: number, el: Element | null) {
if (!el) return
const node = el as HTMLElement
const lh = parseFloat(getComputedStyle(node).lineHeight) || 22
if (node.scrollHeight > lh * 4 + 2) {
if (!overflowIds.value.has(id)) {
overflowIds.value = new Set([...overflowIds.value, id])
}
}
}
function toggleExpand(id: number) {
const next = new Set(expandedIds.value)
if (next.has(id)) {
next.delete(id)
} else {
next.add(id)
}
expandedIds.value = next
}
function escapeBrackets(text: string): string { function escapeBrackets(text: string): string {
return text.replace(/[<>]/g, (ch) => '\\' + ch) return text.replace(/[<>]/g, (ch) => '\\' + ch)
@ -205,7 +228,20 @@ onMounted(() => {
<span class="comment-author">{{ comment.authorName }}</span> <span class="comment-author">{{ comment.authorName }}</span>
<span class="comment-time">{{ formatDate(comment.createdAt) }}</span> <span class="comment-time">{{ formatDate(comment.createdAt) }}</span>
</div> </div>
<p class="comment-content" v-html="renderCommentContent(comment.content ?? '')"></p>
<p
class="comment-content"
:class="{ 'content-clamped': overflowIds.has(comment.id!) && !expandedIds.has(comment.id!) }"
:ref="(el: unknown) => measureComment(comment.id!, el as Element | null)"
v-html="renderCommentContent(comment.content ?? '')"
></p>
<button
v-if="overflowIds.has(comment.id!)"
class="comment-toggle"
type="button"
@click="toggleExpand(comment.id!)"
>
{{ expandedIds.has(comment.id!) ? '收起' : '展开全文' }}
</button>
<button class="comment-quote" type="button" title="引用评论" @click="quoteComment(comment)"> <button class="comment-quote" type="button" title="引用评论" @click="quoteComment(comment)">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" /> <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" />
@ -345,6 +381,29 @@ onMounted(() => {
white-space: pre-line; white-space: pre-line;
} }
.comment-content.content-clamped {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
overflow: hidden;
}
.comment-toggle {
display: block;
margin-top: 4px;
border: none;
background: none;
color: var(--ac-primary-ink);
cursor: pointer;
font-size: 12px;
padding: 2px 0;
transition: color var(--song-dur-1) var(--song-ease);
}
.comment-toggle:hover {
color: var(--ac-primary);
}
.comment-star { .comment-star {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;

Loading…
Cancel
Save