Files
soul-yongping/app/api/book/chapters/route.ts

219 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// app/api/book/chapters/route.ts
// 章节管理API - 使用 Prisma ORM
// 优势类型安全、防SQL注入、简化查询
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/prisma'
/**
* GET - 获取章节列表
*/
export async function GET(req: NextRequest) {
try {
const { searchParams } = new URL(req.url)
const partId = searchParams.get('partId')
const status = searchParams.get('status') || 'published'
const page = parseInt(searchParams.get('page') || '1')
const pageSize = parseInt(searchParams.get('pageSize') || '100')
// 构建 Prisma where 条件
const where: any = {}
if (partId) where.part_id = partId
if (status && status !== 'all') where.status = status as any
// 使用 Prisma 分页查询
const [results, total] = await Promise.all([
prisma.chapters.findMany({
where,
orderBy: { sort_order: 'asc' },
skip: (page - 1) * pageSize,
take: pageSize,
select: {
id: true,
part_id: true,
part_title: true,
chapter_id: true,
chapter_title: true,
section_title: true,
word_count: true,
is_free: true,
price: true,
sort_order: true,
status: true,
created_at: true,
updated_at: true
}
}),
prisma.chapters.count({ where })
])
return NextResponse.json({
success: true,
data: {
list: results.map(r => ({
...r,
price: Number(r.price)
})),
total,
page,
pageSize,
totalPages: Math.ceil(total / pageSize)
}
})
} catch (error) {
console.error('[Chapters API] 获取列表失败:', error)
return NextResponse.json(
{ success: false, error: '获取章节列表失败' },
{ status: 500 }
)
}
}
/**
* POST - 新增章节
*/
export async function POST(req: NextRequest) {
try {
const body = await req.json()
const {
id, partId, partTitle, chapterId, chapterTitle, sectionTitle,
content, wordCount, isFree, price, sortOrder, status
} = body
if (!id || !partId || !chapterId) {
return NextResponse.json(
{ success: false, error: '缺少必要字段' },
{ status: 400 }
)
}
// 使用 Prisma 创建章节
const chapter = await prisma.chapters.create({
data: {
id,
part_id: partId,
part_title: partTitle || '',
chapter_id: chapterId,
chapter_title: chapterTitle || '',
section_title: sectionTitle || '',
content: content || '',
word_count: wordCount || 0,
is_free: isFree || false,
price: price || 1,
sort_order: sortOrder || 0,
status: (status as any) || 'published'
}
})
return NextResponse.json({
success: true,
message: '章节创建成功',
data: { ...chapter, price: Number(chapter.price) }
})
} catch (error: any) {
console.error('[Chapters API] 创建失败:', error)
if (error.code === 'P2002') {
return NextResponse.json(
{ success: false, error: '章节ID已存在' },
{ status: 400 }
)
}
return NextResponse.json(
{ success: false, error: '创建章节失败' },
{ status: 500 }
)
}
}
/**
* PUT - 更新章节
*/
export async function PUT(req: NextRequest) {
try {
const body = await req.json()
const { id, ...updateData } = body
if (!id) {
return NextResponse.json(
{ success: false, error: '缺少章节ID' },
{ status: 400 }
)
}
// 构建更新数据
const data: any = { updated_at: new Date() }
if (updateData.partTitle !== undefined) data.part_title = updateData.partTitle
if (updateData.chapterTitle !== undefined) data.chapter_title = updateData.chapterTitle
if (updateData.sectionTitle !== undefined) data.section_title = updateData.sectionTitle
if (updateData.content !== undefined) data.content = updateData.content
if (updateData.wordCount !== undefined) data.word_count = updateData.wordCount
if (updateData.isFree !== undefined) data.is_free = updateData.isFree
if (updateData.price !== undefined) data.price = updateData.price
if (updateData.sortOrder !== undefined) data.sort_order = updateData.sortOrder
if (updateData.status !== undefined) data.status = updateData.status
// 使用 Prisma 更新章节
const chapter = await prisma.chapters.update({
where: { id },
data
})
return NextResponse.json({
success: true,
message: '章节更新成功',
data: { ...chapter, price: Number(chapter.price) }
})
} catch (error: any) {
console.error('[Chapters API] 更新失败:', error)
if (error.code === 'P2025') {
return NextResponse.json(
{ success: false, error: '章节不存在' },
{ status: 404 }
)
}
return NextResponse.json(
{ success: false, 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(
{ success: false, error: '缺少章节ID' },
{ status: 400 }
)
}
// 使用 Prisma 删除章节
await prisma.chapters.delete({
where: { id }
})
return NextResponse.json({
success: true,
message: '章节删除成功'
})
} catch (error: any) {
console.error('[Chapters API] 删除失败:', error)
if (error.code === 'P2025') {
return NextResponse.json(
{ success: false, error: '章节不存在' },
{ status: 404 }
)
}
return NextResponse.json(
{ success: false, error: '删除章节失败' },
{ status: 500 }
)
}
}