BUG修复,返回结构统一

This commit is contained in:
李琦
2026-01-16 17:03:34 +08:00
parent 87ed11db7a
commit e6edf7210b
57 changed files with 3642 additions and 1074 deletions

View File

@@ -85,16 +85,33 @@
<!-- Category Field -->
<div class="space-y-2">
<label for="category" class="block text-xs font-medium text-art-muted uppercase tracking-wider">分类</label>
<input
type="text"
id="category"
v-model="form.category"
class="admin-input"
placeholder="文章分类"
required
<CustomSelect
v-model="form.categoryId"
:options="categories"
placeholder="选择文章分类"
/>
<div class="text-art-error text-xs mt-1" v-if="errors.category">
{{ errors.category }}
<div class="text-art-error text-xs mt-1" v-if="errors.categoryId">
{{ errors.categoryId }}
</div>
</div>
<!-- Tags Field -->
<div class="space-y-2">
<label class="block text-xs font-medium text-art-muted uppercase tracking-wider">标签</label>
<div class="flex flex-wrap gap-2">
<button
type="button"
v-for="tag in availableTags"
:key="tag.id"
@click="toggleTag(tag.id)"
class="px-2 py-1 text-xs rounded border transition-colors"
:class="form.tagIds.includes(tag.id) ? 'bg-art-accent/20 border-art-accent text-art-accent' : 'bg-white/5 border-white/10 text-art-muted hover:border-white/30'"
>
{{ tag.name }}
</button>
<div v-if="availableTags.length === 0" class="text-xs text-art-muted italic">
暂无可用标签
</div>
</div>
</div>
@@ -140,7 +157,7 @@ import { MdEditor } from 'md-editor-v3'
import 'md-editor-v3/lib/style.css'
import { useToast } from '../../composables/useToast'
import { createPost, updatePost, fetchPost } from '../../services/api'
import { createPost, updatePost, fetchPost, fetchCategories, fetchTags, Category, Tag } from '../../services/api'
import CustomSelect from '../../components/CustomSelect.vue'
const router = useRouter()
@@ -158,14 +175,19 @@ const isSubmitting = ref(false)
const isEditing = computed(() => !!route.params.id)
const errors = reactive<Record<string, string>>({})
// Data sources
const categories = ref<{value: number, label: string}[]>([])
const availableTags = ref<Tag[]>([])
// Form data
const form = reactive({
title: '',
category: '',
categoryId: 0,
date: new Date().toISOString().split('T')[0],
excerpt: '',
content: '',
isPublished: 1
isPublished: 1,
tagIds: [] as number[]
})
// Select options
@@ -190,8 +212,8 @@ const validateForm = (): boolean => {
}
// Validate category
if (!form.category.trim()) {
errors.category = '文章分类不能为空'
if (!form.categoryId) {
errors.categoryId = '请选择文章分类'
isValid = false
isSidebarOpen.value = true
}
@@ -212,6 +234,16 @@ const validateForm = (): boolean => {
return isValid
}
// Toggle tag selection
const toggleTag = (tagId: number) => {
const index = form.tagIds.indexOf(tagId)
if (index === -1) {
form.tagIds.push(tagId)
} else {
form.tagIds.splice(index, 1)
}
}
// Submit handler
const handleSubmit = async () => {
if (!validateForm()) {
@@ -221,13 +253,24 @@ const handleSubmit = async () => {
isSubmitting.value = true
try {
// Construct payload
const payload = {
title: form.title,
categoryId: form.categoryId,
date: form.date,
excerpt: form.excerpt,
content: form.content,
isPublished: form.isPublished,
tags: form.tagIds.map(id => ({ id } as any)) // Backend expects objects with ID
}
if (isEditing.value) {
// Update existing post
await updatePost(route.params.id as string, form)
await updatePost(route.params.id as string, payload)
toast.showToast('文章更新成功', 'success')
} else {
// Create new post
await createPost(form)
await createPost(payload)
toast.showToast('文章创建成功', 'success')
}
@@ -246,26 +289,49 @@ const handleCancel = () => {
router.push('/admin/posts')
}
// Lifecycle
onMounted(async () => {
// If editing, load post data from API
if (isEditing.value) {
try {
// Load initial data
const loadData = async () => {
try {
// Fetch categories and tags in parallel
const [cats, tags] = await Promise.all([
fetchCategories(),
fetchTags()
])
categories.value = cats.map(c => ({
value: c.id,
label: c.name
}))
availableTags.value = tags
// If editing, load post data
if (isEditing.value) {
const postId = route.params.id as string
const post = await fetchPost(postId)
// Populate form with post data
form.title = post.title
form.category = post.category
form.categoryId = post.categoryId
form.date = post.date
form.excerpt = post.excerpt || ''
form.content = post.content || ''
form.isPublished = post.isPublished === 1 ? 1 : 0
} catch (error: any) {
console.error('Failed to fetch post data:', error)
toast.showToast('加载文章数据失败: ' + (error.message || '未知错误'), 'error')
// Map tags to tagIds
if (post.tags && post.tags.length > 0) {
form.tagIds = post.tags.map(t => t.id)
}
}
} catch (error: any) {
console.error('Failed to load data:', error)
toast.showToast('加载数据失败: ' + (error.message || '未知错误'), 'error')
}
}
// Lifecycle
onMounted(() => {
loadData()
})
</script>