大家好我是Java1234_小锋老师分享一套锋哥原创的基于Python的微信小程序图书馆(图书借阅)管理系统(FastAPIVue3)项目介绍随着移动互联网与智慧校园建设的不断推进传统图书馆借阅方式在效率、便捷性与数据统计能力方面已难以满足高校师生的日常需求。读者希望能够随时随地检索馆藏、办理借还与续借管理人员则需要对图书、读者与借阅业务进行可视化监控与精细化管理。针对上述问题本文设计并实现了一套基于微信小程序的图书馆图书借阅管理系统。系统采用前后端分离与多端协同架构后端基于 Python 语言与 FastAPI 框架提供 RESTful API使用 SQLAlchemy 完成对象关系映射以 MySQL 数据库库名 db_library持久化业务数据管理员端采用 Vue3、Vite、Element Plus 与 ECharts 构建 Web 管理后台实现数据看板、图书与分类管理、读者管理、借阅管理、轮播图维护以及个人中心等功能读者端基于微信小程序实现用户名密码登录与注册、图书浏览与检索、自助借阅、续借还书、个人资料与头像修改、密码修改等功能。系统在业务层实现了借阅上限校验、库存扣减与恢复、超期状态自动更新与罚款计算等规则。实践表明该系统结构清晰、接口规范、交互便捷能够有效提升图书借阅管理效率对同类校园信息化应用具有一定参考价值。源码下载链接: https://pan.baidu.com/s/1kzu7OgwVgto-_5Etlhotvg?pwd1234提取码: 1234系统展示核心代码 读者业务服务 from datetime import datetime from sqlalchemy import or_ from sqlalchemy.orm import Session from app.common.exceptions import BusinessException from app.common.result import Result, fail, page_result, success, success_msg from app.models.reader import Reader from app.schemas.reader import ReaderRequest from app.utils.datetime_util import format_datetime class ReaderService: 读者业务服务类 def __init__(self, db: Session): 构造读者服务 :param db: 数据库会话 self.db db def list_readers(self, page: int, page_size: int, keyword: str) - Result: 分页查询读者列表 :param page: 页码 :param page_size: 每页条数 :param keyword: 关键字 :return: 分页结果 query self.db.query(Reader) if keyword: query query.filter(or_( Reader.real_name.like(f%{keyword}%), Reader.username.like(f%{keyword}%), Reader.card_no.like(f%{keyword}%), )) total query.count() items query.order_by(Reader.id.desc()).offset((page - 1) * page_size).limit(page_size).all() list_data [self._to_map(r) for r in items] return page_result(list_data, total, page, page_size) def all_readers(self) - Result: 全部正常读者下拉用 :return: 读者简要列表 items self.db.query(Reader).filter(Reader.status 1).order_by(Reader.id.asc()).all() list_data [{ id: r.id, real_name: r.real_name, card_no: r.card_no, max_borrow: r.max_borrow, } for r in items] return success(list_data) def add(self, req: ReaderRequest) - Result: 新增读者 :param req: 请求体 :return: 统一响应 if self.db.query(Reader).filter(Reader.username req.username).count() 0: return fail(用户名已存在) if self.db.query(Reader).filter(Reader.card_no req.card_no).count() 0: return fail(借书证号已存在) reader Reader( usernamereq.username, passwordreq.password if req.password else 123456, card_noreq.card_no, real_namereq.real_name, genderreq.gender if req.gender is not None else 1, phonereq.phone, emailreq.email, max_borrowreq.max_borrow if req.max_borrow is not None else 5, statusreq.status if req.status is not None else 1, create_timedatetime.now(), ) self.db.add(reader) self.db.commit() return success_msg(添加成功) def update(self, reader_id: int, req: ReaderRequest) - Result: 修改读者 :param reader_id: 读者ID :param req: 请求体 :return: 统一响应 reader self.db.query(Reader).filter(Reader.id reader_id).first() if reader is None: raise BusinessException(读者不存在) if req.card_no is not None: reader.card_no req.card_no if req.real_name is not None: reader.real_name req.real_name if req.gender is not None: reader.gender req.gender if req.phone is not None: reader.phone req.phone if req.email is not None: reader.email req.email if req.max_borrow is not None: reader.max_borrow req.max_borrow if req.status is not None: reader.status req.status if req.password is not None: reader.password req.password self.db.commit() return success_msg(修改成功) def delete(self, reader_id: int) - Result: 删除读者 :param reader_id: 读者ID :return: 统一响应 reader self.db.query(Reader).filter(Reader.id reader_id).first() if reader is None: raise BusinessException(读者不存在) self.db.delete(reader) self.db.commit() return success_msg(删除成功) def _to_map(self, reader: Reader) - dict: 读者实体转字典 :param reader: 读者实体 :return: 字典 return { id: reader.id, username: reader.username, card_no: reader.card_no, real_name: reader.real_name, gender: reader.gender, phone: reader.phone, email: reader.email, max_borrow: reader.max_borrow, status: reader.status, create_time: format_datetime(reader.create_time), }template div classpage-container div classsearch-bar el-select v-modelform.reader_id placeholder选择读者 filterable stylewidth:220px el-option v-forr in readers :keyr.id :label${r.real_name} (${r.card_no}) :valuer.id / /el-select el-select v-modelform.book_id placeholder选择图书 filterable stylewidth:280px el-option v-forb in books :keyb.id :label${b.title} (库存:${b.stock_count}) :valueb.id :disabledb.stock_count 0 / /el-select el-button typeprimary clickhandleLendel-iconSwitch //el-icon办理借书/el-button /div div classtable-card h3 stylemargin-bottom:16px;color:#303133当前在借图书/h3 el-table :databorrowingList stripe border stylewidth:100% el-table-column propreader_name label读者 min-width100 / el-table-column propcard_no label借书证号 min-width130 / el-table-column propbook_title label图书 min-width180 show-overflow-tooltip / el-table-column propborrow_time label借阅时间 min-width170 / el-table-column propdue_time label应还时间 min-width170 / el-table-column proprenew_count label续借次数 min-width90 / el-table-column propstatus_text label状态 min-width80 template #default{ row } el-tag :typerow.status 3 ? danger : warning sizesmall{{ row.status_text }}/el-tag /template /el-table-column el-table-column propfine label罚款(元) min-width90 / el-table-column label操作 min-width180 fixedright template #default{ row } el-button v-ifrow.status ! 2 typesuccess link clickhandleReturn(row)还书/el-button el-button v-ifrow.status 1 typeprimary link clickhandleRenew(row)续借/el-button /template /el-table-column /el-table div classpagination-wrap el-pagination v-model:current-pagepage v-model:page-sizepageSize :totaltotal layouttotal, sizes, prev, pager, next changeloadBorrowing / /div /div /div /template script setup /** 借阅管理页面 - 管理员办理借书/还书/续借 */ import { ref, reactive, onMounted } from vue import { ElMessage, ElMessageBox } from element-plus import { getAllReaders, getBookList, getBorrowList, lendBook, returnBook, renewBook } from /api const readers ref([]) const books ref([]) const borrowingList ref([]) const page ref(1) const pageSize ref(10) const total ref(0) const form reactive({ reader_id: null, book_id: null }) async function loadReaders() { const res await getAllReaders() readers.value res.data } async function loadBooks() { const res await getBookList({ page: 1, page_size: 100 }) books.value res.data.list } async function loadBorrowing() { const res await getBorrowList({ page: page.value, page_size: pageSize.value, active_only: 1 }) borrowingList.value res.data.list total.value res.data.total } async function handleLend() { if (!form.reader_id || !form.book_id) { ElMessage.warning(请选择读者和图书) return } await lendBook(form) ElMessage.success(借书成功) form.book_id null loadBooks() loadBorrowing() } async function handleReturn(row) { await ElMessageBox.confirm(确定为「${row.reader_name}」办理还书吗, 还书确认, { type: info }) const res await returnBook(row.id) ElMessage.success(res.msg) loadBooks() loadBorrowing() } async function handleRenew(row) { await ElMessageBox.confirm(确定为「${row.book_title}」办理续借吗, 续借确认, { type: info }) await renewBook(row.id) ElMessage.success(续借成功) loadBorrowing() } onMounted(() { loadReaders(); loadBooks(); loadBorrowing() }) /script
分享一套锋哥原创的基于Python的微信小程序图书馆(图书借阅)管理系统(FastAPI+Vue3)
大家好我是Java1234_小锋老师分享一套锋哥原创的基于Python的微信小程序图书馆(图书借阅)管理系统(FastAPIVue3)项目介绍随着移动互联网与智慧校园建设的不断推进传统图书馆借阅方式在效率、便捷性与数据统计能力方面已难以满足高校师生的日常需求。读者希望能够随时随地检索馆藏、办理借还与续借管理人员则需要对图书、读者与借阅业务进行可视化监控与精细化管理。针对上述问题本文设计并实现了一套基于微信小程序的图书馆图书借阅管理系统。系统采用前后端分离与多端协同架构后端基于 Python 语言与 FastAPI 框架提供 RESTful API使用 SQLAlchemy 完成对象关系映射以 MySQL 数据库库名 db_library持久化业务数据管理员端采用 Vue3、Vite、Element Plus 与 ECharts 构建 Web 管理后台实现数据看板、图书与分类管理、读者管理、借阅管理、轮播图维护以及个人中心等功能读者端基于微信小程序实现用户名密码登录与注册、图书浏览与检索、自助借阅、续借还书、个人资料与头像修改、密码修改等功能。系统在业务层实现了借阅上限校验、库存扣减与恢复、超期状态自动更新与罚款计算等规则。实践表明该系统结构清晰、接口规范、交互便捷能够有效提升图书借阅管理效率对同类校园信息化应用具有一定参考价值。源码下载链接: https://pan.baidu.com/s/1kzu7OgwVgto-_5Etlhotvg?pwd1234提取码: 1234系统展示核心代码 读者业务服务 from datetime import datetime from sqlalchemy import or_ from sqlalchemy.orm import Session from app.common.exceptions import BusinessException from app.common.result import Result, fail, page_result, success, success_msg from app.models.reader import Reader from app.schemas.reader import ReaderRequest from app.utils.datetime_util import format_datetime class ReaderService: 读者业务服务类 def __init__(self, db: Session): 构造读者服务 :param db: 数据库会话 self.db db def list_readers(self, page: int, page_size: int, keyword: str) - Result: 分页查询读者列表 :param page: 页码 :param page_size: 每页条数 :param keyword: 关键字 :return: 分页结果 query self.db.query(Reader) if keyword: query query.filter(or_( Reader.real_name.like(f%{keyword}%), Reader.username.like(f%{keyword}%), Reader.card_no.like(f%{keyword}%), )) total query.count() items query.order_by(Reader.id.desc()).offset((page - 1) * page_size).limit(page_size).all() list_data [self._to_map(r) for r in items] return page_result(list_data, total, page, page_size) def all_readers(self) - Result: 全部正常读者下拉用 :return: 读者简要列表 items self.db.query(Reader).filter(Reader.status 1).order_by(Reader.id.asc()).all() list_data [{ id: r.id, real_name: r.real_name, card_no: r.card_no, max_borrow: r.max_borrow, } for r in items] return success(list_data) def add(self, req: ReaderRequest) - Result: 新增读者 :param req: 请求体 :return: 统一响应 if self.db.query(Reader).filter(Reader.username req.username).count() 0: return fail(用户名已存在) if self.db.query(Reader).filter(Reader.card_no req.card_no).count() 0: return fail(借书证号已存在) reader Reader( usernamereq.username, passwordreq.password if req.password else 123456, card_noreq.card_no, real_namereq.real_name, genderreq.gender if req.gender is not None else 1, phonereq.phone, emailreq.email, max_borrowreq.max_borrow if req.max_borrow is not None else 5, statusreq.status if req.status is not None else 1, create_timedatetime.now(), ) self.db.add(reader) self.db.commit() return success_msg(添加成功) def update(self, reader_id: int, req: ReaderRequest) - Result: 修改读者 :param reader_id: 读者ID :param req: 请求体 :return: 统一响应 reader self.db.query(Reader).filter(Reader.id reader_id).first() if reader is None: raise BusinessException(读者不存在) if req.card_no is not None: reader.card_no req.card_no if req.real_name is not None: reader.real_name req.real_name if req.gender is not None: reader.gender req.gender if req.phone is not None: reader.phone req.phone if req.email is not None: reader.email req.email if req.max_borrow is not None: reader.max_borrow req.max_borrow if req.status is not None: reader.status req.status if req.password is not None: reader.password req.password self.db.commit() return success_msg(修改成功) def delete(self, reader_id: int) - Result: 删除读者 :param reader_id: 读者ID :return: 统一响应 reader self.db.query(Reader).filter(Reader.id reader_id).first() if reader is None: raise BusinessException(读者不存在) self.db.delete(reader) self.db.commit() return success_msg(删除成功) def _to_map(self, reader: Reader) - dict: 读者实体转字典 :param reader: 读者实体 :return: 字典 return { id: reader.id, username: reader.username, card_no: reader.card_no, real_name: reader.real_name, gender: reader.gender, phone: reader.phone, email: reader.email, max_borrow: reader.max_borrow, status: reader.status, create_time: format_datetime(reader.create_time), }template div classpage-container div classsearch-bar el-select v-modelform.reader_id placeholder选择读者 filterable stylewidth:220px el-option v-forr in readers :keyr.id :label${r.real_name} (${r.card_no}) :valuer.id / /el-select el-select v-modelform.book_id placeholder选择图书 filterable stylewidth:280px el-option v-forb in books :keyb.id :label${b.title} (库存:${b.stock_count}) :valueb.id :disabledb.stock_count 0 / /el-select el-button typeprimary clickhandleLendel-iconSwitch //el-icon办理借书/el-button /div div classtable-card h3 stylemargin-bottom:16px;color:#303133当前在借图书/h3 el-table :databorrowingList stripe border stylewidth:100% el-table-column propreader_name label读者 min-width100 / el-table-column propcard_no label借书证号 min-width130 / el-table-column propbook_title label图书 min-width180 show-overflow-tooltip / el-table-column propborrow_time label借阅时间 min-width170 / el-table-column propdue_time label应还时间 min-width170 / el-table-column proprenew_count label续借次数 min-width90 / el-table-column propstatus_text label状态 min-width80 template #default{ row } el-tag :typerow.status 3 ? danger : warning sizesmall{{ row.status_text }}/el-tag /template /el-table-column el-table-column propfine label罚款(元) min-width90 / el-table-column label操作 min-width180 fixedright template #default{ row } el-button v-ifrow.status ! 2 typesuccess link clickhandleReturn(row)还书/el-button el-button v-ifrow.status 1 typeprimary link clickhandleRenew(row)续借/el-button /template /el-table-column /el-table div classpagination-wrap el-pagination v-model:current-pagepage v-model:page-sizepageSize :totaltotal layouttotal, sizes, prev, pager, next changeloadBorrowing / /div /div /div /template script setup /** 借阅管理页面 - 管理员办理借书/还书/续借 */ import { ref, reactive, onMounted } from vue import { ElMessage, ElMessageBox } from element-plus import { getAllReaders, getBookList, getBorrowList, lendBook, returnBook, renewBook } from /api const readers ref([]) const books ref([]) const borrowingList ref([]) const page ref(1) const pageSize ref(10) const total ref(0) const form reactive({ reader_id: null, book_id: null }) async function loadReaders() { const res await getAllReaders() readers.value res.data } async function loadBooks() { const res await getBookList({ page: 1, page_size: 100 }) books.value res.data.list } async function loadBorrowing() { const res await getBorrowList({ page: page.value, page_size: pageSize.value, active_only: 1 }) borrowingList.value res.data.list total.value res.data.total } async function handleLend() { if (!form.reader_id || !form.book_id) { ElMessage.warning(请选择读者和图书) return } await lendBook(form) ElMessage.success(借书成功) form.book_id null loadBooks() loadBorrowing() } async function handleReturn(row) { await ElMessageBox.confirm(确定为「${row.reader_name}」办理还书吗, 还书确认, { type: info }) const res await returnBook(row.id) ElMessage.success(res.msg) loadBooks() loadBorrowing() } async function handleRenew(row) { await ElMessageBox.confirm(确定为「${row.book_title}」办理续借吗, 续借确认, { type: info }) await renewBook(row.id) ElMessage.success(续借成功) loadBorrowing() } onMounted(() { loadReaders(); loadBooks(); loadBorrowing() }) /script