数据模型
Narrator Android · Room 数据库 + 文件持久化双轨 · 5 大实体
Narrator 的数据存储采用 双轨制:
① 结构化数据用 Room(剧本 / AI 服务商 / 对话消息三表);
② 大纲 / 章节推演记录使用文件系统(每个剧本一套 outline/{scriptId}/ 目录树)。
数据层位于 com.carrots.narrator.model,由多个 Repository 仓库对外暴露。
1. 整体结构
2. Room 数据库
2.1 AppDatabase 单例
文件:model/AppDatabase.java 数据库:carrot_narrator.db 版本:4
fallbackToDestructiveMigration()——若 schema 变更未提供迁移路径,将丢弃旧库重建(开发期方便但生产需谨慎)。
2.2 scripts 表 — ScriptEntity
对应:Web types/script.ts ScriptItem
| 字段 | 类型 | 说明 |
|---|---|---|
id | String(PK) | 主键 |
title | String | 标题 |
description | String | 描述 |
status | String | "active" 进行中 / "draft" 草稿 |
scriptGroup | String | 分组(悬疑 / 科幻 / 奇幻 等) |
author | String | 作者 |
createdAt | long | 创建时间戳(毫秒) |
ScriptEntity 提供结构与 Room 通路;当前 UI 层(ScriptFragment)主要通过
ScriptRepository(filesDir/scripts.json)管理剧本,仓库内含 5 个预置示例剧本
(从 assets/default_scripts.json 加载)。Script POJO 充当 UI 数据载体。
2.3 ai_providers 表 — AIProviderEntity
对应:Web types/ai.ts AIProvider
| 字段 | 类型 | 说明 |
|---|---|---|
id | String(PK) | "openai" / "deepseek" / "custom_xxx" |
name | String | 显示名称 |
apiUrl | String | API 地址(https://api.openai.com/v1 等) |
apiKey | String | Bearer Token |
modelName | String | 默认模型名(注入 chat/completions 的 model 字段) |
timeoutSeconds | int | 超时秒数 |
isDefault | boolean | 是否默认选中 |
2.4 dialogues 表 — DialogueEntity
对应:Web types/dialogue.ts DialogueMsg 索引:@Index("scriptId")
| 字段 | 类型 | 说明 |
|---|---|---|
id | long(PK·自增) | 主键 |
scriptId | String | 所属剧本 / 会话标识(无外键约束,对话可独立于剧本存在) |
label | String | "M_001" / "M_002" ... 序列标签 |
role | String | director 导演 | narrator 旁白 | character 角色 | user 用户 |
sender | String | 角色名称 |
content | String | 消息内容 |
reasoningContent | String? | AI 思考过程(如 deepseek-reasoner 的 reasoning_content) |
directive | String? | 导演指令 JSON(仅导演角色,其余为 null) |
timestamp | long | 消息时间戳(毫秒) |
3. Script POJO
model/Script.java —— UI 层剧本载体,含两个构造:6 参(创建时间取 SimpleDateFormat.getDateInstance().format(now))与 7 参(从 JSON 反序列化时保留原始 createdAt)。
生成规则:ScriptRepository.add(...) 用自增 nextId 生成 S_%05d 格式 ID 并置顶插入;getGrouped() 按 group 分组供 ScriptFragment 渲染。
4. 文件持久化大纲
文件:model/OutlineRepository.java —— 基于文件系统分卷 / 章节存储,对应 Web 端大纲目录树。
4.1 outline.json 格式
4.2 settings.json / prompts.json
4.3 章节推演记录 {chapterId}.json
每章独立 JSON 文件,保存该章的 messages 数组(对话流)与 state(推演状态),供 DeductionFragment 加载续演。
5. 其它仓库
| 仓库 | 承载 | 说明 |
|---|---|---|
TrashRepository | 回收站 | TrashItem 列表;ScriptRepository.remove(id) 会先移入此处(restore(...) 可恢复到列表首位) |
ScriptCharRepository | 剧本角色 | 按 scriptId 管理 CharData(性格 / 目标 / 关系 / 能力 / temperature / status) |
ScriptSettingsRepository | 剧本设置 | 剧本级配置项(演绎参数等) |
GroupRepository | 分组 | 分组命名 / 重命名(重命名时联动 ScriptRepository.renameGroup) |
DialogueRepository | 对话历史 | 聚合跨剧本对话(Room dialogues 表 + 可选文件缓存) |
AIProviderRepository | AI 服务商 | 封装 AIProviderDao,配合 AiService 使用 |
6. 演绎角色数据 CharData
DeductionFragment 内部角色数据结构(运行期聚合,非 Room 实体):
| 字段 | 类型 | 说明 |
|---|---|---|
id / name / avatar | String | 标识 / 名号 / 头像 |
player | String | "character" AI 角色自动生成 | "system" 人类角色等待输入 |
personality / goal / relationships / abilities | String | 人格 / 目标 / 关系 / 能力(拼入角色 prompt) |
temperature | double | 角色级采样温度,传入 AiService.sendChatStream(..., temperature, ...) |
status | String | 在线 / 不在线 / 连线 |
7. 默认配置体系
util/Defaults.java 从 res/values/defaults.xml 统一取值,模块通过 Defaults 取默认值,避免硬编码散落: