Merge pull request #637 from zpaeng/main

fix:删帖需要给发帖者提示
This commit is contained in:
Tim
2025-08-19 17:01:44 +08:00
committed by GitHub
4 changed files with 118 additions and 14 deletions

View File

@@ -21,6 +21,7 @@
</div>
</div>
<GlobalPopups />
<ConfirmDialog />
</div>
</template>
@@ -28,6 +29,7 @@
import HeaderComponent from '~/components/HeaderComponent.vue'
import MenuComponent from '~/components/MenuComponent.vue'
import GlobalPopups from '~/components/GlobalPopups.vue'
import ConfirmDialog from '~/components/ConfirmDialog.vue'
import { useIsMobile } from '~/utils/screen'
const isMobile = useIsMobile()

View File

@@ -0,0 +1,53 @@
<template>
<BasePopup :visible="state.visible" @close="onCancel">
<div class="confirm-dialog">
<h3 class="confirm-title">{{ state.title }}</h3>
<p class="confirm-message">{{ state.message }}</p>
<div class="confirm-actions">
<button class="cancel-button" @click="onCancel">取消</button>
<button class="confirm-button" @click="onConfirm">确认</button>
</div>
</div>
</BasePopup>
</template>
<script setup>
import BasePopup from '~/components/BasePopup.vue'
import { useConfirm } from '~/composables/useConfirm'
const { state, onConfirm, onCancel } = useConfirm()
</script>
<style scoped>
.confirm-dialog {
padding: 20px;
text-align: center;
}
.confirm-title {
margin-top: 0;
}
.confirm-message {
margin: 20px 0;
}
.confirm-actions {
display: flex;
justify-content: center;
gap: 10px;
}
.confirm-button {
background-color: var(--primary-color);
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
}
.cancel-button {
background-color: #ccc;
color: black;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
}
</style>

View File

@@ -0,0 +1,42 @@
import { ref } from 'vue'
const state = ref({
visible: false,
title: '',
message: '',
resolve: null,
reject: null,
})
export const useConfirm = () => {
const confirm = (title, message) => {
state.value.title = title
state.value.message = message
state.value.visible = true
return new Promise((resolve, reject) => {
state.value.resolve = resolve
state.value.reject = reject
})
}
const onConfirm = () => {
if (state.value.resolve) {
state.value.resolve(true)
}
state.value.visible = false
}
const onCancel = () => {
if (state.value.reject) {
state.value.reject(false)
}
state.value.visible = false
}
return {
confirm,
onConfirm,
onCancel,
state,
}
}

View File

@@ -185,6 +185,7 @@ import { useRouter } from 'vue-router'
import { useIsMobile } from '~/utils/screen'
import Dropdown from '~/components/Dropdown.vue'
import { ClientOnly } from '#components'
import { useConfirm } from '~/composables/useConfirm'
const config = useRuntimeConfig()
const API_BASE_URL = config.public.apiBaseUrl
@@ -212,6 +213,7 @@ const subscribed = ref(false)
const commentSort = ref('NEWEST')
const isFetchingComments = ref(false)
const isMobile = useIsMobile()
const { confirm } = useConfirm()
const headerHeight = process.client
? parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--header-height')) || 0
@@ -283,7 +285,7 @@ const articleMenuItems = computed(() => {
const items = []
if (isAuthor.value || isAdmin.value) {
items.push({ text: '编辑文章', onClick: () => editPost() })
items.push({ text: '删除文章', color: 'red', onClick: () => deletePost() })
items.push({ text: '删除文章', color: 'red', onClick: deletePost })
}
if (isAdmin.value) {
if (pinnedAt.value) {
@@ -621,19 +623,24 @@ const editPost = () => {
}
const deletePost = async () => {
const token = getToken()
if (!token) {
toast.error('请先登录')
return
}
const res = await fetch(`${API_BASE_URL}/api/posts/${postId}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${token}` },
})
if (res.ok) {
toast.success('已删除')
navigateTo('/', { replace: true })
} else {
try {
await confirm('确认删除', '确定要删除这篇文章吗?此操作不可撤销。')
const token = getToken()
if (!token) {
toast.error('请先登录')
return
}
const res = await fetch(`${API_BASE_URL}/api/posts/${postId}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${token}` },
})
if (res.ok) {
toast.success('已删除')
navigateTo('/', { replace: true })
} else {
toast.error('操作失败')
}
} catch (e) {
toast.error('操作失败')
}
}