不写玩具示例,直接给你一个能跑起来的「古典文学网」底子。这里有两个骨架:后端 hiflask(Flask 3 应用工厂 + 蓝图 + ORM + JWT)和前端 hivue(Vite + Router + Pinia + Element Plus + axios 封装)。骨架已经把工程结构、统一响应、鉴权、跨域代理这些「脏活」搭好,你每学完一章,就往对应的位置补一块功能。听不懂的接口位置都留了 TODO 注释,照着讲义填就行。
初学者写 Flask,最容易把 18 个接口全塞进一个 app.py,几十行之后自己都找不到北。真实项目按「应用工厂 → 蓝图分模块 → ORM 模型 → 工具函数」分层,谁的活儿谁干。这个骨架就是那套分层的最小可用版,你照着往下填,代码从第一天起就是能交付的形状。
hiflask/
├── app.py 应用工厂 create_app():装配扩展、注册蓝图、挂 JWT 回调与全局错误处理
├── config.py Config / DevConfig / ProdConfig / TestingConfig,连接串与密钥从环境变量读
├── extensions.py db / jwt / cors / migrate 单拎出来,避免应用工厂与模型互相 import
├── requirements.txt Flask 3 + SQLAlchemy + JWT + PyMySQL + cryptography 等依赖
├── README.md 环境要求、四步启动、curl 自测、接口实现状态、常见问题
├── models/ 数据层:一张表一个类
│ ├── __init__.py 汇总导出,让 Flask-Migrate 能发现全部模型
│ ├── user.py User
│ ├── article.py Category / Article / Banner
│ └── comment.py Comment / Favorite / UserLike
├── views/ 接口层:一个模块一个蓝图
│ ├── __init__.py register_blueprints(app),app.py 不用关心有几个模块
│ ├── home.py home_bp:banner / category / recommend
│ ├── user.py user_bp:register / login / profile / avatar / logout
│ ├── article.py article_bp:list / detail / like
│ ├── comment.py comment_bp:list / add / like / delete
│ └── favorite.py favorite_bp:toggle / list
└── utils/
├── __init__.py
├── response.py success() / fail() / page_data(),统一 {code,msg,data}
└── auth.py @login_required、optional_login(),解析 Bearer token 取 user_id
前提:本机已装 Python 3.10+ 与 MySQL 8。
# ① 建库并导入数据(脚本在 pyweb/sql/ 下)
cd ../../sql
mysql -uroot -p < hiwen.sql
# ② 建虚拟环境并安装依赖(回到骨架目录)
cd ../code/hiflask
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\Activate.ps1
pip install -r requirements.txt
# ③ 启动
python app.py # 或:flask --app app run --debug
其一,hiwen.sql 开头会 DROP DATABASE IF EXISTS hiwen,重复执行会清空数据,别在生产库上跑。其二,种子用户 admin / libai 的密码是占位符 PUT_HASH_HERE,用它俩登不进去——直接调注册接口新建一个账号来测。
页面能跑起来,靠的不只是 .vue 文件:路由怎么配、登录态存哪、请求怎么自动带 token、开发时跨域怎么绕——这些都配好了,你才能专心写业务。骨架还把 /api 通过 Vite 代理转给后端,前端代码里永远只写 /api/xxx,不用写全地址,上线换成 Nginx 反代零改动。
hivue/
├── index.html SPA 唯一入口,挂载点 #app
├── package.json 依赖与脚本(dev / build / preview)
├── vite.config.js 开发服务器 + /api 代理到 http://127.0.0.1:5000
├── .env.development 环境变量样例(接口前缀等)
├── public/ 静态资源
└── src/
├── main.js 创建应用、装 Pinia / Router / Element Plus,挂载 App.vue
├── App.vue 根组件,只放路由出口
├── router/
│ └── index.js 路由表 + 全局前置守卫(未登录跳登录页)
├── stores/
│ └── user.js Pinia:token / 用户信息,同步 localStorage,login() / logout()
├── utils/
│ └── request.js axios 实例 + 请求拦截器(带 token)+ 响应拦截器(按 code 统一处理)
├── api/ 一个模块一个文件,只写「调哪个接口」
│ ├── user.js register / login / getProfile / updateProfile / uploadAvatar / logout
│ ├── article.js list / detail / like / recommend
│ ├── comment.js list / add / like / remove
│ └── favorite.js toggle / list
├── layouts/
│ └── DefaultLayout.vue 顶部导航 + 内容区 + 页脚
├── views/ 页面级组件,与路由一一对应
│ ├── HomeView.vue 首页:轮播图 / 分类 / 推荐
│ ├── ArticleListView.vue 作品列表:分页 / 筛选 / 搜索
│ ├── ArticleDetailView.vue 作品详情:正文 / 点赞 / 收藏 / 书评
│ ├── LoginView.vue 登录
│ ├── RegisterView.vue 注册
│ ├── UserCenterView.vue 用户中心:资料 / 改资料 / 传头像
│ └── FavoriteView.vue 我的收藏
└── components/ 可复用组件
├── AppHeader.vue 顶栏(登录态、进用户中心)
├── ArticleCard.vue 作品卡片
└── CommentItem.vue 书评条目(含楼中楼回复)
前提:本机已装 Node 18 或 20 LTS。
# ① 安装依赖
cd ../hivue
npm install
# ② 启动开发服务器
npm run dev
# ③ 先启动后端(另开一个终端)
# Vite 把 /api 代理到 5000 端口,后端没起页面就是空的
开发期前端是 5173、后端是 5000,跨域靠 vite.config.js 里的 /api 代理绕过去。后端没启动时,所有请求都会失败、页面自然空白。先在浏览器 Network 面板看请求是不是 5173 发出去的、代理有没有转发到 5000;实在分不清,就用 Postman 直接打后端 5000 确认后端是好的。