Archived
8.6 KiB
8.6 KiB
新项目复用教程
假设你要开一个新仓库,做一个类似的"Flask + 互动剧本 + 人格测试"项目。本教程告诉你从这个老仓库拿什么、怎么拿、怎么改。
一、先搞清楚这个项目有哪几块可复用
| 模块 | 核心文件 | 能干嘛 |
|---|---|---|
| Flask 后端骨架 | app.py |
路由、API、SQLite、gzip 压缩、静态缓存 |
| 互动剧本引擎 | data/seed_story.json + desktop.js 中的 story 相关函数 |
读取 JSON 剧本 → 前端渲染场景文字 + 选项按钮 + 属性变化 |
| MathBTI 人格测试 | data/seed_mathbti.json + templates/mathbti.html + mathbti.css/js |
12 题测出 16 种结果,前端自包含可独立部署 |
| 卡片/抽卡系统 | desktop.js 中的 card/gacha 相关函数 |
16 张人物卡,读知识卡片攒抽卡次数,保底机制 |
| 内容构建脚本 | scripts/build_*.py |
用 Python dict 生成种子 JSON |
| Word 导出脚本 | scripts/export_*.py |
把人物设定导出为 docx |
| 小说/设定原稿 | docs/novel/*.txt |
纯文本,可直接喂给任何文本处理流程 |
二、新项目规划建议
场景 A:做一个新互动剧本项目(最常见)
你只需要:Flask 骨架 + 剧本引擎 + 剧本数据。
new-project/
├── app.py # 从老项目复制,改掉路径和 API key
├── data/
│ └── my_story.json # 你的新剧本(照着老格式写)
├── templates/
│ └── index.html # 从 desktop.html 简化,或自己写
├── static/
│ ├── css/
│ └── js/
└── requirements.txt
场景 B:做一个人格/心理测试项目
你只需要:MathBTI 前端 + 数据格式。
new-project/
├── data/
│ └── seed_mytest.json # 你的测试题+结果(照 mathbti 格式写)
├── templates/
│ └── test.html # 从 mathbti.html 改
├── static/
│ ├── css/
│ └── js/
└── scripts/
└── build_mytest.py # 从 build_mathbti.py 改
场景 C:纯内容搬运(不要代码)
你只需要 docs/ 和 data/*.json 里的文本和数据,用自己的技术栈重新实现前端。
三、逐步操作
Step 1 — 拿 Flask 骨架
从老项目复制 app.py,然后改这几处:
# 1. 改 DeepSeek API Key(第 83 行附近)
DEEPSEEK_API_KEY = "你的key"
# 2. 改数据路径(第 30~40 行)
# 删掉你不需要的路径变量,加上你自己的
DATA_DIR = os.path.join(BASE_DIR, "data").replace("\\", "/")
MY_STORY_PATH = os.path.join(DATA_DIR, "my_story.json").replace("\\", "/")
# 3. 改路由(第 258 行起)
# 删掉不需要的 @app.route,加上你自己的
@app.route("/")
def index():
return render_template("index.html")
# 4. 改 API 函数
# 照着 api_story() 的写法,load 你的 JSON 返回给前端
Step 2 — 拿剧本引擎
数据格式(这是最关键的,任何语言都能读):
{
"title": "我的剧本",
"start_node": "ch1_start",
"nodes": {
"ch1_start": {
"scene": "场景描述文字。用 \\n 换行。",
"character": "旁白",
"choices": [
{
"text": "选项A的文字",
"next": "ch1_choice_a",
"effects": { "str": 5 }
},
{
"text": "选项B的文字",
"next": "ch1_choice_b",
"effects": { "str": -3 }
}
]
},
"ch1_choice_a": {
"scene": "你选了A之后的故事...",
"character": "NPC",
"choices": [...]
}
}
}
前端渲染逻辑(从 desktop.js 提取的核心循环):
let storyData = null;
let currentState = { currentNode: null, stats: {} };
async function loadStory() {
const r = await fetch('/api/story');
storyData = (await r.json()).data;
const start = storyData.start_node;
const node = storyData.nodes[start];
renderNode(start);
}
function renderNode(nodeId) {
const node = storyData.nodes[nodeId];
if (!node) return;
currentState.currentNode = nodeId;
localStorage.setItem('my_story_save', JSON.stringify(currentState));
// 渲染场景文字
document.getElementById('scene').textContent = node.scene || '';
// 渲染说话人
document.getElementById('character').textContent = node.character || '';
// 渲染选项按钮
const choicesEl = document.getElementById('choices');
choicesEl.innerHTML = '';
for (const choice of (node.choices || [])) {
const btn = document.createElement('button');
btn.textContent = choice.text;
btn.onclick = () => makeChoice(choice);
choicesEl.appendChild(btn);
}
// 没有选项 = 故事结束
if (!node.choices || node.choices.length === 0) {
choicesEl.innerHTML = '<div>故事结束</div>';
}
}
function makeChoice(choice) {
// 应用属性变化
if (choice.effects) {
for (const key in choice.effects) {
currentState.stats[key] = (currentState.stats[key] || 0) + choice.effects[key];
}
}
// 跳到下一节点
renderNode(choice.next);
}
HTML 骨架:
<div id="stats"></div>
<div id="character"></div>
<div id="scene"></div>
<div id="choices"></div>
Step 3 — 拿剧本构建脚本
从 scripts/build_story.py 复制,它提供了两个辅助函数让你不用手写 JSON:
# N(node_id, 场景文字, 说话人, 选项列表)
# C(选项文字, 下一节点ID, 属性变化...)
N("ch1_start", "你站在路口。", "旁白", [
C("往左走", "ch1_left", str=5),
C("往右走", "ch1_right", str=-2),
])
在脚本末尾改输出路径后运行 py scripts/build_story.py 就会生成 JSON 文件。
Step 4 — 拿 MathBTI 测试
- 复制
templates/mathbti.html、static/css/mathbti.css、static/js/mathbti.js、data/seed_mathbti.json - 前端逻辑在
mathbti.js里,读 JSON → 逐题渲染 → 算 4 轴分数 → 映射到 16 种结果(4 位二进制) - 如果你要改题,直接改
data/seed_mathbti.json,或用scripts/build_mathbti.py重新生成
Step 5 — 拿 Word 导出脚本
scripts/export_*.py 用 python-docx 把设定文字导出为 Word。复制后改两处:
- 脚本内的内容文字(硬编码在 Python dict/string 里)
- 输出路径(脚本末尾,硬编码的绝对路径)
py -m pip install python-docx
py scripts/export_mathbti_doc.py
四、内容文件怎么搬
| 你要什么 | 从哪拿 | 怎么用 |
|---|---|---|
| 葫芦侠行剧本(8 章 93 节点) | data/seed_story.json |
直接当 JSON 读,格式见上 |
| 数学少年线剧本(85 节点) | docs/数学少年线_story.json |
同上格式,但属性名不同(shuli/xiayi/xinzhi) |
| MathBTI 全套数据(4 轴 12 题 16 结果) | data/seed_mathbti.json |
前端 fetch 后渲染问卷 |
| 模拟器剧本 | data/seed_simulator.json |
同剧本格式,属性为 gpa/interest/skill |
| 校友访谈数据 | data/seed_alumni.json |
线性叙事,four_years.nodes 数组 |
| 16 位数学家肖像图 | static/img/mathematicians/ |
文件名是 4 位二进制(0000~1111.png) |
| 小说原稿 | docs/novel/第0X章.txt |
纯文本,随便用 |
| 人物设定文档 | docs/novel/数学家小传_*.md |
Markdown,随便用 |
五、新项目清单
开新仓库时按这个清单走:
- 复制
app.py,改掉 API key、数据路径、路由 - 复制
requirements.txt,删掉不需要的包 - 建
data/目录,放你的 JSON 种子数据 - 建
templates/目录,放你的 HTML 模板 - 建
static/css/和static/js/,放样式和脚本 - 如果有剧本,照 Step 2 的格式写 JSON,或用
build_story.py生成 - 如果有 Word 导出需求,复制
scripts/export_*.py改内容 py app.py启动,浏览器验证
六、常见坑
- 旧 Flask 进程占端口:改完代码后页面不更新?
Get-Process python | Stop-Process -Force杀掉旧进程再重启。 - 剧本 JSON 里的中文:文件编码必须是 UTF-8,
json.load(f)时加encoding='utf-8'。 - build_story.py 输出路径:脚本末尾的
out_path是硬编码绝对路径,换机器必改。 - math_teen 故事文件位置:
数学少年线_story.json在docs/不在data/,app.py第 37 行直接指向 docs 目录。 - localStorage 存档:前端用 localStorage 保存剧本进度,key 名在 JS 里定义(如
mb_story_save),换项目时注意别冲突。 - 静态资源缓存:HTML 里引用 CSS/JS 带
?v=数字版本号,改了前端代码后递增这个数字,否则浏览器用缓存。