This repository has been archived on 2026-08-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2026-08-08 18:45:07 +08:00

209 lines
8.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 葫芦数学 · Hulu Math
Flask 单体应用,提供网页端 + MathBTI 数学人格测试。一个 `app.py` 包含路由、API、数据库、大模型对接。
## 快速开始
```bash
# 1. 安装依赖
py -m pip install -r requirements.txt
# 2. 启动服务
py app.py
# 3. 浏览器访问
# http://127.0.0.1:5000/ → 自动跳转 /web(桌面端网页)
# http://127.0.0.1:5000/mathbti → MathBTI 数学人格测试
# http://127.0.0.1:5000/math_teen → 数学少年线独立剧本页
```
## 目录结构
```
Hulumath-Web-Demo/
├── app.py # Flask 后端主文件(路由 + API + SQLite + DeepSeek 对接)
├── requirements.txt # Python 依赖
├── vercel.json # Vercel 部署路由配置
├── templates/ # Jinja2 模板
│ ├── desktop.html # 网页端(桌面布局,引用 desktop.css + desktop.js
│ ├── mathbti.html # MathBTI 数学人格测试页(引用 mathbti.css + mathbti.js
│ └── math_teen.html # 数学少年线独立播放页(自包含,无外部 CSS/JS)
├── static/ # 静态资源
│ ├── css/
│ │ ├── desktop.css # 网页端样式
│ │ └── mathbti.css # MathBTI 页样式
│ ├── js/
│ │ ├── desktop.js # 网页端逻辑
│ │ └── mathbti.js # MathBTI 页逻辑
│ └── img/
│ └── mathematicians/ # 16 位数学人物肖像图片(0000~1111.png
├── data/ # 运行时数据(SQLite + 种子 JSON
│ ├── miniapp_v3.db # SQLite 数据库(用户、收藏、历史、知识卡片)
│ ├── seed_videos.json # 视频种子数据(54 条)
│ ├── seed_story.json # 葫芦侠行剧本数据(8 章 93 节点)
│ ├── seed_simulator.json # 数学专业模拟器剧本数据
│ ├── seed_mathbti.json # MathBTI 测试题目 + 16 种结果数据
│ └── seed_alumni.json # 数学校友访谈数据
├── docs/ # 内容创作文档(不是运行时依赖)
│ ├── 数学少年线_story.json # 数学少年线剧本数据(被 app.py 直接读取)
│ ├── novel/ # 小说原稿(葫芦侠行 8 章 txt + 设定)
│ ├── 产品文档/ # PRD、需求、开发记录
│ └── 会议记录/ # 需求评审纪要
└── scripts/ # 构建/导出脚本
├── build_mathbti.py
├── build_story.py
├── export_mathbti_doc.py
└── export_mathematicians_docx.py
```
## data/ 下的 JSON 文件说明
这些是应用运行时通过 API 读取的种子数据。`app.py` 在启动时根据路径加载它们。
| 文件 | 对应 API 路由 | 用途 | 数据结构概要 |
|------|-------------|------|-------------|
| `seed_videos.json` | `/api/videos` | 发现页视频列表 | 数组,每条含 id/title/author/discipline/video_url/duration_min 等 |
| `seed_story.json` | `/api/story` | 葫芦侠行互动剧本 | `{title, start_node, nodes: {node_id: {scene, character, choices: [{text, next, effects}]}}}` |
| `seed_simulator.json` | `/api/simulator` | 数学专业模拟器 | 同 story 结构,属性为 gpa/interest/skill |
| `seed_mathbti.json` | `/api/math_personality` | MathBTI 测试题+结果 | `{axes, clans, questions, results: {binary_code: {name, clan, stats5, ...}}}` |
| `seed_alumni.json` | `/api/alumni` | 数学校友访谈 | `{alumni: [{id, name, major, four_years: {nodes}}], meta}` |
> **注意**`数学少年线_story.json` 在 `docs/` 目录下,不在 `data/`。`app.py` 第 37 行直接指向 `docs/数学少年线_story.json`。
## docs/ 目录说明
`docs/` 是内容创作区,**不影响应用运行**(除了数学少年线剧本文件被直接读取)。
- `docs/novel/` — 葫芦侠行的小说原稿和设定文档(txt/md/docx
- `docs/产品文档/` — 产品需求文档、PRD、开发记录
- `docs/会议记录/` — 需求评审会议纪要
- `docs/数学少年线_story.json` — 数学少年线互动剧本数据,**被 app.py 直接读取**API `/api/story/math_teen` 返回此文件内容
### 在新项目中复用 docs/
如果你想在新项目里使用这些内容:
1. **互动剧本**:复制 `docs/数学少年线_story.json``data/seed_story.json` 到新项目,按 `{start_node, nodes: {id: {scene, character, choices}}}` 格式读取即可。前端用 JS 根据 `currentNode` 渲染 `scene` 文字和 `choices` 按钮即可。
2. **MathBTI 数据**:复制 `data/seed_mathbti.json`,包含 4 轴 12 题 + 16 种结果(含数学家小传、五维能力值、肖像图路径)。
3. **小说原稿**`docs/novel/第0X章.txt` 是纯文本,可直接用于任何文本展示场景。
## scripts/ 脚本说明
这些脚本用于**生成种子 JSON** 或**导出 Word 文档**。在项目根目录运行。
### build_mathbti.py — 生成 MathBTI 种子数据
将硬编码的题目、4 轴、4 族、16 种结果写入 `data/seed_mathbti.json`
```bash
py scripts/build_mathbti.py
# 输出: data/seed_mathbti.json
# 打印: OK: seed_mathbti.json generated, 16 results, 4 clans
```
> 脚本内用 Python dict 写死全部数据,`json.dump` 输出。修改题目/结果后重跑即可刷新 `data/seed_mathbti.json`。
### build_story.py — 生成葫芦侠行剧本
根据大纲原文构建 8 章 93 节点的互动剧情 JSON。
```bash
py scripts/build_story.py
# 输出路径写死在脚本末尾(第 1006 行),需手动改为你的项目路径
```
> 脚本提供 `N(node_id, scene, character, choices)` 和 `C(text, next, shuli, xiayi, xinzhi)` 两个辅助函数来逐节点构建故事。**输出路径硬编码在脚本中**,复制到新项目后需修改 `out_path`。
### export_mathbti_doc.py — 导出 Word 设定文档
将 16 位数学家设定导出为 Word 文档。
```bash
py scripts/export_mathbti_doc.py
# 输出: scripts/万理之城_设定圣经.docx
# 依赖: python-docx
```
### export_mathematicians_docx.py — 导出数学家小传 Word
将 16 位数学家小传 + 六维雷达数据导出为 Word。
```bash
py scripts/export_mathematicians_docx.py
# 输出路径硬编码在脚本第 528 行,需手动修改
# 依赖: python-docx
```
> **注意**:两个导出脚本的输出路径是硬编码的绝对路径,复制到新项目后需要修改脚本中的路径。
## 在新项目中使用
### 最小化移植(只要网页端)
1. 复制 `app.py``templates/desktop.html``static/css/desktop.css``static/js/desktop.js``data/` 目录
2. `py -m pip install flask requests`
3. `py app.py`
### 只要互动剧本引擎
剧本数据格式是通用的 JSON,任何语言都能读:
```python
import json
with open('seed_story.json', 'r', encoding='utf-8') as f:
story = json.load(f)
current_node = story['start_node'] # 例如 'ch1_start'
node = story['nodes'][current_node]
print(node['scene']) # 场景文字
print(node['character']) # 说话人
for choice in node.get('choices', []):
print(choice['text']) # 选项文字
print(choice['next']) # 下一节点 ID
print(choice.get('effects', {})) # 属性变化
```
前端渲染逻辑参考 `static/js/desktop.js` 中的 `loadStory()``rSN()` 函数。
### 只要 MathBTI 测试
1. 复制 `templates/mathbti.html``static/css/mathbti.css``static/js/mathbti.js``data/seed_mathbti.json`
2. MathBTI 前端是自包含的,只需能 fetch 到 `seed_mathbti.json` 即可运行
## 环境要求
- Python 3.12+
- Flask 3.x
- requestsDeepSeek AI 对话用)
- python-docx(仅 scripts/ 导出 Word 用)
## API 路由一览
| 路由 | 方法 | 说明 |
|------|------|------|
| `/` | GET | 重定向到 `/web` |
| `/web` | GET | 桌面端网页 |
| `/mathbti` | GET | MathBTI 测试页 |
| `/math_teen` | GET | 数学少年线独立剧本页 |
| `/api/videos` | GET | 视频列表 |
| `/api/knowledge` | GET | 知识卡片列表 |
| `/api/knowledge/<id>` | GET | 单个知识卡片详情 |
| `/api/story` | GET | 葫芦侠行剧本数据 |
| `/api/story/math_teen` | GET | 数学少年线剧本数据 |
| `/api/simulator` | GET | 模拟器剧本数据 |
| `/api/alumni` | GET | 校友访谈数据 |
| `/api/math_personality` | GET | MathBTI 题目+结果数据 |
| `/api/math_personality/calculate` | POST | 计算数学人格结果 |
| `/api/chat` | POST | AI 数学助教对话(对接 DeepSeek |
| `/api/favorites` | GET/POST/DELETE | 收藏管理 |
| `/api/history` | GET/POST | 观看历史 |
| `/api/user/profile` | GET/POST | 用户资料 |
| `/api/user/stats` | GET | 用户统计 |
| `/api/simulator/save` | GET/POST | 模拟器存档 |
| `/data/<filename>` | GET | 直接访问 data/ 下的 JSON 文件 |