159 lines
3.8 KiB
TypeScript
159 lines
3.8 KiB
TypeScript
|
|
// app/api/admin/content/route.ts
|
||
|
|
// 内容模块管理API
|
||
|
|
|
||
|
|
import { NextRequest, NextResponse } from 'next/server'
|
||
|
|
import fs from 'fs'
|
||
|
|
import path from 'path'
|
||
|
|
import matter from 'gray-matter'
|
||
|
|
|
||
|
|
const BOOK_DIR = path.join(process.cwd(), 'book')
|
||
|
|
|
||
|
|
// GET: 获取所有章节列表
|
||
|
|
export async function GET(req: NextRequest) {
|
||
|
|
try {
|
||
|
|
const chapters = getAllChapters()
|
||
|
|
|
||
|
|
return NextResponse.json({
|
||
|
|
success: true,
|
||
|
|
chapters,
|
||
|
|
total: chapters.length
|
||
|
|
})
|
||
|
|
} catch (error) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: '获取章节列表失败' },
|
||
|
|
{ status: 500 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// POST: 创建新章节
|
||
|
|
export async function POST(req: NextRequest) {
|
||
|
|
try {
|
||
|
|
const body = await req.json()
|
||
|
|
const { title, content, category, tags } = body
|
||
|
|
|
||
|
|
if (!title || !content) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: '标题和内容不能为空' },
|
||
|
|
{ status: 400 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
// 生成文件名
|
||
|
|
const fileName = `${title}.md`
|
||
|
|
const filePath = path.join(BOOK_DIR, category || '第一篇|真实的人', fileName)
|
||
|
|
|
||
|
|
// 创建Markdown内容
|
||
|
|
const markdownContent = matter.stringify(content, {
|
||
|
|
title,
|
||
|
|
date: new Date().toISOString(),
|
||
|
|
tags: tags || [],
|
||
|
|
draft: false
|
||
|
|
})
|
||
|
|
|
||
|
|
// 写入文件
|
||
|
|
fs.writeFileSync(filePath, markdownContent, 'utf-8')
|
||
|
|
|
||
|
|
return NextResponse.json({
|
||
|
|
success: true,
|
||
|
|
message: '章节创建成功',
|
||
|
|
filePath
|
||
|
|
})
|
||
|
|
} catch (error) {
|
||
|
|
console.error('创建章节失败:', error)
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: '创建章节失败' },
|
||
|
|
{ status: 500 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// PUT: 更新章节
|
||
|
|
export async function PUT(req: NextRequest) {
|
||
|
|
try {
|
||
|
|
const body = await req.json()
|
||
|
|
const { id, title, content, category, tags } = body
|
||
|
|
|
||
|
|
if (!id) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: '章节ID不能为空' },
|
||
|
|
{ status: 400 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
// TODO: 根据ID找到文件并更新
|
||
|
|
|
||
|
|
return NextResponse.json({
|
||
|
|
success: true,
|
||
|
|
message: '章节更新成功'
|
||
|
|
})
|
||
|
|
} catch (error) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: '更新章节失败' },
|
||
|
|
{ status: 500 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// DELETE: 删除章节
|
||
|
|
export async function DELETE(req: NextRequest) {
|
||
|
|
try {
|
||
|
|
const { searchParams } = new URL(req.url)
|
||
|
|
const id = searchParams.get('id')
|
||
|
|
|
||
|
|
if (!id) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: '章节ID不能为空' },
|
||
|
|
{ status: 400 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
// TODO: 根据ID删除文件
|
||
|
|
|
||
|
|
return NextResponse.json({
|
||
|
|
success: true,
|
||
|
|
message: '章节删除成功'
|
||
|
|
})
|
||
|
|
} catch (error) {
|
||
|
|
return NextResponse.json(
|
||
|
|
{ error: '删除章节失败' },
|
||
|
|
{ status: 500 }
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 辅助函数:获取所有章节
|
||
|
|
function getAllChapters() {
|
||
|
|
const chapters: any[] = []
|
||
|
|
|
||
|
|
// 遍历book目录下的所有子目录
|
||
|
|
const categories = fs.readdirSync(BOOK_DIR).filter(item => {
|
||
|
|
const itemPath = path.join(BOOK_DIR, item)
|
||
|
|
return fs.statSync(itemPath).isDirectory()
|
||
|
|
})
|
||
|
|
|
||
|
|
categories.forEach(category => {
|
||
|
|
const categoryPath = path.join(BOOK_DIR, category)
|
||
|
|
const files = fs.readdirSync(categoryPath).filter(file => file.endsWith('.md'))
|
||
|
|
|
||
|
|
files.forEach(file => {
|
||
|
|
const filePath = path.join(categoryPath, file)
|
||
|
|
const fileContent = fs.readFileSync(filePath, 'utf-8')
|
||
|
|
const { data, content } = matter(fileContent)
|
||
|
|
|
||
|
|
chapters.push({
|
||
|
|
id: `${category}/${file.replace('.md', '')}`,
|
||
|
|
title: data.title || file.replace('.md', ''),
|
||
|
|
category,
|
||
|
|
words: content.length,
|
||
|
|
date: data.date || fs.statSync(filePath).mtime.toISOString(),
|
||
|
|
tags: data.tags || [],
|
||
|
|
draft: data.draft || false,
|
||
|
|
filePath
|
||
|
|
})
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
return chapters.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
|
||
|
|
}
|