3c9b65d982
- Nuxt 4 + Nuxt UI 4 + AI SDK 7 + Drizzle/SQLite - 主编规划大纲与章节简报、选派作家;作家流式写入章节文件并实时推送前端 - 逐章确认模式(默认)与自动模式;摘要与故事记忆 - 酒馆角色卡(PNG/JSON,V1-V3)与世界书导入 - 自定义最高优先级系统提示词、审稿/修改/多版本、任务日志与提示词检视 - 模拟 LLM 服务与端到端测试脚本 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
24 lines
1.2 KiB
TypeScript
24 lines
1.2 KiB
TypeScript
/** 导出整本小说:format=txt|md,scope=approved|all */
|
||
export default defineEventHandler(async (event) => {
|
||
const project = getProject(param(event))
|
||
const q = getQuery(event)
|
||
const format = q.format === 'md' ? 'md' : 'txt'
|
||
const scope = q.scope === 'approved' ? 'approved' : 'all'
|
||
const chapters = listChapters(project.id).filter(c => c.activeVersionId && (scope === 'all' || c.status === 'approved'))
|
||
|
||
const parts: string[] = []
|
||
parts.push(format === 'md' ? `# ${project.title}` : project.title)
|
||
if (project.description) parts.push(project.description)
|
||
for (const c of chapters) {
|
||
const v = getVersion(c.activeVersionId)
|
||
if (!v) continue
|
||
const body = stripHeading(await readChapterFile(v.filePath)).trim()
|
||
const heading = `第${c.index}章 ${c.title}`
|
||
parts.push(format === 'md' ? `## ${heading}\n\n${body}` : `${heading}\n\n${body}`)
|
||
}
|
||
const filename = encodeURIComponent(`${project.title}.${format}`)
|
||
setHeader(event, 'Content-Type', format === 'md' ? 'text/markdown; charset=utf-8' : 'text/plain; charset=utf-8')
|
||
setHeader(event, 'Content-Disposition', `attachment; filename*=UTF-8''${filename}`)
|
||
return parts.join('\n\n\n')
|
||
})
|