138 lines
3.9 KiB
Vue
138 lines
3.9 KiB
Vue
<script setup lang="ts">
|
|
// 文章互动区(点赞/打赏/分享)+ 评论区
|
|
import { ref } from 'vue'
|
|
|
|
import Avatar from '@/components/common/Avatar.vue'
|
|
import Time from '@/components/common/Time.vue'
|
|
import type { Comment, Post } from '@/mock/data'
|
|
import { comments } from '@/mock/data'
|
|
|
|
const props = defineProps<{ post: Post }>()
|
|
|
|
// 点赞
|
|
const liked = ref(false)
|
|
const likeCount = ref(props.post.likes)
|
|
function toggleLike() {
|
|
liked.value = !liked.value
|
|
likeCount.value += liked.value ? 1 : -1
|
|
}
|
|
|
|
// 打赏
|
|
const tipped = ref(false)
|
|
|
|
// 分享(复制链接)
|
|
const shared = ref(false)
|
|
async function share() {
|
|
try {
|
|
await navigator.clipboard.writeText(window.location.href)
|
|
} catch {
|
|
/* ignore clipboard errors */
|
|
}
|
|
shared.value = true
|
|
window.setTimeout(() => (shared.value = false), 2000)
|
|
}
|
|
|
|
// 评论
|
|
const list = ref<Comment[]>(comments)
|
|
const draft = ref('')
|
|
function submitComment() {
|
|
const content = draft.value.trim()
|
|
if (!content) return
|
|
list.value.unshift({
|
|
id: `c-${list.value.length + 1}`,
|
|
author: {
|
|
handle: 'you',
|
|
name: 'You',
|
|
avatar: '',
|
|
},
|
|
content,
|
|
date: new Date().toISOString(),
|
|
likes: 0,
|
|
})
|
|
draft.value = ''
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<!-- 互动按钮 -->
|
|
<div
|
|
class="xlog-reactions flex fill-gray-400 text-gray-500 sm:items-center space-x-6 sm:space-x-10 mt-14 mb-12"
|
|
>
|
|
<button class="button is-like" :class="{ 'text-[#f91880]': liked }" @click="toggleLike">
|
|
<i class="i-mingcute-thumb-up-2-fill mr-2" />
|
|
<span>{{ likeCount }}</span>
|
|
</button>
|
|
<button class="button is-tip" @click="tipped = !tipped">
|
|
<i class="i-mingcute-pig-money-line mr-2" />
|
|
<span>{{ tipped ? 'Tipped ✓' : 'Tip' }}</span>
|
|
</button>
|
|
<button class="button is-share" @click="share">
|
|
<i class="i-mingcute-share-forward-line mr-2" />
|
|
<span>{{ shared ? 'Copied!' : 'Share' }}</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 评论区 -->
|
|
<div class="xlog-comment mb-10" id="comments">
|
|
<div class="xlog-comment-count border-b pb-2 mb-6 font-bold">
|
|
Comments ({{ list.length }})
|
|
</div>
|
|
|
|
<!-- 评论输入 -->
|
|
<div class="xlog-comment-input flex mb-6">
|
|
<span class="mr-3">
|
|
<Avatar name="You" :size="45" />
|
|
</span>
|
|
<div class="flex-1">
|
|
<textarea
|
|
v-model="draft"
|
|
class="input is-block min-h-[74px] py-3 resize-y"
|
|
placeholder="Write a comment..."
|
|
@keydown.meta.enter="submitComment"
|
|
@keydown.ctrl.enter="submitComment"
|
|
/>
|
|
<div class="flex justify-end mt-2">
|
|
<button
|
|
class="button is-primary is-sm"
|
|
:class="{ 'is-loading': false }"
|
|
:disabled="!draft.trim()"
|
|
@click="submitComment"
|
|
>
|
|
Send
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 评论列表 -->
|
|
<div class="xlog-comment-list">
|
|
<div
|
|
v-for="comment in list"
|
|
:key="comment.id"
|
|
class="xlog-comment-item mt-6 flex space-x-3"
|
|
>
|
|
<Avatar :src="comment.author.avatar" :name="comment.author.name" :size="40" />
|
|
<div class="flex-1 min-w-0">
|
|
<div class="flex items-center space-x-2 text-sm">
|
|
<span class="font-bold">{{ comment.author.name }}</span>
|
|
<span class="text-zinc-400 text-xs">
|
|
<Time :date="comment.date" />
|
|
</span>
|
|
</div>
|
|
<div class="text-zinc-600 mt-1 leading-relaxed break-words">
|
|
{{ comment.content }}
|
|
</div>
|
|
<button
|
|
class="text-zinc-400 text-xs mt-1 hover:text-accent inline-flex items-center"
|
|
>
|
|
<i class="i-mingcute-thumb-up-2-line mr-1" />
|
|
{{ comment.likes }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|