2026-01-14 12:50:00 +08:00
|
|
|
|
// app/api/book/chapter/[id]/route.ts
|
2026-01-25 09:57:21 +08:00
|
|
|
|
// 获取章节详情 - 从数据库读取,支持小程序和Web端
|
|
|
|
|
|
// 更新: 2026-01-25 改为从MySQL数据库读取章节内容
|
2026-01-14 12:50:00 +08:00
|
|
|
|
|
|
|
|
|
|
import { NextRequest, NextResponse } from 'next/server'
|
2026-01-25 09:57:21 +08:00
|
|
|
|
import { query } from '@/lib/db'
|
2026-01-14 12:50:00 +08:00
|
|
|
|
|
2026-01-25 09:57:21 +08:00
|
|
|
|
// 免费章节列表
|
|
|
|
|
|
const FREE_CHAPTERS = ['preface', 'epilogue', '1.1', 'appendix-1', 'appendix-2', 'appendix-3']
|
2026-01-25 09:27:32 +08:00
|
|
|
|
|
2026-01-14 12:50:00 +08:00
|
|
|
|
export async function GET(
|
|
|
|
|
|
req: NextRequest,
|
2026-01-25 10:36:30 +08:00
|
|
|
|
{ params }: { params: Promise<{ id: string }> }
|
2026-01-14 12:50:00 +08:00
|
|
|
|
) {
|
|
|
|
|
|
try {
|
2026-01-25 10:36:30 +08:00
|
|
|
|
const { id: chapterId } = await params
|
2026-01-25 09:27:32 +08:00
|
|
|
|
console.log('[Chapter API] 请求章节:', chapterId)
|
|
|
|
|
|
|
2026-01-25 09:57:21 +08:00
|
|
|
|
// 从数据库查询章节
|
|
|
|
|
|
const results = await query(
|
|
|
|
|
|
`SELECT id, part_id, part_title, chapter_id, chapter_title, section_title,
|
|
|
|
|
|
content, word_count, is_free, price, sort_order, status, updated_at
|
|
|
|
|
|
FROM chapters
|
|
|
|
|
|
WHERE id = ? AND status = 'published'`,
|
|
|
|
|
|
[chapterId]
|
|
|
|
|
|
) as any[]
|
2026-01-25 09:27:32 +08:00
|
|
|
|
|
2026-01-25 09:57:21 +08:00
|
|
|
|
if (!results || results.length === 0) {
|
2026-01-25 09:27:32 +08:00
|
|
|
|
console.log('[Chapter API] 章节不存在:', chapterId)
|
2026-01-14 12:50:00 +08:00
|
|
|
|
return NextResponse.json(
|
2026-01-25 09:27:32 +08:00
|
|
|
|
{ error: '章节不存在', success: false },
|
2026-01-14 12:50:00 +08:00
|
|
|
|
{ status: 404 }
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
2026-01-25 09:57:21 +08:00
|
|
|
|
|
|
|
|
|
|
const chapter = results[0]
|
|
|
|
|
|
const isFree = chapter.is_free || FREE_CHAPTERS.includes(chapterId)
|
|
|
|
|
|
|
|
|
|
|
|
console.log('[Chapter API] 返回章节内容:', chapterId, '长度:', chapter.content?.length || 0)
|
2026-01-25 09:27:32 +08:00
|
|
|
|
|
|
|
|
|
|
// 返回小程序兼容的格式
|
|
|
|
|
|
return NextResponse.json({
|
|
|
|
|
|
success: true,
|
2026-01-25 09:57:21 +08:00
|
|
|
|
id: chapter.id,
|
|
|
|
|
|
title: chapter.section_title,
|
|
|
|
|
|
content: chapter.content,
|
|
|
|
|
|
partTitle: chapter.part_title,
|
|
|
|
|
|
chapterTitle: chapter.chapter_title,
|
|
|
|
|
|
sectionTitle: chapter.section_title,
|
|
|
|
|
|
words: chapter.word_count,
|
|
|
|
|
|
updateTime: chapter.updated_at,
|
2026-01-25 09:27:32 +08:00
|
|
|
|
isFree,
|
2026-01-25 09:57:21 +08:00
|
|
|
|
price: chapter.price,
|
2026-01-25 09:27:32 +08:00
|
|
|
|
needPurchase: !isFree
|
|
|
|
|
|
})
|
2026-01-14 12:50:00 +08:00
|
|
|
|
} catch (error) {
|
2026-01-25 09:27:32 +08:00
|
|
|
|
console.error('[Chapter API] 获取章节失败:', error)
|
2026-01-14 12:50:00 +08:00
|
|
|
|
return NextResponse.json(
|
2026-01-25 09:27:32 +08:00
|
|
|
|
{ error: '获取章节失败', success: false },
|
2026-01-14 12:50:00 +08:00
|
|
|
|
{ status: 500 }
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|