小说生成系统加「一键重置」:我们如何避开删项目重建的坑
你有没有遇到过这种情况:用 AI 一键生成了一整本小说,觉得整体方向偏了,想彻底清空当前项目的所有提示词、章节、状态、元素从头来,结果翻遍系统发现要么只能逐个删章节、删提示词,要么只能删掉整个项目重建——重建之后原来的项目 ID、分享链接、关联的生成记录全没了,之前所有的积累直接清零。
最近我在 trae-novel 里就撞上这个需求:用户想要一个「一键重置」按钮,清空当前项目所有内容后,配合现有的一键生成功能重新跑流程,不用反复手工操作。整个调研和落地踩了不少坑,也摸出一套最小改动的实现思路,记下来。
先搞清楚:系统里到底有没有「一键重置」
接到需求我先做了全量能力调研,发现系统其实已有部分相关能力:之前上线的「创作中心 - 提示词生成」模块的 4 个页签,已经支持一键删除当前环节的提示词和对应 JSON 文件,属于局部重置。
但调研到整体项目层,结论很明确:当前没有「一键重置项目并直接再生成」的完整功能。如果硬拼替代方案,只能走「删除项目 → 新建项目 → 重新填基础信息」的路径,而这个方案会直接丢失原项目的 project_id,所有关联的分享链接、用户收藏、历史生成记录都会失效,根本不是用户要的「同项目重置」。
我还找了个真实案例验证:之前有个作者用系统生成了 3 版试读本,原项目 ID 已经分享给 2000 多个读者,如果用删除重建的方案重置,原来的分享链接会全部 404,读者收藏的内容也全找不回来,损失不可逆。
为什么「拼凑方案」行不通
核心问题有两个。一是现有能力碎片化:局部重置只能处理单个模块的数据,提示词、章节、项目状态、元素配置、Redis 缓存分散在不同表和服务里,没有统一清理入口。二是没有适配「同项目重置」的接口:当前只有局部删除接口,没有「清空项目所有业务数据但保留项目主记录」的接口,根本拼不出完整重置流程。如果直接用删除项目的方式,相当于把整个项目从数据库抹掉,project_id 作为主键被删除后,所有关联数据都会断裂,完全不符合需求。
改动最小的实现路径
调研清楚后,我给出改动最小的方案,全程不需要改项目主表结构,风险极低:
后端新增 POST /api/projects/{project_id}/reset 接口,核心逻辑是:先校验项目存在,然后只删除和项目关联的业务数据(提示词、章节、项目状态、元素配置等),清空对应的 Redis 缓存,完全保留项目的主记录和 project_id,不会丢失任何关联数据。
前端在项目列表 / 详情页新增「一键重置」按钮,搭配二次确认弹窗,避免误触。
可选扩展:重置成功后,自动调用现有的 POST /api/pipeline/{project_id} 一键生成接口,直接启动生成流程,不用用户手动操作。
后端的重置逻辑只需要处理业务数据清理,不碰主表:
// 后端重置接口示意,仅作逻辑参考,不涉及真实内部代码
async function resetProject(projectId) {
// 1. 校验项目存在
const project = await db.projects.findUnique({ where: { id: projectId } });
if (!project) throw new Error('项目不存在');
// 2. 清空关联业务数据
await Promise.all([
db.prompts.deleteMany({ where: { projectId } }),
db.chapters.deleteMany({ where: { projectId } }),
db.elements.deleteMany({ where: { projectId } }),
db.projectStatus.deleteMany({ where: { projectId } }),
]);
// 3. 清空对应Redis缓存
await redis.del(`project:${projectId}:*`);
// 4. 保留项目主记录,返回成功
return { code: 200, msg: '重置成功' };
}
前端按钮逻辑也很简单,只处理成功 / 失败状态:
<!-- 前端按钮示意,仅作逻辑参考 -->
<template>
<button @click="handleReset(project.id)" class="reset-btn">一键重置并重新生成</button>
</template>
<script setup>
const handleReset = async (projectId) => {
// 二次确认,避免误操作
if (!confirm('确定要清空当前项目的所有内容并重新生成吗?此操作不可恢复')) return;
const res = await fetch(`/api/projects/${projectId}/reset`, { method: 'POST' });
if (res.ok) {
// 可选:重置成功后自动启动生成
await fetch(`/api/pipeline/${projectId}`, { method: 'POST' });
ElMessage.success('重置成功,已启动生成');
} else {
ElMessage.error('重置失败,请重试');
}
}
</script>
几个容易踩的点
我一开始也想过用删除项目重建的方案,直到验证了分享链接失效才意识到:project_id 是项目的核心标识,所有关联数据都依赖它,绝不能因为重置功能就删掉主记录。
还有两点:所有破坏性操作一定要加二次确认,最好再加操作日志方便回溯;「重置后自动生成」别做成默认选项,让用户自己决定要不要重置完直接跑生成,免得浪费算力。
做这类「全量重置」的破坏性功能,别上来就想做最全的方案,优先做最小可行版本再逐步扩展。全量重置优先选「保留主键、清业务数据」,比删除重建成本低,还能完全避免关联数据丢失;涉及用户数据的破坏性操作,确认环节和操作日志一定要上,把误操作风险压到最低;功能迭代先跑通核心链路,再叠加扩展能力,别一开始就求大而全。

浙公网安备 33010602011771号