Files
soul/app/api/db/book/route.ts
卡若 b60edb3d47 feat: 完整重构小程序匹配功能 + 修复UI对齐 + 文章数据API
主要更新:
1. 按H5网页端完全重构匹配功能(match页面)
   - 4种匹配类型: 创业合伙/资源对接/导师顾问/团队招募
   - 资源对接等类型弹出手机号/微信号输入框
   - 去掉重新匹配按钮,改为返回按钮

2. 修复所有卡片对齐和宽度问题
   - 目录页附录卡片居中
   - 首页阅读进度卡片满宽度
   - 我的页面菜单卡片对齐
   - 推广中心分享卡片统一宽度

3. 修复目录页图标和文字对齐
   - section-icon固定40rpx宽高
   - section-title与图标垂直居中

4. 更新真实完整文章标题(62篇)
   - 从book目录读取真实markdown文件名
   - 替换之前的简化标题

5. 新增文章数据API
   - /api/db/chapters - 获取完整书籍结构
   - 支持按ID获取单篇文章内容
2026-01-21 15:49:12 +08:00

195 lines
5.3 KiB
TypeScript

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