一、引言
图书馆是学习的重要场所,但传统借阅流程存在查书难、预约排队、超期罚款等问题。本次项目旨在设计并实现一个轻量化的在线图书借阅平台,涵盖查书、借书、续借、预约及到期提醒等全流程线上化功能。作为课程设计项目,重点在于通过 AI 辅助工具提升开发效率,规范代码结构,确保系统逻辑的完整性与可维护性。
二、环境准备
基于 Windows 环境,完成以下基础配置即可开始开发:
1. 下载并安装 IntelliJ IDEA
选择 IDEA 社区版(免费且满足需求)。访问 JetBrains 官网下载 Windows 安装包。安装时建议勾选'Add launchers dir to the PATH'以便环境变量配置,以及'Create Desktop Shortcut'方便启动。
2. 安装 AI 编程插件
打开 IDEA,进入 File → Settings → Plugins,搜索并安装相应的 AI 辅助插件。重启 IDE 后登录账号,即可使用需求分析、代码生成等功能。
3. 登录与初始化
登录成功后,面板将提供从需求分析到工程代码生成的全流程引导,支持将口语化需求转化为可执行的开发任务。

三、模块设计与编码
在 AI 辅助下,采用'需求描述→拆解分析→设计→编码'的流程进行系统化开发。
1. 需求分析与模块生成
在需求编辑器中输入核心功能描述,例如:'生成在线图书借阅平台基础模块,包含用户(学生/管理员)、图书、借阅记录三类实体;实现注册登录、图书查询、借阅续借归还、超期提醒等功能;技术栈 Spring Boot 3.x + MyBatis-Plus + MySQL 8.0,前端 Thymeleaf+Bootstrap。'
提交后,AI 会自动解析需求,拆解为关键执行点(如用户管理、图书管理、权限控制等),并自动生成项目骨架。

生成的项目结构清晰,包含以下核心包:
com.student.library
├─ entity // 实体类
├─ dto // 数据传输对象
├─ vo // 视图对象
├─ mapper // 数据访问接口
├─ service // 业务逻辑层
├─ controller // 接口控制层
└─ config // 配置类
2. 核心代码展示
(1)Entity 包:核心实体类
User.java(用户实体)
package com.student.library.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String account;
private String password;
private String name;
private Integer role;
private String className;
private String email;
private LocalDateTime createTime;
}
Book.java(图书实体)
package com.student.library.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("book")
public class Book {
@TableId(type = IdType.AUTO)
private Long bookNo;
private String bookName;
private String author;
private Long categoryId;
private String publisher;
private LocalDateTime publishDate;
private Integer totalCount;
private Integer availableCount;
private String description;
}
(2)DTO 包:数据传输对象
BorrowBookDTO.java(借阅请求)
package com.student.library.dto;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class BorrowBookDTO {
@NotNull(message = "学生 ID 不能为空")
private Long studentId;
@NotNull(message = "图书编号不能为空")
private Long bookNo;
@NotNull(message = "借阅天数不能为空")
private Integer borrowDays = 30;
}
(3)VO 包:视图对象
BookDetailVO.java(图书详情)
package com.student.library.vo;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class BookDetailVO {
private Long bookNo;
private String bookName;
private String author;
private String categoryName;
private String publisher;
private LocalDateTime publishDate;
private Integer availableCount;
private String description;
private Boolean canBorrow;
}
(4)Service 包:业务逻辑实现
BorrowServiceImpl.java(借阅服务)
package com.student.library.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.student.library.dto.BorrowBookDTO;
import com.student.library.entity.Book;
import com.student.library.entity.BorrowRecord;
import com.student.library.entity.User;
import com.student.library.mapper.BookMapper;
import com.student.library.mapper.BorrowRecordMapper;
import com.student.library.mapper.UserMapper;
import com.student.library.service.BorrowService;
import com.student.library.vo.BorrowRecordVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class BorrowServiceImpl extends ServiceImpl<BorrowRecordMapper, BorrowRecord> implements BorrowService {
private final BorrowRecordMapper borrowRecordMapper;
private final BookMapper bookMapper;
private final UserMapper userMapper;
@Override
@Transactional
public BorrowRecord borrowBook(BorrowBookDTO borrowBookDTO) {
log.info("学生借阅图书:学生 ID={}, 图书编号={}, 借阅天数={}",
borrowBookDTO.getStudentId(), borrowBookDTO.getBookNo(), borrowBookDTO.getBorrowDays());
// 1. 校验学生身份
User student = userMapper.selectById(borrowBookDTO.getStudentId());
if (student == null || student.getRole() != 0) {
throw new RuntimeException("无效的学生账号,无法借阅图书");
}
// 2. 校验图书状态
Book book = bookMapper.selectById(borrowBookDTO.getBookNo());
if (book == null) {
throw new RuntimeException("该图书不存在");
}
if (book.getAvailableCount() <= 0) {
throw new RuntimeException("该图书已无库存,可尝试预约");
}
// 3. 生成借阅记录
BorrowRecord borrowRecord = new BorrowRecord();
borrowRecord.setStudentId(borrowBookDTO.getStudentId());
borrowRecord.setBookNo(borrowBookDTO.getBookNo());
borrowRecord.setBorrowDate(LocalDate.now());
borrowRecord.setDueDate(LocalDate.now().plusDays(borrowBookDTO.getBorrowDays()));
borrowRecord.setReturnStatus(0);
// 4. 更新库存
book.setAvailableCount(book.getAvailableCount() - 1);
bookMapper.updateById(book);
save(borrowRecord);
return borrowRecord;
}
@Override
@Transactional
public BorrowRecord renewBook(Long recordId) {
BorrowRecord record = getById(recordId);
if (record == null) {
throw new RuntimeException("借阅记录不存在");
}
if (record.getReturnStatus() == 1) {
throw new RuntimeException("该图书已归还,无需续借");
}
if (LocalDate.now().isAfter(record.getDueDate())) {
throw new RuntimeException("图书已超期,请先归还并处理罚款");
}
if (record.getRenewCount() >= 1) {
throw new RuntimeException("该图书已续借 1 次,无法再次续借");
}
record.setDueDate(record.getDueDate().plusDays(30));
record.setRenewCount(record.getRenewCount() + 1);
updateById(record);
return record;
}
@Override
public List<BorrowRecordVO> getStudentBorrowRecords(Long studentId) {
List<BorrowRecord> recordList = lambdaQuery()
.eq(BorrowRecord::getStudentId, studentId)
.eq(BorrowRecord::getReturnStatus, 0)
.list();
return recordList.stream().map(record -> {
BorrowRecordVO vo = new BorrowRecordVO();
BeanUtils.copyProperties(record, vo);
Book book = bookMapper.selectById(record.getBookNo());
vo.setBookName(book.getBookName());
vo.setAuthor(book.getAuthor());
long daysLeft = ChronoUnit.DAYS.between(LocalDate.now(), record.getDueDate());
vo.setDaysLeft((int) daysLeft);
if (daysLeft < 0) {
vo.setOverdueReminder("已超期" + (-daysLeft) + "天,请尽快归还");
} else if (daysLeft <= 3) {
vo.setOverdueReminder("即将超期,剩余" + daysLeft + "天");
} else {
vo.setOverdueReminder("正常借阅中");
}
return vo;
}).collect(Collectors.toList());
}
}
四、网页展示
前端采用 Bootstrap 实现响应式布局,适配电脑端场景。
1. 图书查询页
顶部搜索栏支持按书名、作者检索,左侧分类筛选,中间卡片式展示图书列表。库存为 0 时显示红色标签,支持分页。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>图书查询 - 校园图书馆系统</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.category-item:hover, .category-item.active { background-color: #0d6efd; color: white !important; }
.book-card:hover { transform: translateY(-5px); box-shadow: 0 10px 20px rgba(0,0,0,0.1); }
.no-stock { position: absolute; top: 10px; right: 10px; }
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-4">
<div class="container"><a class="navbar-brand" href="#">校园图书馆</a></div>
</nav>
<div class="container">
<h3 class="mb-4">图书查询</h3>
<div class="row mb-4">
<div class="col-md-8 offset-md-2">
<div class="input-group">
<input type="text" class="form-control" placeholder="请输入书名或作者进行搜索..." id="searchInput">
<button class="btn btn-primary" type="button" id="searchBtn">搜索</button>
</div>
</div>
</div>
<div class="row">
<div class="col-md-3 mb-4">
<div class="card">
<div class="card-header bg-light"><h5 class="mb-0">图书分类</h5></div>
<div class="list-group list-group-flush">
<a href="#" class="list-group-item list-group-item-action category-item active">全部图书</a>
<a href="#" class="list-group-item list-group-item-action category-item">计算机类</a>
<a href="#" class="list-group-item list-group-item-action category-item">文学类</a>
</div>
</div>
</div>
<div class="col-md-9">
<!-- 图书卡片示例 -->
<div class="col-md-4 mb-4">
<div class="card book-card h-100 position-relative">
<img src="https://picsum.photos/id/24/300/400" class="card-img-top" alt="Java 编程思想">
<div class="card-body">
<h5 class="card-title">Java 编程思想</h5>
<p class="card-text text-muted">作者:Bruce Eckel</p>
<p class="card-text"><small>剩余可借:<span class="text-success">5</span>/10</small></p>
<a href="#" class="btn btn-primary btn-sm w-100">查看详情</a>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

2. 借阅记录页
表格展示未归还记录,列包含图书名称、到期时间、剩余天数。剩余天数小于 3 天显示红色预警,支持续借与归还预约。

3. 图书管理页
管理员端页面,支持添加、编辑、下架图书。库存低于 1/3 时显示黄色提示,便于补充馆藏。

五、优化与调试
1. 核心优化点
- 密码加密:集成 Spring Security 的 BCrypt 加密,避免明文存储密码。
- 超期提醒:在 Service 层计算剩余天数,前端根据数值动态渲染警告信息。
- 分类管理:补充 CategoryController 和 Service,支持管理员灵活维护图书分类。
2. 常见问题解决
- 数据库连接失败:检查
application.yml中的 MySQL 密码配置是否正确。 - 库存未减少:确认
borrowBook方法中是否调用了bookMapper.updateById(book)更新库存。
六、总结
本项目展示了如何利用 AI 辅助工具快速构建功能完整的图书管理系统。通过规范的需求拆解与代码生成,有效降低了基础代码编写成本,使开发者能更专注于核心业务逻辑的实现。后续可进一步扩展预约功能、罚款系统等模块,以适应更复杂的实际场景。

