后台管理系统:JWT 认证 + 分栏编辑器的完整实现

2026年6月13日 blogTech 6 分钟阅读 2 次阅读
📖 文章摘要

完整后台管理系统详解:JWT 认证中间件、分栏实时 Markdown 编辑器、评论审核流程、站点 key-value 配置和图片上传。

后台管理系统

博客后台提供完整的文章/分类/标签/评论/站点配置管理功能,所有接口需 JWT 认证。

认证体系

使用 JWT 实现无状态认证。首次部署通过 /api/auth/init 创建管理员,后续通过 /api/auth/login 登录。

前端认证拦截

Nuxt 中间件 middleware/auth.ts 自动保护后台路由:

export default defineNuxtRouteMiddleware((to) => {
  const token = useCookie('auth_token').value
  if (!token) return navigateTo('/admin/login')
})

所有 /admin/* 页面自动检查 token 有效性,无效则跳转登录。

文章编辑器

分栏实时预览编辑器是后台的核心功能:

<template>
  <div class="grid grid-cols-2 gap-4">
    <!-- 左栏:Markdown 编辑器 -->
    <textarea v-model="form.content_md" @input="updatePreview" />
    <!-- 右栏:实时预览 -->
    <div class="prose" v-html="preview" />
  </div>
</template>

主要功能特点:

  • 分栏布局 — 左栏编辑 Markdown 源码,右栏实时渲染预览
  • 同步滚动 — 编辑时自动渲染,无需手动刷新
  • 草稿机制 — 支持将文章存为草稿,发布时才写入 published_at
  • 标签选择 — 复选框选择已存在的标签,支持多选
  • 分类选择 — 下拉列表选择所属分类

创建文章 API

@router.post("", response_model=ArticleResponse)
def create_article(data: ArticleCreate, ...):
    article = Article(
        title=data.title, slug=data.slug,
        content_md=data.content_md,
        content_html=_render_markdown(data.content_md),  # 写入时渲染
        published_at=datetime.utcnow() if data.is_published else None,
    )
    db.add(article)
    if data.tag_ids:
        tags = db.query(Tag).filter(Tag.id.in_(data.tag_ids)).all()
        article.tags = tags
    db.commit()
    return article

评论审核

评论提交后默认 is_approved = False,不会对外显示。管理员在后台审核通过后才公开:

@router.post("/{comment_id}/approve")
def approve_comment(comment_id: int, ...):
    comment = db.query(Comment).filter(Comment.id == comment_id).first()
    comment.is_approved = True
    db.commit()

文章管理列表

后台文章列表与前台不同——显示所有状态的文章(已发布 + 草稿 + 已下架),按更新时间倒序:

@router.get("")
def list_all_articles(page, size, q=None, ...):
    query = db.query(Article).order_by(desc(Article.updated_at))
    if q:
        query = query.filter(Article.title.ilike(f"%{q}%"))
    # ...

搜索和筛选

  • 标题模糊搜索(防抖 300ms 输入)
  • 按状态快捷筛选(全部/已发布/草稿/置顶)
  • 批量发布/下架(Promise.all 并发)

站点设置

key-value 配置表通过管理界面编辑,无需修改代码:

@router.put("/admin/site")
def update_settings(data: dict, ...):
    for key, value in data.items():
        setting = db.query(SiteSetting).filter(SiteSetting.key == key).first()
        if setting:
            setting.value = value
        else:
            db.add(SiteSetting(key=key, value=value))
    db.commit()

可配置项:站点名称、作者姓名、头像(base64 上传)、技能标签、社交链接、背景图片地址。

图片上传

上传接口支持 jpg/png/gif/webp 格式,自动压缩优化:

POST /api/admin/upload → 返回图片 URL

图片存储在 /data/uploads/ 目录,通过 Nginx 直出,缓存策略 3 天。

最后更新:2026年6月29日CC BY-NC-SA 4.0

评论

暂无评论,来写第一条吧

© 2026 My Blog. Built with Nuxt.js + FastAPI.