目录

智慧图书馆管理系统

Flask + SQLite 分层架构的图书馆借阅管理系统
规格驱动开发(Spec → Models → Services → Routes → UI)


一、项目简介

系统覆盖图书馆业务全流程:图书管理 / 读者管理 / 借阅(借书 · 还书 · 续借)/ 逾期管理 / 数据概览,同时提供 REST API 与管理端 Web 界面。

项目采用 规格驱动 的组织方式:先由 case/spec/API_SPEC.md 明确实体、接口与业务规则(Spec 层),再按 models(实体与仓储)→ services(业务规则)→ routes(REST 接口)→ templates + static(管理端界面)逐层实现,使业务约束集中在 Service 层、可被 pytest 直接验证。


二、功能模块

模块 界面视图 说明
数据概览 data-view="dashboard" 馆藏统计卡片、馆藏分类分布条形图、逾期提醒列表
图书管理 data-view="books" 关键词搜索(书名/作者/ISBN)、分类筛选、新增 / 编辑 / 删除
读者管理 data-view="users" 按姓名/证号/院系搜索、注册读者、展示各读者在借册数
在借管理 data-view="loans" 在借列表(按到期日升序)、可勾选「仅显示逾期」、归还、续借
借阅历史 data-view="history" 已归还记录(按归还时间倒序)
办理借书 顶部按钮 / 弹窗 选择图书与读者、填写借期(1–90 天)后借出

三、技术栈

层次 技术
后端框架 Flask 3.x(应用工厂 create_app + Blueprint 蓝图)
数据存储 SQLite(标准库 sqlite3Row 行工厂 + 上下文管理器管理事务)
数据建模 dataclass 实体 + 静态方法 Repository(无 ORM 依赖)
前端 原生 HTML / CSS / JavaScript 单页应用(无构建步骤)
测试 pytest 8.x

依赖清单(case/requirements.txt):

flask>=3.0,<4
pytest>=8.0,<9

四、目录结构

图书管理系统/
├── case/                          # 案例实现(主程序)
│   ├── app.py                     # 应用入口:create_app / 路由 / 启动
│   ├── config.py                  # 配置:SQLite 数据库路径
│   ├── requirements.txt
│   ├── README.md                  # 案例目录内的精简说明
│   ├── spec/
│   │   └── API_SPEC.md            # 规格文档(实体 / API / 业务规则)
│   ├── models/                    # 数据层
│   │   ├── __init__.py            # 导出 init_db 与实体
│   │   ├── database.py            # 连接管理、建表、增量迁移、初始化
│   │   ├── book.py                # Book 实体 + BookRepository
│   │   ├── user.py                # User 实体 + UserRepository
│   │   ├── loan.py                # Loan 实体 + LoanRepository
│   │   └── seed.py                # 首次启动写入演示数据
│   ├── services/                  # 业务层
│   │   ├── loan_service.py        # 借书 / 还书 / 续借规则校验
│   │   └── stats_service.py       # 概览统计聚合
│   ├── routes/                    # 接口层(Blueprint)
│   │   ├── __init__.py            # register_blueprints 统一注册
│   │   ├── books.py               # /api/books
│   │   ├── users.py               # /api/users
│   │   ├── loans.py               # /api/loans
│   │   └── stats.py               # /api/stats
│   ├── tests/
│   │   └── test_loan_service.py   # 借阅业务单元测试
│   ├── templates/index.html       # 管理端单页界面
│   ├── static/
│   │   ├── css/main.css
│   │   └── js/main.js             # 视图切换、表格渲染、弹窗与 API 调用
│   └── data/library.db            # SQLite 数据库文件(运行时生成)
├── start_case.bat                 # 一键:装依赖 → 跑测试 → 起服务
├── export_word.py                 # 研究报告 Markdown → Word 转换脚本
├── 研究报告.docx                   # 课程研究报告
└── 安装部署说明.pdf                 # 安装部署说明

五、数据库设计

数据库文件:case/data/library.db(可通过环境变量 BOOK_DB_PATH 覆盖)。

books(图书)

字段 类型 说明
id INTEGER PK AUTOINCREMENT 主键
isbn TEXT NOT NULL UNIQUE ISBN,唯一约束
title TEXT NOT NULL 书名
author TEXT NOT NULL 作者
category TEXT NOT NULL DEFAULT ‘综合’ 分类
publisher TEXT DEFAULT ‘’ 出版社
shelf TEXT DEFAULT ‘’ 架位
copies_total INTEGER NOT NULL DEFAULT 1 总册数
copies_available INTEGER NOT NULL DEFAULT 1 可借册数
created_at TEXT DEFAULT (datetime(‘now’,’localtime’)) 创建时间

users(读者)

字段 类型 说明
id INTEGER PK AUTOINCREMENT 主键
card_no TEXT NOT NULL UNIQUE 借书证号,唯一约束
name TEXT NOT NULL 姓名
email TEXT 邮箱
phone TEXT DEFAULT ‘’ 电话
department TEXT DEFAULT ‘’ 院系
created_at TEXT 创建时间

loans(借阅记录)

字段 类型 说明
id INTEGER PK AUTOINCREMENT 单号
book_id INTEGER NOT NULL FK→books(id) 图书
user_id INTEGER NOT NULL FK→users(id) 读者
loan_date TEXT NOT NULL 借出日期(ISO 格式)
due_date TEXT NOT NULL 应还日期
return_date TEXT 归还日期,NULL 表示在借

索引:idx_loans_active(return_date)idx_books_title(title)

增量迁移models/database.py 中的 _migrate() 会通过 PRAGMA table_info 检查字段是否存在,为旧版本数据库自动补齐 categorypublishershelfphonedepartment 等新增字段,保证历史数据文件可直接升级。


六、业务规则

规则集中在 services/loan_service.py,常量与 spec/API_SPEC.md 第 4 节严格一致:

规则 说明
借期范围 MIN_LOAN_DAYS = 1 ~ MAX_LOAN_DAYS = 90,超出抛出 LoanServiceError
借书前置校验 图书必须存在、读者必须存在
并发借阅上限 MAX_ACTIVE_LOANS_PER_USER = 5,每位读者同时最多在借 5 册
库存扣减 通过 UPDATE ... WHERE copies_available > 0 原子扣减,失败即「无可借册数」
归还 仅在 return_date IS NULL 时生效,成功后库存 +1
续借 仅未归还记录可续借,默认延长 14 天(extra_days 可调)
删除图书 仅当 copies_available == copies_total(无在借)时允许删除
修改总册数 不得小于已借出数量,否则抛出 ValueError("总册数不能小于已借出数量")

借阅状态Loan.to_dict() 计算得出,非存储字段):

  • returned:已归还
  • overdue:未归还且 due_date < 今天
  • active:未归还且未到期
  • 同时附带 days_left(剩余天数,可为负数)

七、API 接口

完整规格见 case/spec/API_SPEC.md。服务基础地址:http://127.0.0.1:5005

系统

方法 路径 说明
GET / 管理端主界面
GET /health 健康检查,返回 {"status": "ok"}

统计 /api/stats

方法 路径 说明
GET /api/stats/dashboard 概览统计

返回字段:book_titles(书目数)、total_copies(总册数)、available_copiesborrowed_copiesreader_countactive_loansoverdue_loansreturned_totalby_category(分类分布数组)。

图书 /api/books

方法 路径 说明
GET /api/books?q=&category= 图书列表 / 搜索(书名、作者、ISBN 模糊匹配 + 分类精确筛选)
GET /api/books/categories 全部分类列表
GET /api/books/<id> 图书详情
POST /api/books 新增图书(必填 isbn/title/authorcopies_total 至少为 1;ISBN 重复返回 409)
PUT /api/books/<id> 更新图书(可改 title/author/category/publisher/shelf/copies_total
DELETE /api/books/<id> 删除图书(存在在借记录时返回 400)

读者 /api/users

方法 路径 说明
GET /api/users?q= 读者列表(姓名、证号、院系模糊匹配),附带 active_loans 在借册数
POST /api/users 注册读者(必填 card_no/name;证号重复返回 409)

借阅 /api/loans

方法 路径 说明
GET /api/loans?overdue=1 在借列表,overdue=1 时仅返回逾期记录
GET /api/loans/history?limit=50 已归还记录(limit 上限 200)
POST /api/loans/borrow 借书,Body: {"book_id":1,"user_id":1,"days":30}
POST /api/loans/<id>/return 归还
POST /api/loans/<id>/renew 续借,Body: {"days":14}(默认 14 天)

业务校验失败统一返回 400{"error": "..."};资源不存在返回 404;创建成功返回 201


八、快速开始

8.1 环境要求

依赖 版本建议
Python 3.9+(代码使用了 `str
浏览器 现代浏览器(Chrome / Edge / Firefox)

无需安装数据库服务——使用 Python 内置 SQLite。

8.2 一键启动(Windows)

双击根目录的 start_case.bat,脚本会依次:

  1. 安装依赖:pip install -r requirements.txt -q
  2. 运行测试:python -m pytest tests -q
  3. 启动服务:python app.py

8.3 手动启动

cd case

# 1. 安装依赖(建议先创建虚拟环境)
python -m venv venv
venv\Scripts\activate           # Windows
# source venv/bin/activate      # macOS / Linux

pip install -r requirements.txt

# 2. 运行测试
python -m pytest tests -q

# 3. 启动服务
python app.py

启动后访问 http://127.0.0.1:5005/

8.4 演示数据

首次启动时 init_db() 会自动检测 books 表是否为空,为空则写入演示数据(models/seed.py):

  • 5 本图书:软件工程、深入理解计算机系统、设计模式、人类简史、三体(每本 3 册)
  • 3 位读者:张明(计算机学院)、李华(软件学院)、王芳(信息学院)
  • 2 条借阅记录:1 条正常在借、1 条已逾期(用于演示逾期筛选与提醒)

如需重新加载演示数据,删除 case/data/library.db 后重启即可。


九、测试

测试文件:case/tests/test_loan_service.py,共 7 个用例,通过 monkeypatch 将数据库指向 pytest 的临时目录,每个用例使用独立数据库,互不干扰。

用例 覆盖内容
test_borrow_and_return 借书扣减库存、还书恢复库存、联表书名回填
test_borrow_no_stock 库存为 0 时重复借阅抛错
test_renew_extends_due_date 续借延长应还日期
test_borrow_days_out_of_range 借期 0 天 / 91 天越界报错
test_borrow_days_boundary_ok 借期边界值 1 天与 90 天可借
test_max_active_loans 达到 5 册上限后再借报错
test_can_borrow_after_return_when_at_limit 归还一本后可以继续借阅

运行:

cd case
python -m pytest tests -q

十、配置项

环境变量 默认值 说明
BOOK_DB_PATH case/data/library.db SQLite 数据库文件路径

其他运行参数(case/app.py):

  • 监听地址:127.0.0.1
  • 端口:5005
  • debug=True

十一、使用示例

# 健康检查
curl http://127.0.0.1:5005/health

# 查看概览统计
curl http://127.0.0.1:5005/api/stats/dashboard

# 新增图书
curl -X POST http://127.0.0.1:5005/api/books \
  -H "Content-Type: application/json" \
  -d "{\"isbn\":\"978-7-111-99999-9\",\"title\":\"软件工程\",\"author\":\"Sommerville\",\"copies_total\":3,\"category\":\"计算机\"}"

# 搜索计算机类图书
curl "http://127.0.0.1:5005/api/books?q=软件&category=计算机"

# 注册读者
curl -X POST http://127.0.0.1:5005/api/users \
  -H "Content-Type: application/json" \
  -d "{\"card_no\":\"2024099\",\"name\":\"赵六\",\"department\":\"计算机学院\"}"

# 借书
curl -X POST http://127.0.0.1:5005/api/loans/borrow \
  -H "Content-Type: application/json" \
  -d "{\"book_id\":1,\"user_id\":1,\"days\":30}"

# 归还 / 续借
curl -X POST http://127.0.0.1:5005/api/loans/1/return
curl -X POST http://127.0.0.1:5005/api/loans/1/renew \
  -H "Content-Type: application/json" -d "{\"days\":14}"

# 查看逾期记录
curl "http://127.0.0.1:5005/api/loans?overdue=1"

十二、常见问题

1. 端口 5005 被占用 修改 case/app.py 末尾 create_app().run(...) 中的 port 参数,或释放该端口。

2. 演示数据没有出现 seed_if_empty() 仅在 books 表记录数为 0 时写入。若数据库已有数据,可删除 case/data/library.db 后重启。

3. 新增图书提示「ISBN 可能重复」 books.isbn 有唯一约束,请更换 ISBN。

4. 删除图书失败 业务规则限制:仅当该书无在借记录(copies_available == copies_total)时才可删除,请先办理归还。

5. 修改图书总册数报错「总册数不能小于已借出数量」 新总册数不得低于当前已借出数量(copies_total - copies_available)。

6. 运行 export_word.py 提示未找到 研究报告.md 该脚本期望读取根目录的 研究报告.md 并生成 研究报告.docx。当前仓库只保留了导出后的 研究报告.docx,如需重新生成,请先补回 研究报告.md,并安装依赖:

pip install python-docx
python export_word.py

十三、说明

  • 本项目为课程实践案例,未实现用户登录与权限控制,管理端界面默认全功能开放。
  • 数据存储使用 SQLite + 手写 SQL,未引入 ORM;models 层以 dataclass 承载实体、以静态方法类充当 Repository。
  • 借阅规则(借期范围、并发上限)以常量形式与 spec/API_SPEC.md 保持同步,修改规则时需同时更新规格文档与测试用例。
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号