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:
卡若
2026-01-25 10:36:30 +08:00
parent 263da246c9
commit 153b8d9795
11 changed files with 300 additions and 656 deletions

View File

@@ -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 })
}
}

View File

@@ -1,96 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { distributionDB, purchaseDB } from '@/lib/db'
// 获取分销数据
export async function GET(req: NextRequest) {
try {
const { searchParams } = new URL(req.url)
const type = searchParams.get('type')
const referrerId = searchParams.get('referrer_id')
// 获取佣金记录
if (type === 'commissions') {
const commissions = await distributionDB.getAllCommissions()
return NextResponse.json({ success: true, commissions })
}
// 获取指定推荐人的绑定
if (referrerId) {
const bindings = await distributionDB.getBindingsByReferrer(referrerId)
return NextResponse.json({ success: true, bindings })
}
// 获取所有绑定关系
const bindings = await distributionDB.getAllBindings()
return NextResponse.json({ success: true, bindings })
} catch (error: any) {
console.error('Get distribution data 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 { type, data } = body
if (type === 'binding') {
const binding = await distributionDB.createBinding({
id: `binding_${Date.now()}`,
...data,
bound_at: new Date().toISOString(),
expires_at: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), // 30天有效期
status: 'active'
})
return NextResponse.json({ success: true, binding })
}
if (type === 'commission') {
const commission = await distributionDB.createCommission({
id: `commission_${Date.now()}`,
...data,
status: 'pending'
})
return NextResponse.json({ success: true, commission })
}
return NextResponse.json({
success: false,
error: '未知操作类型'
}, { status: 400 })
} catch (error: any) {
console.error('Create distribution record 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, status } = body
if (!id) {
return NextResponse.json({
success: false,
error: '缺少记录ID'
}, { status: 400 })
}
await distributionDB.updateBindingStatus(id, status)
return NextResponse.json({ success: true })
} catch (error: any) {
console.error('Update distribution status error:', error)
return NextResponse.json({
success: false,
error: error.message
}, { status: 500 })
}
}

View File

@@ -1,106 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { purchaseDB, userDB, distributionDB } from '@/lib/db'
// 获取购买记录
export async function GET(req: NextRequest) {
try {
const { searchParams } = new URL(req.url)
const userId = searchParams.get('user_id')
if (userId) {
const purchases = await purchaseDB.getByUserId(userId)
return NextResponse.json({ success: true, purchases })
}
const purchases = await purchaseDB.getAll()
return NextResponse.json({ success: true, purchases })
} catch (error: any) {
console.error('Get purchases 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 {
user_id,
type,
section_id,
section_title,
amount,
payment_method,
referral_code
} = body
// 创建购买记录
const purchase = await purchaseDB.create({
id: `purchase_${Date.now()}`,
user_id,
type,
section_id,
section_title,
amount,
payment_method,
referral_code,
referrer_earnings: 0,
status: 'completed'
})
// 更新用户购买状态
if (type === 'fullbook') {
await userDB.update(user_id, { has_full_book: true })
}
// 处理分销佣金
if (referral_code) {
// 查找推荐人
const users = await userDB.getAll()
const referrer = users.find((u: any) => u.referral_code === referral_code)
if (referrer) {
const commissionRate = 0.9 // 90% 佣金
const commissionAmount = amount * commissionRate
// 查找有效的绑定关系
const binding = await distributionDB.getActiveBindingByReferee(user_id)
if (binding) {
// 创建佣金记录
await distributionDB.createCommission({
id: `commission_${Date.now()}`,
binding_id: binding.id,
referrer_id: referrer.id,
referee_id: user_id,
order_id: purchase.id,
amount,
commission_rate: commissionRate * 100,
commission_amount: commissionAmount,
status: 'pending'
})
// 更新推荐人收益
await userDB.update(referrer.id, {
earnings: (referrer.earnings || 0) + commissionAmount,
pending_earnings: (referrer.pending_earnings || 0) + commissionAmount
})
// 更新购买记录的推荐人收益
purchase.referrer_earnings = commissionAmount
}
}
}
return NextResponse.json({ success: true, purchase })
} catch (error: any) {
console.error('Create purchase error:', error)
return NextResponse.json({
success: false,
error: error.message
}, { status: 500 })
}
}

View File

@@ -1,31 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { settingsDB } from '@/lib/db'
// 获取系统设置
export async function GET() {
try {
const settings = await settingsDB.get()
return NextResponse.json({ success: true, settings: settings?.data || null })
} catch (error: any) {
console.error('Get settings error:', error)
return NextResponse.json({
success: false,
error: error.message
}, { status: 500 })
}
}
// 保存系统设置
export async function POST(req: NextRequest) {
try {
const body = await req.json()
await settingsDB.update(body)
return NextResponse.json({ success: true, message: '设置已保存' })
} catch (error: any) {
console.error('Save settings error:', error)
return NextResponse.json({
success: false,
error: error.message
}, { status: 500 })
}
}

View File

@@ -1,114 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { userDB } from '@/lib/db'
// 获取所有用户
export async function GET(req: NextRequest) {
try {
const { searchParams } = new URL(req.url)
const id = searchParams.get('id')
const phone = searchParams.get('phone')
if (id) {
const user = await userDB.getById(id)
return NextResponse.json({ success: true, user })
}
if (phone) {
const user = await userDB.getByPhone(phone)
return NextResponse.json({ success: true, user })
}
const users = await userDB.getAll()
return NextResponse.json({ success: true, users })
} catch (error: any) {
console.error('Get users 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 { phone, nickname, password, referral_code, referred_by } = body
// 检查手机号是否已存在
const existing = await userDB.getByPhone(phone)
if (existing) {
return NextResponse.json({
success: false,
error: '该手机号已注册'
}, { status: 400 })
}
const user = await userDB.create({
id: `user_${Date.now()}`,
phone,
nickname,
password,
referral_code: referral_code || `REF${Date.now().toString(36).toUpperCase()}`,
referred_by
})
return NextResponse.json({ success: true, user })
} catch (error: any) {
console.error('Create user 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 })
}
await userDB.update(id, updates)
const user = await userDB.getById(id)
return NextResponse.json({ success: true, user })
} catch (error: any) {
console.error('Update user error:', error)
return NextResponse.json({
success: false,
error: error.message
}, { status: 500 })
}
}
// 删除用户
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 })
}
await userDB.delete(id)
return NextResponse.json({ success: true })
} catch (error: any) {
console.error('Delete user error:', error)
return NextResponse.json({
success: false,
error: error.message
}, { status: 500 })
}
}

View File

@@ -1,113 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { withdrawalDB, userDB } from '@/lib/db'
// 获取提现记录
export async function GET(req: NextRequest) {
try {
const { searchParams } = new URL(req.url)
const userId = searchParams.get('user_id')
if (userId) {
const withdrawals = await withdrawalDB.getByUserId(userId)
return NextResponse.json({ success: true, withdrawals })
}
const withdrawals = await withdrawalDB.getAll()
return NextResponse.json({ success: true, withdrawals })
} catch (error: any) {
console.error('Get withdrawals 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 { user_id, amount, method, account, name } = body
// 验证用户余额
const user = await userDB.getById(user_id)
if (!user) {
return NextResponse.json({
success: false,
error: '用户不存在'
}, { status: 404 })
}
if ((user.earnings || 0) < amount) {
return NextResponse.json({
success: false,
error: '余额不足'
}, { status: 400 })
}
// 创建提现记录
const withdrawal = await withdrawalDB.create({
id: `withdrawal_${Date.now()}`,
user_id,
amount,
method,
account,
name,
status: 'pending'
})
// 扣除用户余额,增加待提现金额
await userDB.update(user_id, {
earnings: (user.earnings || 0) - amount,
pending_earnings: (user.pending_earnings || 0) + amount
})
return NextResponse.json({ success: true, withdrawal })
} catch (error: any) {
console.error('Create withdrawal 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, status } = body
if (!id) {
return NextResponse.json({
success: false,
error: '缺少提现记录ID'
}, { status: 400 })
}
await withdrawalDB.updateStatus(id, status)
// 如果状态是已完成,更新用户的已提现金额
if (status === 'completed') {
const withdrawals = await withdrawalDB.getAll()
const withdrawal = withdrawals.find((w: any) => w.id === id)
if (withdrawal) {
const user = await userDB.getById(withdrawal.user_id)
if (user) {
await userDB.update(user.id, {
pending_earnings: (user.pending_earnings || 0) - withdrawal.amount,
withdrawn_earnings: (user.withdrawn_earnings || 0) + withdrawal.amount
})
}
}
}
return NextResponse.json({ success: true })
} catch (error: any) {
console.error('Update withdrawal status error:', error)
return NextResponse.json({
success: false,
error: error.message
}, { status: 500 })
}
}