feat: 我的页整合扫一扫/设置与提现、all-chapters去重、内容上传API、文档与后台登录

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
卡若
2026-02-20 18:50:16 +08:00
parent 09fb67d2af
commit 0e4baa4b7f
27 changed files with 1526 additions and 347 deletions

View File

@@ -146,13 +146,40 @@ export async function GET(request: NextRequest) {
}
// 列出所有章节(不含内容)
// 优先从数据库读取,确保新建章节能立即显示
if (action === 'list') {
const sectionsFromDb = new Map<string, any>()
try {
const rows = await query(`
SELECT id, part_id, part_title, chapter_id, chapter_title, section_title,
price, is_free, content
FROM chapters ORDER BY part_id, chapter_id, id
`) as any[]
if (rows && rows.length > 0) {
for (const r of rows) {
sectionsFromDb.set(r.id, {
id: r.id,
title: r.section_title || '',
price: r.price ?? 1,
isFree: !!r.is_free,
partId: r.part_id || 'part-1',
partTitle: r.part_title || '',
chapterId: r.chapter_id || 'chapter-1',
chapterTitle: r.chapter_title || '',
filePath: ''
})
}
}
} catch (e) {
console.log('[Book API] list 从数据库读取失败,回退到 bookData:', (e as Error).message)
}
// 合并:以数据库为准,数据库没有的用 bookData 补
const sections: any[] = []
for (const part of bookData) {
for (const chapter of part.chapters) {
for (const section of chapter.sections) {
sections.push({
const dbRow = sectionsFromDb.get(section.id)
sections.push(dbRow || {
id: section.id,
title: section.title,
price: section.price,
@@ -163,14 +190,25 @@ export async function GET(request: NextRequest) {
chapterTitle: chapter.title,
filePath: section.filePath
})
sectionsFromDb.delete(section.id)
}
}
}
// 数据库有但 bookData 没有的(新建章节)
for (const [, v] of sectionsFromDb) {
sections.push(v)
}
// 按 id 去重,避免数据库重复或合并逻辑导致同一文章出现多次
const seen = new Set<string>()
const deduped = sections.filter((s) => {
if (seen.has(s.id)) return false
seen.add(s.id)
return true
})
return NextResponse.json({
success: true,
sections,
total: sections.length
sections: deduped,
total: deduped.length
})
}
@@ -324,7 +362,7 @@ export async function POST(request: NextRequest) {
export async function PUT(request: NextRequest) {
try {
const body = await request.json()
const { id, title, content, price, saveToFile = true } = body
const { id, title, content, price, saveToFile = true, partId, chapterId, partTitle, chapterTitle, isFree } = body
if (!id) {
return NextResponse.json({
@@ -334,28 +372,40 @@ export async function PUT(request: NextRequest) {
}
const sectionInfo = getSectionInfo(id)
const finalPartId = partId || sectionInfo?.partId || 'part-1'
const finalPartTitle = partTitle || sectionInfo?.partTitle || '未分类'
const finalChapterId = chapterId || sectionInfo?.chapterId || 'chapter-1'
const finalChapterTitle = chapterTitle || sectionInfo?.chapterTitle || '未分类'
const finalPrice = price ?? sectionInfo?.section?.price ?? 1
const finalIsFree = isFree ?? sectionInfo?.section?.isFree ?? false
// 更新数据库
// 更新数据库(含新建章节)
try {
await query(`
INSERT INTO chapters (id, part_id, part_title, chapter_id, chapter_title, section_title, content, word_count, price, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'published')
INSERT INTO chapters (id, part_id, part_title, chapter_id, chapter_title, section_title, content, word_count, is_free, price, status)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'published')
ON DUPLICATE KEY UPDATE
part_id = VALUES(part_id),
part_title = VALUES(part_title),
chapter_id = VALUES(chapter_id),
chapter_title = VALUES(chapter_title),
section_title = VALUES(section_title),
content = VALUES(content),
word_count = VALUES(word_count),
is_free = VALUES(is_free),
price = VALUES(price),
updated_at = CURRENT_TIMESTAMP
`, [
id,
sectionInfo?.partId || 'part-1',
sectionInfo?.partTitle || '未分类',
sectionInfo?.chapterId || 'chapter-1',
sectionInfo?.chapterTitle || '未分类',
title || sectionInfo?.section.title || '',
finalPartId,
finalPartTitle,
finalChapterId,
finalChapterTitle,
title || sectionInfo?.section?.title || '',
content || '',
(content || '').length,
price ?? sectionInfo?.section.price ?? 1
finalIsFree,
finalPrice
])
} catch (e) {
console.error('[Book API] 更新数据库失败:', e)