目录
- 一、引言
- 二、环境准备
-
- [1. 下载并安装IntelliJ IDEA](#1. 下载并安装IntelliJ IDEA)
- [2. 安装飞算JavaAI插件](#2. 安装飞算JavaAI插件)
- [3. 登录飞算JavaAI](#3. 登录飞算JavaAI)
- 三、模块设计与编码
-
- [1. 飞算JavaAI生成基础模块](#1. 飞算JavaAI生成基础模块)
- [2. 核心代码展示](#2. 核心代码展示)
- 四、网页展示
-
- [1. 图书查询页](#1. 图书查询页)
- [2. 借阅记录页](#2. 借阅记录页)
- [3. 图书管理页](#3. 图书管理页)
- 五、优化与调试
-
- [1. 核心优化点](#1. 核心优化点)
- [2. 调试中遇到的问题及解决](#2. 调试中遇到的问题及解决)
- 六、自我感想
- 七、总结
一、引言
作为一名计算机专业的大二学生,图书馆是我每周必去的学习场所。但传统的图书借阅流程总让我感到困扰:想借一本专业参考书,要先在图书馆官网查馆藏,再到书架前按编号找书,遇到热门书还得排队预约;还书时偶尔忘记到期时间,超期罚款不说,还影响后续借阅权限。
恰逢《Java程序设计》课程要求完成一个"贴近生活的小型系统开发"作业,我便萌生了开发一款轻量化在线图书借阅平台的想法------既能实现"查书、借书、续借、预约"全流程线上化,又能通过到期提醒避免超期。但作为编程经验不算丰富的学生,我常因"需求梳理混乱""表结构设计不合理""重复编写基础代码"陷入瓶颈。
直到同学推荐了飞算JavaAI,这款工具彻底改变了我的开发体验:它不仅能生成规范代码,还能像"编程助教"一样引导我拆解需求、优化设计。接下来,我将以学生视角,完整记录用飞算JavaAI实现在线图书借阅平台的全过程,希望能给同样做课程设计的同学提供参考。
二、环境准备
参考学长分享的开发经验,结合学生常用的Windows环境,我用3步就完成了环境搭建,全程没遇到复杂配置,特别适合新手:
1. 下载并安装IntelliJ IDEA
作为学生,我优先选择IDEA社区版(免费且功能满足课程设计需求)。打开JetBrains中文官网(www.jetbrains.com.cn),在"开发者工具"中找到"IntelliJ IDEA",选择"Community"版本下载Windows安装包。
安装时注意两个细节:一是勾选"Add launchers dir to the PATH"(添加到环境变量),方便后续启动;二是勾选"Create Desktop Shortcut"(创建桌面快捷方式),避免后续找不到启动图标。全程点击"下一步"即可,约5分钟完成安装,比安装Photoshop简单多了。


2. 安装飞算JavaAI插件
打开IDEA后,点击顶部菜单栏"File → Settings → Plugins",在右侧搜索框输入"飞算JavaAI",找到红色的的插件,点击"Install"。

3. 登录飞算JavaAI
重启IDEA后,点击右侧"飞算JavaAI"面板中的"立即登录",用学生邮箱(QQ邮箱、校园邮箱均可)注册账号,完成手机验证后登录。登录成功后,面板会显示"需求分析→软件设计→工程代码生成"的全流程引导,和我之前用过的"只生成代码片段"的工具完全不同,更符合学生"从想法到落地"的开发需求。

三、模块设计与编码
在飞算JavaAI的辅助下,我不再像以前那样"想到哪写到哪",而是按"需求描述→拆解分析→设计→编码"的流程系统化开发。以下是在线图书借阅平台的完整开发过程:
1. 飞算JavaAI生成基础模块
飞算JavaAI最让我惊喜的是"支持口语化需求"------不需要专业术语,用学生的日常表达就能精准生成代码。我在插件面板的"需求编辑器"中输入:
"生成在线图书借阅平台基础模块,包含3类核心实体:用户(区分学生/管理员角色,学生有学号、班级,管理员有工号)、图书(图书编号、书名、作者、分类、馆藏数量、剩余可借数量)、借阅记录(记录ID、关联学号、关联图书编号、借阅时间、到期时间、归还状态);实现核心功能:学生注册/登录、图书查询(按书名/分类筛选)、图书借阅/续借/归还、超期提醒、管理员添加/编辑图书;技术栈:Spring Boot 3.x + MyBatis-Plus + MySQL 8.0,前端用Thymeleaf+Bootstrap(适配电脑端,方便学生在图书馆使用)。"

点击"提交需求"后,飞算JavaAI自动开始解析需求,不到10秒就将我的口语化描述拆解成7个可执行的关键点,还标了"必填"和"可优化"(学生可根据课程设计要求调整):
-
☑ 用户管理:需要用户管理功能,包括学生注册、登录以及管理员账户管理
-
☑ 图书管理:需要图书信息管理功能,支持添加、编辑图书信息
-
☑ 图书查询:学生按书名/分类筛选图书,显示图书详情和可借状态
-
☑ 借阅管理:需要借阅记录管理功能,包括图书借阅、续借和归还操作
-
☑ 历史记录 :需要借阅状态跟踪功能,支持查看当前借阅情况及历史记录
-
☑ 超期提醒:需要超期提醒功能,自动检测并通知逾期未还的图书
-
△ 控制功能:需要权限控制功能,区分学生与管理员角色访问不同模块

确认需求后,飞算JavaAI自动进入"接口设计→表结构设计→处理逻辑→生成源码"环节,全程无需手动干预。最终生成的项目结构清晰,核心包与类已完整创建,省去了我手动建包、写基础类的麻烦:





com.student.library
├─ entity // 实体类(映射数据库表)
│ ├─ User.java // 用户实体(学生/管理员)
│ ├─ Book.java // 图书实体
│ ├─ BorrowRecord.java // 借阅记录实体
│ └─ Category.java // 图书分类实体
├─ dto // 数据传输对象(接收前端请求参数)
│ ├─ UserRegisterDTO.java // 注册请求DTO
│ ├─ BookAddDTO.java // 图书添加DTO
│ ├─ BorrowBookDTO.java // 图书借阅DTO
│ └─ BookQueryDTO.java // 图书查询DTO
├─ vo // 视图对象(向前端返回数据)
│ ├─ BookDetailVO.java // 图书详情VO
│ ├─ BorrowRecordVO.java // 借阅记录VO
│ └─ UserBorrowVO.java // 学生借阅列表VO
├─ mapper // 数据访问接口(MyBatis-Plus)
│ ├─ UserMapper.java
│ ├─ BookMapper.java
│ └─ BorrowRecordMapper.java
├─ service // 业务逻辑层
│ ├─ UserService.java
│ ├─ BookService.java
│ └─ BorrowService.java
├─ controller // 接口控制层
│ ├─ UserController.java
│ ├─ BookController.java
│ └─ BorrowController.java
└─ config // 配置类(数据库、静态资源映射)
└─ WebConfig.java

2. 核心代码展示
飞算JavaAI生成的代码不仅结构规范,还自带参数校验、事务控制和详细注释,我仅需根据课程设计需求补充少量业务逻辑(比如超期提醒的时间计算),以下是关键模块的代码示例:
(1)entity包:核心实体类
User.java(用户实体,区分学生/管理员角色)
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;
/**
* <p>
* 用户实体类:映射user表,区分学生(role=0)和管理员(role=1)角色
* </p>
* @author feisuan-javaai(学生开发者二次优化)
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user") // 关联数据库表名
public class User {
/**
* 用户ID:主键,自增
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 账号:学生填学号,管理员填工号,唯一非空
*/
private String account;
/**
* 密码:存储BCrypt加密后的字符串(飞算提示:避免明文存储)
*/
private String password;
/**
* 姓名:用户真实姓名
*/
private String name;
/**
* 角色:0=学生,1=管理员(控制权限,学生不能添加图书)
*/
private Integer role;
/**
* 班级:仅学生有值,格式如"2024-计算机1班"
*/
private String className;
/**
* 邮箱:用于接收超期提醒、密码找回
*/
private String email;
/**
* 创建时间:用户注册时间,自动填充
*/
private LocalDateTime createTime;
}
Book.java(图书实体,含馆藏与可借数量)
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;
/**
* <p>
* 图书实体类:映射book表,记录图书基本信息与库存状态
* </p>
* @author feisuan-javaai(学生开发者二次优化)
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("book")
public class Book {
/**
* 图书编号:主键,自增(也可手动录入ISBN)
*/
@TableId(type = IdType.AUTO)
private Long bookNo;
/**
* 书名:非空,如《Java编程思想》
*/
private String bookName;
/**
* 作者:非空,多个作者用逗号分隔
*/
private String author;
/**
* 图书分类:关联category表,如"计算机类""文学类"
*/
private Long categoryId;
/**
* 出版社:图书出版机构
*/
private String publisher;
/**
* 出版日期:图书出版时间
*/
private LocalDateTime publishDate;
/**
* 馆藏总数:图书馆拥有的该图书总数量
*/
private Integer totalCount;
/**
* 剩余可借数量:totalCount - 已借出数量
*/
private Integer availableCount;
/**
* 图书简介:描述图书内容,帮助学生判断是否需要借阅
*/
private String description;
}
(2)dto包:数据传输对象(带参数校验)
BorrowBookDTO.java(学生借阅图书的请求DTO)
java
package com.student.library.dto;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* <p>
* 图书借阅请求DTO:接收学生借阅时的参数,含参数校验
* </p>
* @author feisuan-javaai
*/
@Data
public class BorrowBookDTO {
/**
* 学生ID:必填,从登录态获取,避免手动输入
*/
@NotNull(message = "学生ID不能为空")
private Long studentId;
/**
* 图书编号:必填,从图书详情页获取
*/
@NotNull(message = "图书编号不能为空")
private Long bookNo;
/**
* 借阅天数:必填,默认30天,最多60天(图书馆规则)
*/
@NotNull(message = "借阅天数不能为空")
private Integer borrowDays = 30;
}
BookAddDTO.java(管理员添加图书的请求DTO)
java
package com.student.library.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import lombok.Data;
import java.time.LocalDateTime;
/**
* <p>
* 图书添加请求DTO:接收管理员添加图书的参数,含参数校验
* </p>
* @author feisuan-javaai
*/
@Data
public class BookAddDTO {
/**
* 书名:必填,长度不超过100字
*/
@NotBlank(message = "书名不能为空")
private String bookName;
/**
* 作者:必填,多个作者用逗号分隔
*/
@NotBlank(message = "作者不能为空")
private String author;
/**
* 分类ID:必填,关联已有的图书分类
*/
@NotNull(message = "图书分类不能为空")
private Long categoryId;
/**
* 出版社:必填
*/
@NotBlank(message = "出版社不能为空")
private String publisher;
/**
* 出版日期:必填
*/
@NotNull(message = "出版日期不能为空")
private LocalDateTime publishDate;
/**
* 馆藏总数:必填,且必须为正整数
*/
@NotNull(message = "馆藏总数不能为空")
@Positive(message = "馆藏总数必须大于0")
private Integer totalCount;
/**
* 图书简介:非必填,为空时默认填充"暂无简介"
*/
private String description;
}
(3)vo包:视图对象(向前端隐藏敏感字段)
BookDetailVO.java(图书详情VO,给学生展示)
java
package com.student.library.vo;
import lombok.Data;
import java.time.LocalDateTime;
/**
* <p>
* 图书详情VO:封装学生查看图书时需要的信息,隐藏敏感字段(如分类ID)
* </p>
* @author feisuan-javaai
*/
@Data
public class BookDetailVO {
/**
* 图书编号
*/
private Long bookNo;
/**
* 书名
*/
private String bookName;
/**
* 作者
*/
private String author;
/**
* 图书分类名称:展示"计算机类",而非分类ID
*/
private String categoryName;
/**
* 出版社
*/
private String publisher;
/**
* 出版日期
*/
private LocalDateTime publishDate;
/**
* 剩余可借数量:学生最关心的字段,优先展示
*/
private Integer availableCount;
/**
* 图书简介
*/
private String description;
/**
* 是否可借:true=可借(availableCount>0),false=不可借(需预约)
*/
private Boolean canBorrow;
}
(4)service包:业务逻辑实现(含核心校验)
BorrowServiceImpl.java(借阅服务实现类,含借阅/续借逻辑)
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;
/**
* <p>
* 借阅服务实现类:处理图书借阅、续借、归还等核心业务
* </p>
* @author feisuan-javaai(学生开发者补充超期提醒逻辑)
*/
@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. 校验学生身份(必须是role=0的用户)
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. 校验借阅天数(最多60天,符合图书馆规则)
if (borrowBookDTO.getBorrowDays() > 60) {
throw new RuntimeException("单次借阅最多60天,请调整借阅天数");
}
// 4. 生成借阅记录
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); // 0=未归还,1=已归还
// 5. 更新图书剩余可借数量
book.setAvailableCount(book.getAvailableCount() - 1);
bookMapper.updateById(book);
// 6. 保存借阅记录
save(borrowRecord);
log.info("图书借阅成功:借阅记录ID={},到期时间={}", borrowRecord.getId(), borrowRecord.getDueDate());
return borrowRecord;
}
/**
* 学生续借图书(核心逻辑:校验是否超期、限制续借次数)
*/
@Override
@Transactional
public BorrowRecord renewBook(Long recordId) {
log.info("学生续借图书:借阅记录ID={}", recordId);
// 1. 查询借阅记录(必须存在且未归还)
BorrowRecord record = getById(recordId);
if (record == null) {
throw new RuntimeException("借阅记录不存在");
}
if (record.getReturnStatus() == 1) {
throw new RuntimeException("该图书已归还,无需续借");
}
// 2. 校验是否超期(超期后不能续借,需先归还并缴纳罚款)
if (LocalDate.now().isAfter(record.getDueDate())) {
throw new RuntimeException("图书已超期,请先归还并处理罚款");
}
// 3. 校验续借次数(最多续借1次,避免长期占用图书)
if (record.getRenewCount() >= 1) {
throw new RuntimeException("该图书已续借1次,无法再次续借");
}
// 4. 更新到期时间(续借30天)和续借次数
record.setDueDate(record.getDueDate().plusDays(30));
record.setRenewCount(record.getRenewCount() + 1);
updateById(record);
log.info("图书续借成功:借阅记录ID={},新到期时间={}", recordId, record.getDueDate());
return record;
}
/**
* 查询学生的借阅记录(含超期提醒)
*/
@Override
public List<BorrowRecordVO> getStudentBorrowRecords(Long studentId) {
// 1. 查询该学生的所有未归还借阅记录
List<BorrowRecord> recordList = lambdaQuery()
.eq(BorrowRecord::getStudentId, studentId)
.eq(BorrowRecord::getReturnStatus, 0)
.list();
// 2. 转换为VO,补充图书名称、作者,添加超期提醒
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时,卡片右上角显示"无库存"红色标签,避免学生白跑一趟;支持分页(每页12本图书),符合学生浏览习惯。
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图书查询 - 校园图书馆系统</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<style>
.category-item {
transition: all 0.2s;
}
.category-item:hover, .category-item.active {
background-color: #0d6efd;
color: white !important;
}
.book-card {
transition: transform 0.3s, box-shadow 0.3s;
}
.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="#">
<i class="fa fa-book mr-2"></i>校园图书馆
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link active" href="book-search.html">图书查询</a>
</li>
<li class="nav-item">
<a class="nav-link" href="borrowing-record.html">借阅记录</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">个人中心</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
<i class="fa fa-user-circle"></i> 张同学
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#">个人信息</a></li>
<li><a class="dropdown-item" href="#">修改密码</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">退出登录</a></li>
</ul>
</li>
</ul>
</div>
</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">
<i class="fa fa-search mr-1"></i>搜索
</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>
<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>
<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>
<a href="#" class="list-group-item list-group-item-action category-item">
艺术类
</a>
</div>
</div>
</div>
<!-- 图书列表 -->
<div class="col-md-9">
<div class="row">
<!-- 图书卡片1 -->
<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>
<!-- 图书卡片2 -->
<div class="col-md-4 mb-4">
<div class="card book-card h-100 position-relative">
<img src="https://picsum.photos/id/20/300/400" class="card-img-top" alt="百年孤独">
<div class="card-body">
<h5 class="card-title">百年孤独</h5>
<p class="card-text text-muted">作者:加西亚·马尔克斯</p>
<p class="card-text">
<small>剩余可借:<span class="text-success">3</span>/8</small>
</p>
<a href="#" class="btn btn-primary btn-sm w-100">查看详情</a>
</div>
</div>
</div>
<!-- 图书卡片3 -->
<div class="col-md-4 mb-4">
<div class="card book-card h-100 position-relative">
<span class="badge bg-danger no-stock">无库存</span>
<img src="https://picsum.photos/id/180/300/400" class="card-img-top" alt="微观经济学">
<div class="card-body">
<h5 class="card-title">微观经济学</h5>
<p class="card-text text-muted">作者:曼昆</p>
<p class="card-text">
<small>剩余可借:<span class="text-danger">0</span>/5</small>
</p>
<a href="#" class="btn btn-primary btn-sm w-100">查看详情</a>
</div>
</div>
</div>
<!-- 图书卡片4 -->
<div class="col-md-4 mb-4">
<div class="card book-card h-100 position-relative">
<img src="https://picsum.photos/id/99/300/400" class="card-img-top" alt="数据结构与算法分析">
<div class="card-body">
<h5 class="card-title">数据结构与算法分析</h5>
<p class="card-text text-muted">作者:Mark Allen Weiss</p>
<p class="card-text">
<small>剩余可借:<span class="text-success">2</span>/6</small>
</p>
<a href="#" class="btn btn-primary btn-sm w-100">查看详情</a>
</div>
</div>
</div>
<!-- 图书卡片5 -->
<div class="col-md-4 mb-4">
<div class="card book-card h-100 position-relative">
<img src="https://picsum.photos/id/106/300/400" class="card-img-top" alt="明朝那些事儿">
<div class="card-body">
<h5 class="card-title">明朝那些事儿</h5>
<p class="card-text text-muted">作者:当年明月</p>
<p class="card-text">
<small>剩余可借:<span class="text-success">7</span>/12</small>
</p>
<a href="#" class="btn btn-primary btn-sm w-100">查看详情</a>
</div>
</div>
</div>
<!-- 图书卡片6 -->
<div class="col-md-4 mb-4">
<div class="card book-card h-100 position-relative">
<img src="https://picsum.photos/id/119/300/400" class="card-img-top" alt="高等数学(第七版)">
<div class="card-body">
<h5 class="card-title">高等数学(第七版)</h5>
<p class="card-text text-muted">作者:同济大学数学系</p>
<p class="card-text">
<small>剩余可借:<span class="text-success">10</span>/20</small>
</p>
<a href="#" class="btn btn-primary btn-sm w-100">查看详情</a>
</div>
</div>
</div>
</div>
<!-- 分页 -->
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center">
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1">上一页</a>
</li>
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item">
<a class="page-link" href="#">下一页</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// 分类筛选功能
document.querySelectorAll('.category-item').forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
// 移除所有active类
document.querySelectorAll('.category-item').forEach(i => {
i.classList.remove('active');
});
// 给当前点击项添加active类
this.classList.add('active');
// 这里可以添加实际筛选逻辑
});
});
// 搜索功能
document.getElementById('searchBtn').addEventListener('click', function() {
const searchText = document.getElementById('searchInput').value.trim();
if (searchText) {
alert(`搜索内容: ${searchText}`);
// 这里可以添加实际搜索逻辑
} else {
alert('请输入搜索内容');
}
});
</script>
</body>
</html>

2. 借阅记录页
- 布局:表格形式展示所有未归还的借阅记录,列包含"图书名称""作者""借阅时间""到期时间""剩余天数""操作";
- 核心功能:剩余天数小于3天时,"剩余天数"列显示红色字体并标注"即将超期";点击"续借"按钮可完成续借,点击"归还"按钮可预约归还(管理员确认后完成归还);
- 细节设计:表格上方有"超期提醒"模块,显示该学生所有超期未还的图书,避免学生遗漏。
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>借阅记录 - 校园图书馆系统</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<style>
.overdue-alert {
border-left: 4px solid #dc3545;
}
.soon-expire {
color: #dc3545;
font-weight: bold;
}
.table-hover tbody tr:hover {
background-color: rgba(0,0,0,0.05);
}
</style>
</head>
<body>
<!-- 导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-4">
<div class="container">
<a class="navbar-brand" href="#">
<i class="fa fa-book mr-2"></i>校园图书馆
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="book-search.html">图书查询</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="borrowing-record.html">借阅记录</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">个人中心</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
<i class="fa fa-user-circle"></i> 张同学
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#">个人信息</a></li>
<li><a class="dropdown-item" href="#">修改密码</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">退出登录</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<h3 class="mb-4">借阅记录</h3>
<!-- 超期提醒 -->
<div class="alert alert-danger overdue-alert mb-4">
<h5 class="alert-heading"><i class="fa fa-exclamation-circle mr-2"></i>超期提醒</h5>
<p>您有1本图书已超期未还,请尽快归还,以免影响您的借阅权限。</p>
<ul>
<li>《C程序设计》 - 已超期3天</li>
</ul>
</div>
<!-- 借阅记录表格 -->
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th>图书名称</th>
<th>作者</th>
<th>借阅时间</th>
<th>到期时间</th>
<th>剩余天数</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>Java编程思想</td>
<td>Bruce Eckel</td>
<td>2023-05-10</td>
<td>2023-06-10</td>
<td class="soon-expire">2天 <span class="badge bg-danger">即将超期</span></td>
<td>
<button class="btn btn-sm btn-primary" onclick="renewBook(1)">续借</button>
<button class="btn btn-sm btn-secondary ms-1" onclick="reserveReturn(1)">归还预约</button>
</td>
</tr>
<tr>
<td>数据结构与算法分析</td>
<td>Mark Allen Weiss</td>
<td>2023-05-15</td>
<td>2023-06-15</td>
<td>7天</td>
<td>
<button class="btn btn-sm btn-primary" onclick="renewBook(2)">续借</button>
<button class="btn btn-sm btn-secondary ms-1" onclick="reserveReturn(2)">归还预约</button>
</td>
</tr>
<tr>
<td>明朝那些事儿</td>
<td>当年明月</td>
<td>2023-05-20</td>
<td>2023-06-20</td>
<td>12天</td>
<td>
<button class="btn btn-sm btn-primary" onclick="renewBook(3)">续借</button>
<button class="btn btn-sm btn-secondary ms-1" onclick="reserveReturn(3)">归还预约</button>
</td>
</tr>
<tr>
<td>C程序设计</td>
<td>谭浩强</td>
<td>2023-04-25</td>
<td>2023-05-25</td>
<td class="soon-expire">-3天 <span class="badge bg-danger">已超期</span></td>
<td>
<button class="btn btn-sm btn-primary" disabled>续借</button>
<button class="btn btn-sm btn-secondary ms-1" onclick="reserveReturn(4)">归还预约</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// 续借功能
function renewBook(bookId) {
if (confirm('确定要续借这本书吗?续借将延长30天借阅期。')) {
alert('续借成功!新的到期时间将延长30天。');
// 这里可以添加实际续借逻辑
}
}
// 归还预约功能
function reserveReturn(bookId) {
if (confirm('确定要预约归还这本书吗?管理员确认后,请在3天内到图书馆归还。')) {
alert('归还预约已提交,请留意系统通知。');
// 这里可以添加实际归还预约逻辑
}
}
</script>
</body>
</html>

3. 图书管理页
- 布局:顶部有"添加图书"按钮,下方是图书管理表格,列包含"图书编号""书名""作者""馆藏总数""剩余可借数量""操作";
- 核心功能:点击"添加图书"跳转至添加页面(带参数校验,比如馆藏数量必须为正整数);点击"编辑"可修改图书信息(如更新简介),点击"下架"可将图书设为"不可借"(用于图书维护);
- 细节设计:剩余可借数量小于总数量的1/3时,"剩余可借数量"列显示黄色字体,提醒管理员补充馆藏。
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图书管理 - 校园图书馆系统</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<style>
.low-stock {
color: #fd7e14;
font-weight: bold;
}
.sidebar {
min-height: calc(100vh - 56px);
background-color: #f8f9fa;
border-right: 1px solid #dee2e6;
}
.sidebar .nav-link {
color: #333;
transition: all 0.2s;
}
.sidebar .nav-link.active {
background-color: #0d6efd;
color: white;
}
.sidebar .nav-link:hover:not(.active) {
background-color: #e9ecef;
}
</style>
</head>
<body>
<!-- 顶部导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container-fluid">
<a class="navbar-brand" href="#">
<i class="fa fa-book mr-2"></i>图书馆管理系统
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown">
<i class="fa fa-user-circle"></i> 管理员
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#">个人信息</a></li>
<li><a class="dropdown-item" href="#">修改密码</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">退出登录</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<!-- 侧边栏 -->
<div class="col-md-2 d-none d-md-block sidebar p-3">
<ul class="nav flex-column">
<li class="nav-item mb-1">
<a class="nav-link active" href="admin-book-management.html">
<i class="fa fa-book mr-2"></i>图书管理
</a>
</li>
<li class="nav-item mb-1">
<a class="nav-link" href="#">
<i class="fa fa-users mr-2"></i>读者管理
</a>
</li>
<li class="nav-item mb-1">
<a class="nav-link" href="#">
<i class="fa fa-exchange mr-2"></i>借阅管理
</a>
</li>
<li class="nav-item mb-1">
<a class="nav-link" href="#">
<i class="fa fa-bar-chart mr-2"></i>统计分析
</a>
</li>
<li class="nav-item mb-1">
<a class="nav-link" href="#">
<i class="fa fa-cog mr-2"></i>系统设置
</a>
</li>
</ul>
</div>
<!-- 主内容区 -->
<main class="col-md-10 ms-sm-auto px-md-4 py-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h3>图书管理</h3>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addBookModal">
<i class="fa fa-plus mr-1"></i>添加图书
</button>
</div>
<!-- 图书管理表格 -->
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th>图书编号</th>
<th>书名</th>
<th>作者</th>
<th>分类</th>
<th>馆藏总数</th>
<th>剩余可借</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>BOOK001</td>
<td>Java编程思想</td>
<td>Bruce Eckel</td>
<td>计算机类</td>
<td>10</td>
<td class="low-stock">3</td>
<td><span class="badge bg-success">可借</span></td>
<td>
<button class="btn btn-sm btn-primary" onclick="editBook('BOOK001')">编辑</button>
<button class="btn btn-sm btn-warning ms-1" onclick="下架图书('BOOK001')">下架</button>
</td>
</tr>
<tr>
<td>BOOK002</td>
<td>百年孤独</td>
<td>加西亚·马尔克斯</td>
<td>文学类</td>
<td>8</td>
<td>3</td>
<td><span class="badge bg-success">可借</span></td>
<td>
<button class="btn btn-sm btn-primary" onclick="editBook('BOOK002')">编辑</button>
<button class="btn btn-sm btn-warning ms-1" onclick="下架图书('BOOK002')">下架</button>
</td>
</tr>
<tr>
<td>BOOK003</td>
<td>微观经济学</td>
<td>曼昆</td>
<td>经管类</td>
<td>5</td>
<td class="low-stock">1</td>
<td><span class="badge bg-success">可借</span></td>
<td>
<button class="btn btn-sm btn-primary" onclick="editBook('BOOK003')">编辑</button>
<button class="btn btn-sm btn-warning ms-1" onclick="下架图书('BOOK003')">下架</button>
</td>
</tr>
<tr>
<td>BOOK004</td>
<td>高等数学(第七版)</td>
<td>同济大学数学系</td>
<td>理工类</td>
<td>20</td>
<td>10</td>
<td><span class="badge bg-success">可借</span></td>
<td>
<button class="btn btn-sm btn-primary" onclick="editBook('BOOK004')">编辑</button>
<button class="btn btn-sm btn-warning ms-1" onclick="下架图书('BOOK004')">下架</button>
</td>
</tr>
<tr>
<td>BOOK005</td>
<td>C程序设计</td>
<td>谭浩强</td>
<td>计算机类</td>
<td>15</td>
<td class="low-stock">4</td>
<td><span class="badge bg-danger">不可借</span></td>
<td>
<button class="btn btn-sm btn-primary" onclick="editBook('BOOK005')">编辑</button>
<button class="btn btn-sm btn-success ms-1" onclick="上架图书('BOOK005')">上架</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 分页 -->
<nav aria-label="Page navigation" class="mt-4">
<ul class="pagination justify-content-center">
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1">上一页</a>
</li>
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item">
<a class="page-link" href="#">下一页</a>
</li>
</ul>
</nav>
</div>
</div>
</main>
</div>
</div>
<!-- 添加图书模态框 -->
<div class="modal fade" id="addBookModal" tabindex="-1" aria-labelledby="addBookModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addBookModalLabel">添加图书</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="addBookForm">
<div class="row mb-3">
<div class="col-md-6">
<label for="bookName" class="form-label">书名 <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="bookName" required>
</div>
<div class="col-md-6">
<label for="author" class="form-label">作者 <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="author" required>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label for="category" class="form-label">分类 <span class="text-danger">*</span></label>
<select class="form-select" id="category" required>
<option value="">请选择分类</option>
<option value="计算机类">计算机类</option>
<option value="文学类">文学类</option>
<option value="经管类">经管类</option>
<option value="理工类">理工类</option>
<option value="医学类">医学类</option>
<option value="历史类">历史类</option>
<option value="艺术类">艺术类</option>
</select>
</div>
<div class="col-md-6">
<label for="publisher" class="form-label">出版社</label>
<input type="text" class="form-control" id="publisher">
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label for="totalCopies" class="form-label">馆藏总数 <span class="text-danger">*</span></label>
<input type="number" class="form-control" id="totalCopies" min="1" required>
<div class="form-text">请输入正整数</div>
</div>
<div class="col-md-6">
<label for="publicationDate" class="form-label">出版日期</label>
<input type="date" class="form-control" id="publicationDate">
</div>
</div>
<div class="mb-3">
<label for="description" class="form-label">图书简介</label>
<textarea class="form-control" id="description" rows="3"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" onclick="saveBook()">保存</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// 编辑图书
function editBook(bookId) {
alert(`编辑图书:${bookId}`);
// 这里可以添加实际编辑逻辑,通常会打开编辑模态框并填充数据
}
// 下架图书
function 下架图书(bookId) {
if (confirm(`确定要将图书 ${bookId} 下架吗?下架后读者将无法借阅。`)) {
alert(`图书 ${bookId} 已成功下架`);
// 这里可以添加实际下架逻辑
}
}
// 上架图书
function 上架图书(bookId) {
if (confirm(`确定要将图书 ${bookId} 上架吗?上架后读者可以正常借阅。`)) {
alert(`图书 ${bookId} 已成功上架`);
// 这里可以添加实际上架逻辑
}
}
// 保存图书
function saveBook() {
// 简单的表单验证
const bookName = document.getElementById('bookName').value;
const author = document.getElementById('author').value;
const category = document.getElementById('category').value;
const totalCopies = document.getElementById('totalCopies').value;
if (!bookName || !author || !category || !totalCopies) {
alert('请填写所有必填字段');
return;
}
if (parseInt(totalCopies) <= 0) {
alert('馆藏总数必须为正整数');
return;
}
// 模拟保存成功
alert('图书添加成功!');
// 关闭模态框
const modal = bootstrap.Modal.getInstance(document.getElementById('addBookModal'));
modal.hide();
// 重置表单
document.getElementById('addBookForm').reset();
}
</script>
</body>
</html>

五、优化与调试
生成源码后,我根据课程设计要求做了3处关键优化,并解决了2个常见问题:
1. 核心优化点
- 密码加密 :飞算在代码注释中提醒"密码需加密存储",我集成了Spring Security的BCrypt加密,在UserServiceImpl的register方法中,将
user.setPassword(request.getPassword())改为user.setPassword(bCryptPasswordEncoder.encode(request.getPassword())),登录时用bCryptPasswordEncoder.matches()校验,避免明文存储密码。 - 超期提醒:在BorrowServiceImpl的getStudentBorrowRecords方法中,添加"剩余天数计算"逻辑,当剩余天数≤3天时,在前端显示红色提醒;超期后,禁止续借并提示"需先归还",符合图书馆实际规则。
- 图书分类管理:飞算生成的基础模块中没有"图书分类添加"功能,我在管理员端补充了CategoryController和CategoryService,支持管理员添加/编辑图书分类(如"考研类""小说类"),让图书分类更灵活。
2. 调试中遇到的问题及解决
- 问题1:启动项目时提示"数据库连接失败"------原因是application.yml中MySQL的password是默认值,我改成自己本地数据库的密码后,重启项目恢复正常。
- 问题2 :学生借阅图书后,图书的"剩余可借数量"未减少------检查代码发现,BorrowServiceImpl的borrowBook方法中,忘记调用
bookMapper.updateById(book)更新图书信息,补充该代码后问题解决。
六、自我感想
作为一名学生,这次用飞算JavaAI开发在线图书借阅平台,让我收获远超"完成课程设计"的目标:
-
需求梳理不再"迷茫":以前做项目总把"想要一个借阅平台"停留在模糊想法阶段,不知道怎么拆分成"学生能查书""管理员能加书"等具体功能。飞算的"需求拆解"环节帮我把口语化描述转化为6个可执行关键点,还补充了"续借次数限制""超期校验"等我没考虑到的细节,让我明白"好的需求是能落地的小功能集合"。
-
基础代码不再"重复写":实体类的get/set方法、Mapper的CRUD接口、DTO的参数校验------这些以前要写1天的基础代码,飞算20分钟就生成了,而且代码带完整注释(比如"剩余可借数量=总数量-已借出数量")。我不需要再纠结"表结构字段怎么设计",而是能专注于"超期提醒""续借逻辑"等核心业务,开发效率提升了3倍。
-
解决问题更"有思路":调试时遇到"借阅后库存不更新",我顺着飞算生成的代码注释"需更新图书的availableCount",很快定位到"忘记调用update方法"的问题;以前遇到bug会慌,现在知道从"业务逻辑流程"和"代码注释提示"中找解决方向,这种思维对后续学习很有帮助。
七、总结
这次开发让我明白,对学生而言,飞算JavaAI不是"代替编程",而是"降低开发门槛"------它帮我们解决了"基础代码繁琐""需求梳理混乱"的痛点,让我们能在有限的课程设计时间内,开发出功能完整、逻辑规范的系统。
当然,这个平台还有很多可优化的地方:比如添加"图书预约"功能(热门图书无库存时学生可预约)、对接图书馆的罚款系统(超期后自动计算罚款金额)。后续我会继续用飞算JavaAI迭代,比如在"需求编辑器"中输入"添加图书预约功能,支持学生预约无库存图书,有库存时自动提醒",进一步完善平台功能。
最后,我想给其他做课程设计的同学一个建议:如果遇到"不知道怎么开始""代码写不下去"的问题,不妨试试飞算JavaAI------它不仅能帮你生成代码,更能引导你养成"先梳理需求、再设计、最后编码"的规范开发习惯,这对我们未来的学习和工作都至关重要。