# 葫芦数学 · 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 - requests(DeepSeek AI 对话用) - python-docx(仅 scripts/ 导出 Word 用) ## API 路由一览 | 路由 | 方法 | 说明 | |------|------|------| | `/` | GET | 重定向到 `/web` | | `/web` | GET | 桌面端网页 | | `/mathbti` | GET | MathBTI 测试页 | | `/math_teen` | GET | 数学少年线独立剧本页 | | `/api/videos` | GET | 视频列表 | | `/api/knowledge` | GET | 知识卡片列表 | | `/api/knowledge/` | 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/` | GET | 直接访问 data/ 下的 JSON 文件 |