|
|
@ -1,6 +1,6 @@ |
|
|
<script setup lang="ts"> |
|
|
<script setup lang="ts"> |
|
|
import { ref, computed, onMounted } from 'vue' |
|
|
import { ref, computed, onMounted } from 'vue' |
|
|
import { commentApi } from '@/api/client' |
|
|
|
|
|
|
|
|
import { commentApi, commentAdminApi } from '@/api/client' |
|
|
import type { CommentResponse } from '@/generated/api' |
|
|
import type { CommentResponse } from '@/generated/api' |
|
|
import { useAuthStore } from '@/stores/auth' |
|
|
import { useAuthStore } from '@/stores/auth' |
|
|
import SongButton from '@/components/SongButton.vue' |
|
|
import SongButton from '@/components/SongButton.vue' |
|
|
@ -94,6 +94,25 @@ function openForm() { |
|
|
formOpen.value = true |
|
|
formOpen.value = true |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function canDelete(comment: CommentResponse): boolean { |
|
|
|
|
|
if (authStore.isAdmin) return true |
|
|
|
|
|
if (!isLoggedIn.value) return false |
|
|
|
|
|
return comment.authorName === authStore.username |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async function deleteComment(comment: CommentResponse) { |
|
|
|
|
|
const id = comment.id |
|
|
|
|
|
if (id == null) return |
|
|
|
|
|
if (!window.confirm(`确定删除评论?`)) return |
|
|
|
|
|
try { |
|
|
|
|
|
await commentAdminApi.apiAdminCommentsIdDelete(id) |
|
|
|
|
|
comments.value = comments.value.filter((c) => c.id !== id) |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.error(e) |
|
|
|
|
|
error.value = '删除失败' |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
const commentStarBusy = ref<Set<number>>(new Set()) |
|
|
const commentStarBusy = ref<Set<number>>(new Set()) |
|
|
|
|
|
|
|
|
async function toggleCommentStar(comment: CommentResponse) { |
|
|
async function toggleCommentStar(comment: CommentResponse) { |
|
|
@ -149,6 +168,14 @@ onMounted(() => { |
|
|
</svg> |
|
|
</svg> |
|
|
<span>{{ comment.starCount ?? 0 }}</span> |
|
|
<span>{{ comment.starCount ?? 0 }}</span> |
|
|
</button> |
|
|
</button> |
|
|
|
|
|
<button v-if="canDelete(comment)" class="comment-delete" type="button" title="删除评论" @click="deleteComment(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"> |
|
|
|
|
|
<path d="M3 6h18" /> |
|
|
|
|
|
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /> |
|
|
|
|
|
<path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" /> |
|
|
|
|
|
</svg> |
|
|
|
|
|
<span>删除</span> |
|
|
|
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</article> |
|
|
</article> |
|
|
</div> |
|
|
</div> |
|
|
@ -284,6 +311,25 @@ onMounted(() => { |
|
|
color: var(--ac-primary); |
|
|
color: var(--ac-primary); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.comment-delete { |
|
|
|
|
|
display: inline-flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
gap: 3px; |
|
|
|
|
|
margin-left: 8px; |
|
|
|
|
|
border: none; |
|
|
|
|
|
background: none; |
|
|
|
|
|
color: var(--ac-text-disabled); |
|
|
|
|
|
cursor: pointer; |
|
|
|
|
|
font-size: 12px; |
|
|
|
|
|
padding: 2px 6px; |
|
|
|
|
|
border-radius: var(--song-radius-s); |
|
|
|
|
|
transition: color var(--song-dur-1) var(--song-ease); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.comment-delete:hover { |
|
|
|
|
|
color: var(--ac-danger-ink); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
.comment-write { |
|
|
.comment-write { |
|
|
margin-top: 8px; |
|
|
margin-top: 8px; |
|
|
display: flex; |
|
|
display: flex; |
|
|
|