项目亮点异步高性能 JWT认证 双角色权限 开箱即用 技术栈Python 3.8 | FastAPI | SQLite | JWT | 原生前端适合人群Python初学者、Web开发学习者、毕业设计项目目录项目简介功能特性技术架构快速开始项目结构核心代码解析API接口文档演示截图常见问题总结与扩展 项目简介这是一个完整的学生消费管理系统采用前后端分离架构设计支持管理员和学生两种角色。系统实现了用户注册登录、余额充值、在线消费、交易流水查询、数据统计分析等完整业务流程。为什么选择这个项目✅实用性强可直接用于学校食堂、校园卡管理、培训机构等场景 ✅技术全面涵盖RESTful API、JWT认证、数据库操作、权限控制等核心技术 ✅易于上手零配置启动SQLite数据库无需安装5分钟即可运行 ✅代码规范遵循FastAPI最佳实践包含详细注释和类型注解 ✅界面美观现代化UI设计响应式布局适配多端设备✨ 功能特性 用户认证模块学生自助注册填写用户名、密码、学号、姓名即可注册安全登录JWT Token认证60分钟自动过期密码加密bcrypt强加密算法保障账户安全角色区分自动识别管理员/学生身份‍ 管理员功能 数据仪表盘实时显示系统运营数据学生总数 / 活跃学生数总余额 / 总充值金额 / 总消费金额交易总笔数 学生管理查看所有学生列表支持分页查看学生详情学号、姓名、余额、状态更新学生信息删除学生账户 充值管理为学生账户充值支持自定义金额和备注自动更新学生余额生成充值交易记录 统计分析系统总览统计按天消费趋势分析数据可视化展示 交易记录查看所有交易流水查看指定学生交易记录支持分页浏览区分充值/消费类型 学生功能 余额查询实时显示当前可用余额醒目大字体展示 在线消费输入消费金额完成支付支持添加消费备注自动扣除余额余额不足时提示个人账单查看自己的充值记录查看自己的消费记录按时间倒序排列支持分页浏览️ 技术架构后端技术栈技术版本用途Python3.8编程语言FastAPI0.104.1Web框架异步高性能SQLAlchemy2.0.23ORM数据库操作aiosqlite0.19.0异步SQLite驱动Pydantic2.5.0数据验证模型python-jose3.3.0JWT token处理passlib1.7.4密码加密bcryptuvicorn0.24.0ASGI服务器前端技术栈技术用途HTML5页面结构CSS3样式设计渐变、动画、响应式JavaScript (ES6)交互逻辑、API调用Fetch APIHTTP请求LocalStorageToken存储架构图┌─────────────┐ ┌──────────────┐ ┌─────────────┐ │ Browser │◄───────►│ FastAPI │◄───────►│ SQLite │ │ (HTML/CSS │ HTTP │ Backend │ Async │ Database │ │ /JS) │ REST │ │ SQL │ │ └───────────── └──────────────┘ └─────────────┘ │ ├─ JWT认证 ├─ 权限控制 └─ 数据验证 快速开始环境要求Python 3.8 或更高版本pip 包管理器现代浏览器Chrome/Firefox/Edge安装步骤安装依赖python -m pip install -r requirements.依赖说明fastapi0.104.1 # Web框架 uvicorn[standard]0.24.0 # 服务器 sqlalchemy2.0.23 # ORM aiosqlite0.19.0 # 异步SQLite pydantic2.5.0 # 数据验证 pydantic-settings2.1.0 # 配置管理 python-jose[cryptography]3.3.0 # JWT passlib[bcrypt]1.7.4 # 密码加密 bcrypt4.0.1 # bcrypt库兼容版 python-multipart0.0.6 # 表单处理3️⃣ 配置环境变量可选编辑.env文件# 数据库配置 DATABASE_URLsqliteaiosqlite:///./student_consumption.db ​ # JWT配置 SECRET_KEYyour-secret-key-change-this-in-production ALGORITHMHS256 ACCESS_TOKEN_EXPIRE_MINUTES60提示生产环境请修改SECRET_KEY为随机字符串4️ 初始化数据库python33 init_db.py执行后会✅ 创建所有数据库表users、transactions✅ 创建默认管理员账号用户名admin密码admin123⚠️ 首次登录后请修改密码输出示例 学生消费管理系统 - 数据库初始化 正在创建数据库表... 数据库表创建成功 默认管理员账号创建成功 用户名: admin 密码: admin123 请登录后及时修改密码 数据库初始化完成 5️⃣ 启动服务器python -m uvicorn app.main:app --host 0.0.0.0 --port 8001 --reload启动成功后会看到INFO: Uvicorn running on http://0.0.0.0:8001 (Press CTRLC to quit) INFO: Started reloader process [xxxxx] using WatchFiles INFO: Application startup complete.6️⃣ 访问系统打开浏览器访问主页面http://localhost:8001API文档http://localhost:8001/docsSwagger UIReDoc文档http://localhost:8001/redoc 项目结构学生消费管理系统/ │ ├── .env # 环境配置文件 ├── requirements.txt # Python依赖清单 ├── init_db.py # 数据库初始化脚本 │ ├── static/ # 前端静态文件 │ └── index.html # 主页面含UI和逻辑 │ └── app/ # 后端应用代码 ├── __init__.py # 包标识 ├── main.py # 应用入口 ├── config.py # 配置管理 ├── database.py # 数据库连接 ├── models.py # 数据模型 ├── schemas.py # 数据验证 ├── security.py # 安全认证 ├── dependencies.py # 依赖注入 │ └── routers/ # API路由 ├── __init__.py ├── auth.py # 认证路由 ├── students.py # 学生管理 ├── transactions.py # 交易管理 └── stats.py # 统计分析核心文件说明文件行数职责models.py~50定义User和Transaction数据模型schemas.py~120Pydantic请求/响应模型security.py~80JWT生成验证、密码加密dependencies.py~100权限验证依赖函数auth.py~130注册登录接口students.py~180学生CRUD接口transactions.py~200充值消费接口stats.py~140统计分析接口index.html~1200完整前端界面 核心代码解析1. 数据模型设计User模型用户表class User(Base): 用户模型存储管理员和学生信息 __tablename__ users id Column(Integer, primary_keyTrue, indexTrue) username Column(String(50), uniqueTrue, indexTrue, nullableFalse) hashed_password Column(String(255), nullableFalse) role Column(String(20), nullableFalse) # admin 或 student student_id Column(String(50), nullableTrue) # 学号 name Column(String(100), nullableFalse) balance Column(Float, default0.0) # 余额 is_active Column(Boolean, defaultTrue) created_at Column(DateTime, defaultdatetime.utcnow) # 关系一个用户可以有多条交易记录 transactions relationship(Transaction, back_populatesuser)字段说明username唯一索引登录凭证hashed_passwordbcrypt加密后的密码role角色标识admin/studentstudent_id仅学生有值用于业务关联balance仅对学生有意义记录可用余额is_active账户状态支持禁用功能Transaction模型交易表class Transaction(Base): 交易流水模型记录充值和消费 __tablename__ transactions id Column(Integer, primary_keyTrue, indexTrue) user_id Column(Integer, ForeignKey(users.id), nullableFalse) amount Column(Float, nullableFalse) # 正为充值负为消费 type Column(String(20), nullableFalse) # recharge 或 consumption operator_id Column(Integer, nullableTrue) # 充值时的管理员ID remark Column(String(500), nullableTrue) # 备注 created_at Column(DateTime, defaultdatetime.utcnow) # 关系多对一 user relationship(User, back_populatestransactions)设计亮点amount正数表示充值负数表示消费便于统计operator_id记录操作者追溯责任type明确交易类型方便筛选2. JWT认证机制Token生成def create_access_token(data: dict, expires_delta: Optional[timedelta] None) - str: 创建 JWT access token to_encode data.copy() if expires_delta: expire datetime.utcnow() expires_delta else: expire datetime.utcnow() timedelta(minutessettings.ACCESS_TOKEN_EXPIRE_MINUTES) to_encode.update({exp: expire}) encoded_jwt jwt.encode(to_encode, settings.SECRET_KEY, algorithmsettings.ALGORITHM) return encoded_jwtToken验证async def get_current_user( token: str Depends(oauth2_scheme), db: AsyncSession Depends(get_db) ) - User: 从 JWT token 解析当前登录用户 credentials_exception HTTPException( status_codestatus.HTTP_401_UNAUTHORIZED, detail无效的认证凭证, headers{WWW-Authenticate: Bearer}, ) # 解码 token payload decode_access_token(token) if payload is None: raise credentials_exception user_id: Optional[int] payload.get(sub) if user_id is None: raise credentials_exception # 查询用户 result await db.execute(select(User).where(User.id int(user_id))) user result.scalar_one_or_none() if user is None or not user.is_active: raise credentials_exception return user3. 权限控制管理员权限验证async def get_current_admin( current_user: User Depends(get_current_user) ) - User: 验证当前用户是否为管理员 if current_user.role ! admin: raise HTTPException( status_codestatus.HTTP_403_FORBIDDEN, detail权限不足需要管理员权限 ) return current_user学生权限验证async def get_current_student( current_user: User Depends(get_current_user) ) - User: 验证当前用户是否为学生 if current_user.role ! student: raise HTTPException( status_codestatus.HTTP_403_FORBIDDEN, detail权限不足需要学生身份 ) return current_user4. 充值业务逻辑router.post(/recharge, response_modelTransactionResponse) async def recharge( recharge_data: RechargeRequest, db: AsyncSession Depends(get_db), current_admin: User Depends(get_current_admin) ): 管理员为指定学生充值 # 1. 查找学生 result await db.execute( select(User).where( User.student_id recharge_data.student_id, User.role student ) ) student result.scalar_one_or_none() if not student: raise HTTPException( status_codestatus.HTTP_404_NOT_FOUND, detail学生不存在 ) # 2. 检查账户状态 if not student.is_active: raise HTTPException( status_codestatus.HTTP_403_FORBIDDEN, detail学生账户已被禁用无法充值 ) # 3. 更新学生余额 student.balance recharge_data.amount # 4. 创建交易记录 transaction Transaction( user_idstudent.id, amountrecharge_data.amount, # 正数 typerecharge, operator_idcurrent_admin.id, remarkrecharge_data.remark, ) db.add(transaction) await db.flush() return TransactionResponse.model_validate(transaction)5. 消费业务逻辑router.post(/consume, response_modelTransactionResponse) async def consume( consume_data: ConsumeRequest, db: AsyncSession Depends(get_db), current_student: User Depends(get_current_student) ): 学生本人进行消费操作 # 1. 检查余额是否充足 if current_student.balance consume_data.amount: raise HTTPException( status_codestatus.HTTP_400_BAD_REQUEST, detailf余额不足当前余额: {current_student.balance:.2f} ) # 2. 检查账户状态 if not current_student.is_active: raise HTTPException( status_codestatus.HTTP_403_FORBIDDEN, detail账户已被禁用无法消费 ) # 3. 更新学生余额扣除 current_student.balance - consume_data.amount # 4. 创建交易记录负数表示消费 transaction Transaction( user_idcurrent_student.id, amount-consume_data.amount, # 负数 typeconsumption, operator_idNone, remarkconsume_data.remark, ) db.add(transaction) await db.flush() return TransactionResponse.model_validate(transaction)6. 统计分析router.get(/overview, response_modelStatsOverview) async def get_stats_overview( db: AsyncSession Depends(get_db), current_admin: User Depends(get_current_admin) ): 获取系统总览统计数据 # 学生总数 total_students await db.execute( select(func.count()).where(User.role student) ) # 活跃学生数 active_students await db.execute( select(func.count()).where( User.role student, User.is_active True ) ) # 总余额 total_balance await db.execute( select(coalesce(func.sum(User.balance), 0)) .where(User.role student) ) # 总充值金额 total_recharge await db.execute( select(coalesce(func.sum(Transaction.amount), 0)) .where(Transaction.type recharge) ) # 总消费金额 total_consumption await db.execute( select(coalesce(func.sum(func.abs(Transaction.amount)), 0)) .where(Transaction.type consumption) ) return StatsOverview( total_studentstotal_students, active_studentsactive_students, total_balancetotal_balance, total_rechargetotal_recharge, total_consumptiontotal_consumption, ) API接口文档认证接口POST/api/auth/register- 学生注册请求体{ username: student1, password: 123456, student_id: 2024001, name: 张三 }响应{ access_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..., token_type: bearer, user_id: 2, username: student1, role: student }POST/api/auth/login- 用户登录请求体{ username: admin, password: admin123 }响应同注册响应学生管理接口需管理员权限GET/api/students/- 获取学生列表查询参数skip: 跳过记录数默认0limit: 返回数量上限默认100响应{ total: 10, items: [ { id: 2, username: student1, role: student, student_id: 2024001, name: 张三, balance: 74.5, is_active: true, created_at: 2026-06-03T12:30:00 } ] }GET/api/students/{student_id}- 获取学生详情路径参数student_id: 学生学号PUT/api/students/{student_id}- 更新学生信息请求体{ name: 李四, is_active: true }DELETE/api/students/{student_id}- 删除学生交易接口POST/api/transactions/recharge- 充值需管理员请求头Authorization: Bearer token请求体{ student_id: 2024001, amount: 100.0, remark: 月度生活费 }响应{ id: 1, user_id: 2, amount: 100.0, type: recharge, operator_id: 1, remark: 月度生活费, created_at: 2026-06-03T12:44:05 }POST/api/transactions/consume- 消费需学生本人请求体{ amount: 25.5, remark: 午餐 }GET/api/transactions/- 查询交易流水查询参数student_id: 学生学号管理员可查任意学生只能查自己skip: 跳过记录数limit: 返回数量上限响应{ total: 2, items: [ { id: 2, user_id: 2, amount: -25.5, type: consumption, operator_id: null, remark: 午餐, created_at: 2026-06-03T12:44:11 }, { id: 1, user_id: 2, amount: 100.0, type: recharge, operator_id: 1, remark: Initial recharge, created_at: 2026-06-03T12:44:05 } ] }统计接口需管理员权限GET/api/stats/overview- 系统总览响应{ total_students: 1, active_students: 1, total_balance: 74.5, total_recharge: 100.0, total_consumption: 25.5, transaction_count: 2 }GET/api/stats/consumption_by_day- 按天消费统计查询参数start_date: 开始日期YYYY-MM-DDend_date: 结束日期YYYY-MM-DD响应{ data: [ { date: 2026-06-03, total_amount: 25.5, transaction_count: 1 } ] }️ 演示截图登录注册页面支持登录/注册切换表单验证错误提示管理员仪表盘6个统计卡片渐变色设计实时数据学生管理列表展示分页功能查看交易按钮充值管理表单输入金额验证备注可选学生消费余额大字显示消费表单余额不足提示交易记录充值/消费区分颜色标识时间排序❓ 常见问题Q1: 如何修改数据库为MySQL/PostgreSQLA:只需修改.env文件中的DATABASE_URL# MySQL DATABASE_URLmysqlaiomysql://user:passwordlocalhost/dbname # PostgreSQL DATABASE_URLpostgresqlasyncpg://user:passwordlocalhost/dbname同时安装对应驱动pip install aiomysql # MySQL pip install asyncpg # PostgreSQLQ2: 如何部署到生产环境A:推荐以下步骤修改配置SECRET_KEY随机生成的长字符串 DATABASE_URLpostgresqlasyncpg://... ACCESS_TOKEN_EXPIRE_MINUTES1440 # 延长token有效期使用Gunicorn Uvicornpip install gunicorn gunicorn app.main:app \ -w 4 \ -k uvicorn.workers.UvicornWorker \ --bind 0.0.0.0:8000配置Nginx反向代理server { listen 80; server_name your-domain.com; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }使用Supervisor进程守护[program:student-system] commandgunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 directory/path/to/project autostarttrue autorestarttrueQ3: 如何添加更多功能A:参考以下扩展方向导出Excel使用openpyxl库短信通知集成阿里云/腾讯云SMS微信支付接入微信SDK图表展示使用 ECharts/Chart.jsDocker部署编写 Dockerfile 和 docker-compose.yml单元测试使用 pytest httpxQ4: 忘记密码怎么办A:目前系统未实现密码找回功能可以管理员在数据库中重置密码后续可添加邮箱验证找回密码功能Q5: 并发性能如何A:FastAPI是异步框架配合uvicorn可轻松支撑数百并发。如需更高性能增加worker数量-w 8使用Redis缓存热点数据数据库读写分离CDN加速静态资源总结与扩展项目亮点回顾✅完整业务流程从注册到消费的全链路 ✅安全可靠JWT认证 bcrypt加密 权限控制 ✅高性能异步IO 数据库连接池 ✅易维护清晰的分层架构 详细注释 ✅可扩展模块化设计易于添加新功能学习价值通过本项目你可以学习到FastAPI框架路由、依赖注入、中间件异步编程async/await、异步数据库RESTful API设计资源建模、状态码、错误处理JWT认证Token生成、验证、刷新SQLAlchemy ORM模型定义、关系映射、查询优化Pydantic数据验证请求校验、响应序列化前端开发Fetch API、LocalStorage、DOM操作下一步扩展建议短期1-2周添加密码找回功能邮箱验证实现Excel导出功能添加操作日志记录完善前端错误处理中期1个月接入微信支付/支付宝添加数据可视化图表ECharts实现消息推送WebSocket添加单元测试和集成测试长期2-3个月微服务拆分用户服务、交易服务、统计服务引入Redis缓存容器化部署Docker KubernetesCI/CD自动化部署 致谢感谢以下开源项目FastAPISQLAlchemyPydanticUvicorn如果觉得项目有帮助欢迎点赞⭐、收藏、转发你的支持是我持续更新的动力⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇点击此处获取源码⬇⬇⬇⬇⬇⬇⬇⬇⬇