fix: 修复章节API的Next.js 16兼容性问题
- 更新chapter/[id]/route.ts使用Promise params (Next.js 16要求) - 删除过时的app/api/db目录下的旧API文件(bookDB/userDB等不存在的导出) - 添加部署脚本deploy-to-server.sh - 添加章节迁移脚本migrate-chapters-to-db.ts
This commit is contained in:
@@ -1,194 +0,0 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { bookDB } from '@/lib/db'
|
||||
import { bookData } from '@/lib/book-data'
|
||||
import fs from 'fs/promises'
|
||||
import path from 'path'
|
||||
|
||||
// 获取章节
|
||||
export async function GET(req: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const id = searchParams.get('id')
|
||||
const action = searchParams.get('action')
|
||||
|
||||
// 导出所有章节
|
||||
if (action === 'export') {
|
||||
const data = await bookDB.exportAll()
|
||||
return new NextResponse(data, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Disposition': 'attachment; filename=book_sections.json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 从文件系统读取章节内容
|
||||
if (action === 'read' && id) {
|
||||
// 查找章节文件路径
|
||||
let filePath = ''
|
||||
for (const part of bookData) {
|
||||
for (const chapter of part.chapters) {
|
||||
const section = chapter.sections.find(s => s.id === id)
|
||||
if (section) {
|
||||
filePath = section.filePath
|
||||
break
|
||||
}
|
||||
}
|
||||
if (filePath) break
|
||||
}
|
||||
|
||||
if (!filePath) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: '章节不存在'
|
||||
}, { status: 404 })
|
||||
}
|
||||
|
||||
const fullPath = path.join(process.cwd(), filePath)
|
||||
const content = await fs.readFile(fullPath, 'utf-8')
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
section: { id, filePath, content }
|
||||
})
|
||||
}
|
||||
|
||||
if (id) {
|
||||
const section = await bookDB.getSection(id)
|
||||
return NextResponse.json({ success: true, section })
|
||||
}
|
||||
|
||||
const sections = await bookDB.getAllSections()
|
||||
return NextResponse.json({ success: true, sections })
|
||||
} catch (error: any) {
|
||||
console.error('Get book sections error:', error)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: error.message
|
||||
}, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
// 创建或更新章节
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const body = await req.json()
|
||||
const { action, data } = body
|
||||
|
||||
// 导入章节
|
||||
if (action === 'import') {
|
||||
const count = await bookDB.importSections(JSON.stringify(data))
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: `成功导入 ${count} 个章节`
|
||||
})
|
||||
}
|
||||
|
||||
// 同步book-data到数据库
|
||||
if (action === 'sync') {
|
||||
let count = 0
|
||||
let sortOrder = 0
|
||||
|
||||
for (const part of bookData) {
|
||||
for (const chapter of part.chapters) {
|
||||
for (const section of chapter.sections) {
|
||||
sortOrder++
|
||||
const existing = await bookDB.getSection(section.id)
|
||||
|
||||
// 读取文件内容
|
||||
let content = ''
|
||||
try {
|
||||
const fullPath = path.join(process.cwd(), section.filePath)
|
||||
content = await fs.readFile(fullPath, 'utf-8')
|
||||
} catch (e) {
|
||||
console.warn(`Cannot read file: ${section.filePath}`)
|
||||
}
|
||||
|
||||
if (existing) {
|
||||
await bookDB.updateSection(section.id, {
|
||||
title: section.title,
|
||||
content,
|
||||
price: section.price,
|
||||
is_free: section.isFree
|
||||
})
|
||||
} else {
|
||||
await bookDB.createSection({
|
||||
id: section.id,
|
||||
part_id: part.id,
|
||||
chapter_id: chapter.id,
|
||||
title: section.title,
|
||||
content,
|
||||
price: section.price,
|
||||
is_free: section.isFree,
|
||||
sort_order: sortOrder
|
||||
})
|
||||
}
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: `成功同步 ${count} 个章节到数据库`
|
||||
})
|
||||
}
|
||||
|
||||
// 创建单个章节
|
||||
const section = await bookDB.createSection(data)
|
||||
return NextResponse.json({ success: true, section })
|
||||
} catch (error: any) {
|
||||
console.error('Create/Import book section error:', error)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: error.message
|
||||
}, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
// 更新章节
|
||||
export async function PUT(req: NextRequest) {
|
||||
try {
|
||||
const body = await req.json()
|
||||
const { id, ...updates } = body
|
||||
|
||||
if (!id) {
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: '缺少章节ID'
|
||||
}, { status: 400 })
|
||||
}
|
||||
|
||||
// 如果要保存到文件系统
|
||||
if (updates.content && updates.saveToFile) {
|
||||
// 查找章节文件路径
|
||||
let filePath = ''
|
||||
for (const part of bookData) {
|
||||
for (const chapter of part.chapters) {
|
||||
const section = chapter.sections.find(s => s.id === id)
|
||||
if (section) {
|
||||
filePath = section.filePath
|
||||
break
|
||||
}
|
||||
}
|
||||
if (filePath) break
|
||||
}
|
||||
|
||||
if (filePath) {
|
||||
const fullPath = path.join(process.cwd(), filePath)
|
||||
await fs.writeFile(fullPath, updates.content, 'utf-8')
|
||||
}
|
||||
}
|
||||
|
||||
await bookDB.updateSection(id, updates)
|
||||
const section = await bookDB.getSection(id)
|
||||
|
||||
return NextResponse.json({ success: true, section })
|
||||
} catch (error: any) {
|
||||
console.error('Update book section error:', error)
|
||||
return NextResponse.json({
|
||||
success: false,
|
||||
error: error.message
|
||||
}, { status: 500 })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user