laobinghu ce208df092 feat: 实现 Nuxt4 + Nuxt UI 博客前端完整功能
核心功能:
- 项目初始化 (Nuxt 4 + Nuxt UI + Pinia + ofetch)
- TypeScript 类型定义 (User, Article, Comment, API 响应)
- 认证系统 (登录/登出、Cookie 支持、权限中间件)
- 文章列表页 (筛选、分页、响应式布局)
- 文章详情页 (Markdown 渲染、评论系统)
- 文章编辑器 (左右分栏、实时预览、Markdown 工具栏)

管理后台:
- 侧边栏布局、权限检查
- 数据分析 (数据统计卡片、热门文章、评论审核统计)
- 文章管理 (表格、筛选、删除)
- 评论管理 (审核通过/拒绝、删除)
- 用户管理 (角色管理、删除)

全局组件:
- 导航栏 (暗色模式切换、移动端菜单)
- 页脚
- 403/404 错误页

配置文件:
- .env.example 环境变量模板
- nuxt.config.ts 完整配置
- 自定义 CSS 样式
2026-03-28 15:56:50 +08:00

92 lines
2.1 KiB
Vue

<template>
<div class="mt-4">
<div v-if="isAuthenticated">
<UForm :state="form" @submit="onSubmit">
<UFormField class="w-full">
<UTextarea
v-model="form.content"
:placeholder="placeholder"
:minrows="3"
:maxrows="8"
class="w-full"
autoresize
/>
</UFormField>
<div class="mt-2 flex justify-between items-center">
<span class="text-xs text-gray-500 dark:text-gray-400">
{{ form.content.length }}/2000
</span>
<div class="flex gap-2">
<UButton
v-if="parentId"
variant="ghost"
size="sm"
@click="$emit('cancel')"
>
取消
</UButton>
<UButton
type="submit"
color="indigo"
size="sm"
:loading="submitting"
:disabled="!form.content.trim()"
>
{{ parentId ? '回复' : '发表评论' }}
</UButton>
</div>
</div>
</UForm>
</div>
<div v-else class="bg-gray-50 dark:bg-gray-800 rounded-lg p-4 text-center">
<p class="text-gray-600 dark:text-gray-400 mb-2">登录后发表评论</p>
<UButton to="/login" color="indigo" size="sm">立即登录</UButton>
</div>
</div>
</template>
<script setup lang="ts">
const props = defineProps<{
articleId: number
parentId?: number
placeholder?: string
}>()
const emit = defineEmits<{
submitted: []
cancel: []
}>()
const { createComment } = useComments()
const { isAuthenticated } = useAuth()
const form = ref({
content: '',
})
const submitting = ref(false)
const onSubmit = async () => {
if (!form.value.content.trim()) return
submitting.value = true
try {
await createComment(
props.articleId,
form.value.content,
props.parentId,
)
form.value.content = ''
emit('submitted')
// TODO: 显示成功提示
} catch (error) {
console.error('Failed to submit comment:', error)
// TODO: 显示错误提示
} finally {
submitting.value = false
}
}
</script>