/** * 内容上传 API * 供科室/Skill 直接上传单篇文章到书籍内容,写入 chapters 表 * 字段:标题、定价、内容、格式、插入内容中的图片(URL 列表) */ import { NextRequest, NextResponse } from 'next/server' import { query } from '@/lib/db' function slug(id: string): string { return id.replace(/\s+/g, '-').replace(/[^\w\u4e00-\u9fa5-]/g, '').slice(0, 30) || 'section' } export async function POST(request: NextRequest) { try { const body = await request.json() const { title, price = 1, content = '', format = 'markdown', images = [], partId = 'part-1', partTitle = '真实的人', chapterId = 'chapter-1', chapterTitle = '未分类', isFree = false, sectionId } = body if (!title || typeof title !== 'string') { return NextResponse.json( { success: false, error: '标题 title 不能为空' }, { status: 400 } ) } // 若内容中含占位符 {{image_0}} {{image_1}},用 images 数组替换 let finalContent = typeof content === 'string' ? content : '' if (Array.isArray(images) && images.length > 0) { images.forEach((url: string, i: number) => { finalContent = finalContent.replace( new RegExp(`\\{\\{image_${i}\\}\\}`, 'g'), url.startsWith('http') ? `![图${i + 1}](${url})` : url ) }) } // 未替换的占位符去掉 finalContent = finalContent.replace(/\{\{image_\d+\}\}/g, '') const wordCount = (finalContent || '').length const id = sectionId || `upload.${slug(title)}.${Date.now()}` await query( `INSERT INTO chapters (id, part_id, part_title, chapter_id, chapter_title, section_title, content, word_count, is_free, price, sort_order, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 9999, 'published') ON DUPLICATE KEY UPDATE 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, partId, partTitle, chapterId, chapterTitle, title, finalContent, wordCount, !!isFree, Number(price) || 1 ] ) return NextResponse.json({ success: true, id, message: '内容已上传并写入 chapters 表', title, price: Number(price) || 1, isFree: !!isFree, wordCount }) } catch (error) { console.error('[Content Upload]', error) return NextResponse.json( { success: false, error: '上传失败: ' + (error as Error).message }, { status: 500 } ) } }