基于“SpringBoot+uniapp的考研书库微信小程序设计与实现7000字论文
摘要
本文设计并实现了一个基于 SpringBoot 后端和 uniapp 前端的考研书库微信小程序,旨在为考研学生提供便捷的电子资料查询、在线学习和社交交流平台。系统采用前后端分离架构,通过 RESTful API 实现数据交互,支持用户注册登录、资料分类检索、笔记共享、学习计划管理等功能。论文详细阐述了系统需求分析、架构设计、数据库设计、功能模块实现及测试评估过程,最终验证了系统的可行性和实用性。
关键词
SpringBoot;uniapp;微信小程序;考研书库;在线学习平台
1 引言
1.1 研究背景与意义
随着考研人数的逐年增长,考生对优质学习资源的需求日益迫切。传统的考研资料获取方式存在信息分散、更新不及时、检索困难等问题,无法满足考生高效备考的需求。开发一个集资料整合、学习管理和社交交流于一体的考研书库平台,具有重要的现实意义:
- 整合优质考研资源,解决信息碎片化问题
- 提供个性化学习支持,提高备考效率
- 构建学习社区,促进考生间的交流与互助
- 降低学习成本,实现资源共享与优化配置
1.2 国内外研究现状
国内外针对在线学习平台的研究已经取得了一定进展:
- 国外:Coursera、edX 等平台提供了丰富的课程资源,但针对考研的专业化平台较少
- 国内:考研帮、新东方在线等平台主要以课程服务为主,资料共享功能相对薄弱
- 技术层面:SpringBoot 框架在后端开发中广泛应用,uniapp 在跨平台小程序开发中展现出显著优势
然而,现有的考研学习平台在资料整合深度、个性化服务和社交互动方面仍存在不足。
1.3 研究内容与目标
本文研究内容包括:
- 考研书库微信小程序的需求分析与功能设计
- 基于 SpringBoot 的后端架构设计与实现
- 基于 uniapp 的前端界面开发与交互实现
- 数据库设计与优化
- 系统测试与性能评估
研究目标是开发一个功能完善、性能稳定、界面友好的考研书库微信小程序,满足考研学生的学习需求。
2 相关技术与理论基础
2.1 SpringBoot 框架
SpringBoot 是基于 Spring 的快速应用开发框架,具有以下特点:
- 自动配置,减少 XML 配置文件
- 内嵌 Tomcat 等服务器,简化部署
- 提供 Actuator 组件,便于监控系统运行状态
- 支持各种数据库和缓存技术
2.2 uniapp 框架
uniapp 是一个使用 Vue.js 开发所有前端应用的框架,具有以下优势:
- 一套代码可同时发布到微信小程序、H5、APP 等多个平台
- 兼容微信小程序原生组件和 API
- 性能接近原生应用
- 丰富的 UI 组件库和插件市场
2.3 微信小程序开发
微信小程序是一种轻量级应用,具有以下特点:
- 无需下载安装,触手可及
- 基于微信生态,用户基数大
- 提供丰富的 API 接口,如支付、分享、位置等
- 开发成本低,维护方便
2.4 数据库技术
本系统采用 MySQL 作为关系型数据库,Redis 作为缓存数据库:
- MySQL:支持事务处理,适合存储结构化数据
- Redis:高性能内存数据库,适合缓存热点数据,提高系统响应速度
3 系统需求分析
3.1 功能需求
3.1.1 用户管理模块
- 用户注册与登录
- 个人信息管理
- 学习偏好设置
- 账号安全管理
3.1.2 资料管理模块
- 资料分类与标签
- 资料上传与审核
- 资料检索与预览
- 资料下载与收藏
3.1.3 学习管理模块
- 学习计划制定与跟踪
- 学习进度记录
- 学习笔记管理
- 学习数据分析
3.1.4 社交互动模块
- 评论与回复
- 点赞与分享
- 关注与粉丝管理
- 私信交流
3.1.5 系统管理模块
- 管理员账号管理
- 资料审核管理
- 用户权限管理
- 系统日志管理
3.2 非功能需求
3.2.1 性能需求
- 系统响应时间不超过 3 秒
- 支持至少 1000 个并发用户
- 资料下载速度不低于 1MB/s
3.2.2 安全需求
- 用户信息加密存储
- 资料访问权限控制
- 防止 SQL 注入和 XSS 攻击
- 数据定期备份
3.2.3 可用性需求
- 系统 7×24 小时可用
- 故障恢复时间不超过 1 小时
- 操作界面简洁直观,易于使用
3.2.4 兼容性需求
- 兼容主流微信版本
- 适配不同屏幕尺寸的移动设备
4 系统设计
4.1 总体架构设计
系统采用前后端分离的三层架构:
plaintext
┌─────────────────────────────────────────────┐
│ 表示层 │
│ (uniapp前端、微信小程序界面) │
└─────────────────────┬───────────────────────┘│ RESTful API
┌─────────────────────┼───────────────────────┐
│ 业务逻辑层 │
│ (SpringBoot、Service、Repository、Controller) │
└─────────────────────┬───────────────────────┘│ JDBC/MyBatis
┌─────────────────────┼───────────────────────┐
│ 数据访问层 │
│ (MySQL数据库、Redis缓存) │
└─────────────────────────────────────────────┘
4.2 数据库设计
4.2.1 数据库表结构
用户表 (users)
sql
CREATE TABLE `users` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',`username` varchar(50) NOT NULL COMMENT '用户名',`password` varchar(100) NOT NULL COMMENT '密码(加密存储)',`nickname` varchar(50) DEFAULT NULL COMMENT '昵称',`avatar` varchar(255) DEFAULT NULL COMMENT '头像URL',`email` varchar(100) DEFAULT NULL COMMENT '邮箱',`phone` varchar(20) DEFAULT NULL COMMENT '手机号',`gender` tinyint(1) DEFAULT NULL COMMENT '性别(0:未知,1:男,2:女)',`school` varchar(100) DEFAULT NULL COMMENT '学校',`major` varchar(100) DEFAULT NULL COMMENT '专业',`target_school` varchar(100) DEFAULT NULL COMMENT '目标院校',`target_major` varchar(100) DEFAULT NULL COMMENT '目标专业',`role` varchar(20) NOT NULL DEFAULT 'user' COMMENT '角色(user/admin)',`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(0:禁用,1:启用)',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`),UNIQUE KEY `idx_username` (`username`),UNIQUE KEY `idx_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
资料表 (resources)
sql
CREATE TABLE `resources` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '资料ID',`title` varchar(100) NOT NULL COMMENT '资料标题',`description` text COMMENT '资料描述',`category_id` bigint(20) NOT NULL COMMENT '分类ID',`uploader_id` bigint(20) NOT NULL COMMENT '上传者ID',`file_path` varchar(255) NOT NULL COMMENT '文件路径',`file_size` bigint(20) NOT NULL COMMENT '文件大小(字节)',`file_type` varchar(20) NOT NULL COMMENT '文件类型(pdf/doc/xls等)',`download_count` int(11) NOT NULL DEFAULT '0' COMMENT '下载次数',`view_count` int(11) NOT NULL DEFAULT '0' COMMENT '浏览次数',`score` decimal(3,1) DEFAULT '0.0' COMMENT '评分',`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态(0:待审核,1:已通过,2:已拒绝)',`is_free` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否免费(0:付费,1:免费)',`price` decimal(10,2) DEFAULT '0.00' COMMENT '价格',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_category_id` (`category_id`),KEY `idx_uploader_id` (`uploader_id`),KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='资料表';
资料分类表 (resource_categories)
sql
CREATE TABLE `resource_categories` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类ID',`name` varchar(50) NOT NULL COMMENT '分类名称',`parent_id` bigint(20) DEFAULT NULL COMMENT '父分类ID',`level` int(11) NOT NULL DEFAULT '1' COMMENT '分类级别',`sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(0:禁用,1:启用)',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='资料分类表';
资料标签表 (resource_tags)
sql
CREATE TABLE `resource_tags` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '标签ID',`name` varchar(50) NOT NULL COMMENT '标签名称',`count` int(11) NOT NULL DEFAULT '0' COMMENT '使用次数',`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(0:禁用,1:启用)',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`),UNIQUE KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='资料标签表';
资料 - 标签关联表 (resource_tag_relations)
sql
CREATE TABLE `resource_tag_relations` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '关联ID',`resource_id` bigint(20) NOT NULL COMMENT '资料ID',`tag_id` bigint(20) NOT NULL COMMENT '标签ID',`create_time` datetime NOT NULL COMMENT '创建时间',PRIMARY KEY (`id`),UNIQUE KEY `idx_resource_tag` (`resource_id`,`tag_id`),KEY `idx_tag_id` (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='资料-标签关联表';
资料评论表 (resource_comments)
sql
CREATE TABLE `resource_comments` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '评论ID',`resource_id` bigint(20) NOT NULL COMMENT '资料ID',`user_id` bigint(20) NOT NULL COMMENT '评论用户ID',`parent_id` bigint(20) DEFAULT NULL COMMENT '父评论ID',`content` text NOT NULL COMMENT '评论内容',`like_count` int(11) NOT NULL DEFAULT '0' COMMENT '点赞数',`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态(0:禁用,1:启用)',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_resource_id` (`resource_id`),KEY `idx_user_id` (`user_id`),KEY `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='资料评论表';
学习计划表 (study_plans)
sql
CREATE TABLE `study_plans` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '计划ID',`user_id` bigint(20) NOT NULL COMMENT '用户ID',`title` varchar(100) NOT NULL COMMENT '计划标题',`description` text COMMENT '计划描述',`start_date` date NOT NULL COMMENT '开始日期',`end_date` date NOT NULL COMMENT '结束日期',`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态(0:进行中,1:已完成,2:已取消)',`progress` int(11) NOT NULL DEFAULT '0' COMMENT '进度(0-100)',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_user_id` (`user_id`),KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学习计划表';
学习计划项表 (study_plan_items)
sql
CREATE TABLE `study_plan_items` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '计划项ID',`plan_id` bigint(20) NOT NULL COMMENT '计划ID',`title` varchar(100) NOT NULL COMMENT '计划项标题',`description` text COMMENT '计划项描述',`plan_date` date NOT NULL COMMENT '计划日期',`start_time` time DEFAULT NULL COMMENT '开始时间',`end_time` time DEFAULT NULL COMMENT '结束时间',`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态(0:未完成,1:已完成)',`priority` tinyint(1) NOT NULL DEFAULT '2' COMMENT '优先级(1:高,2:中,3:低)',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_plan_id` (`plan_id`),KEY `idx_plan_date` (`plan_date`),KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学习计划项表';
学习笔记表 (study_notes)
sql
CREATE TABLE `study_notes` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '笔记ID',`user_id` bigint(20) NOT NULL COMMENT '用户ID',`title` varchar(100) NOT NULL COMMENT '笔记标题',`content` text NOT NULL COMMENT '笔记内容',`resource_id` bigint(20) DEFAULT NULL COMMENT '关联资料ID',`category_id` bigint(20) DEFAULT NULL COMMENT '分类ID',`is_public` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否公开(0:私密,1:公开)',`like_count` int(11) NOT NULL DEFAULT '0' COMMENT '点赞数',`view_count` int(11) NOT NULL DEFAULT '0' COMMENT '浏览数',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_user_id` (`user_id`),KEY `idx_resource_id` (`resource_id`),KEY `idx_category_id` (`category_id`),KEY `idx_is_public` (`is_public`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学习笔记表';
用户关注表 (user_follows)
sql
CREATE TABLE `user_follows` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '关注ID',`follower_id` bigint(20) NOT NULL COMMENT '关注者ID',`followed_id` bigint(20) NOT NULL COMMENT '被关注者ID',`create_time` datetime NOT NULL COMMENT '创建时间',PRIMARY KEY (`id`),UNIQUE KEY `idx_follower_followed` (`follower_id`,`followed_id`),KEY `idx_followed_id` (`followed_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户关注表';
4.3 系统架构图
4.4 部署架构图
4.5 用例图
4.6 界面原型
4.6.1 首页
首页展示热门资料、推荐分类、学习日历等信息,提供搜索和导航功能。
4.6.2 资料列表页
按分类或标签展示资料列表,支持筛选和排序功能。
4.6.3 资料详情页
展示资料详细信息,包括标题、描述、下载次数、评分等,提供下载和评论功能。
4.6.4 学习计划页
展示用户的学习计划和进度,支持创建、编辑和删除计划。
4.6.5 学习笔记页
展示用户的学习笔记,支持创建、编辑和分享笔记。
4.6.6 个人中心页
展示用户个人信息、收藏、关注等内容,提供账号管理功能。
5 系统实现
5.1 后端实现
5.1.1 项目结构
plaintext
kaoyan-bookstore/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── kaoyan/
│ │ │ ├── KaoyanApplication.java
│ │ │ ├── config/ # 配置类
│ │ │ ├── controller/ # 控制器
│ │ │ ├── service/ # 服务层
│ │ │ ├── repository/ # 数据访问层
│ │ │ ├── model/ # 实体类
│ │ │ ├── dto/ # 数据传输对象
│ │ │ ├── exception/ # 异常处理
│ │ │ ├── util/ # 工具类
│ │ │ └── security/ # 安全配置
│ │ └── resources/
│ │ ├── application.yml # 配置文件
│ │ ├── mapper/ # MyBatis映射文件
│ │ ├── static/ # 静态资源
│ │ └── templates/ # 模板文件
│ └── test/ # 测试代码
└── pom.xml # Maven配置文件
5.1.2 核心代码实现
用户认证与授权
java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Autowiredprivate JwtAuthenticationEntryPoint unauthorizedHandler;@Beanpublic JwtAuthenticationFilter jwtAuthenticationFilter() {return new JwtAuthenticationFilter();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.cors().and().csrf().disable().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests().antMatchers("/api/auth/**", "/api/resources/public/**").permitAll().antMatchers("/api/admin/**").hasRole("ADMIN").anyRequest().authenticated();http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);}
}
资料服务实现
java
@Service
@Transactional
public class ResourceServiceImpl implements ResourceService {@Autowiredprivate ResourceRepository resourceRepository;@Autowiredprivate ResourceCategoryRepository categoryRepository;@Autowiredprivate FileStorageService fileStorageService;@Overridepublic ResourceDTO uploadResource(MultipartFile file, ResourceCreateDTO resourceDTO, Long userId) {// 验证分类是否存在ResourceCategory category = categoryRepository.findById(resourceDTO.getCategoryId()).orElseThrow(() -> new ResourceNotFoundException("分类不存在"));// 保存文件String fileName = fileStorageService.storeFile(file);String fileDownloadUri = "/api/resources/download/" + fileName;// 创建资源Resource resource = new Resource();resource.setTitle(resourceDTO.getTitle());resource.setDescription(resourceDTO.getDescription());resource.setCategory(category);resource.setUploaderId(userId);resource.setFilePath(fileName);resource.setFileSize(file.getSize());resource.setFileType(file.getContentType());resource.setStatus(ResourceStatus.PENDING);resource.setIsFree(resourceDTO.getIsFree());resource.setPrice(resourceDTO.getPrice());// 保存资源Resource savedResource = resourceRepository.save(resource);// 处理标签if (resourceDTO.getTagIds() != null && !resourceDTO.getTagIds().isEmpty()) {// 标签关联逻辑}return convertToDTO(savedResource);}@Overridepublic Page<ResourceDTO> getAllResources(Pageable pageable) {Page<Resource> resources = resourceRepository.findAllByStatus(ResourceStatus.APPROVED, pageable);return resources.map(this::convertToDTO);}@Overridepublic ResourceDTO getResourceById(Long id) {Resource resource = resourceRepository.findByIdAndStatus(id, ResourceStatus.APPROVED).orElseThrow(() -> new ResourceNotFoundException("资源不存在"));// 更新浏览次数resource.setViewCount(resource.getViewCount() + 1);resourceRepository.save(resource);return convertToDTO(resource);}@Overridepublic ResourceDTO updateResource(Long id, ResourceUpdateDTO resourceDTO, Long userId) {Resource resource = resourceRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("资源不存在"));// 验证权限if (!resource.getUploaderId().equals(userId)) {throw new AccessDeniedException("无权修改此资源");}// 更新资源信息resource.setTitle(resourceDTO.getTitle());resource.setDescription(resourceDTO.getDescription());resource.setStatus(resourceDTO.getStatus());resource.setIsFree(resourceDTO.getIsFree());resource.setPrice(resourceDTO.getPrice());// 处理分类更新if (resourceDTO.getCategoryId() != null) {ResourceCategory category = categoryRepository.findById(resourceDTO.getCategoryId()).orElseThrow(() -> new ResourceNotFoundException("分类不存在"));resource.setCategory(category);}// 保存更新Resource updatedResource = resourceRepository.save(resource);// 处理标签更新if (resourceDTO.getTagIds() != null) {// 标签更新逻辑}return convertToDTO(updatedResource);}@Overridepublic void deleteResource(Long id, Long userId) {Resource resource = resourceRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("资源不存在"));// 验证权限if (!resource.getUploaderId().equals(userId)) {throw new AccessDeniedException("无权删除此资源");}// 删除文件fileStorageService.deleteFile(resource.getFilePath());// 删除资源resourceRepository.delete(resource);}private ResourceDTO convertToDTO(Resource resource) {ResourceDTO dto = new ResourceDTO();BeanUtils.copyProperties(resource, dto);dto.setCategoryId(resource.getCategory().getId());dto.setCategoryName(resource.getCategory().getName());// 设置标签List<ResourceTag> tags = resource.getTags();if (tags != null && !tags.isEmpty()) {dto.setTagNames(tags.stream().map(ResourceTag::getName).collect(Collectors.toList()));}return dto;}
}
学习计划服务实现
java
@Service
@Transactional
public class StudyPlanServiceImpl implements StudyPlanService {@Autowiredprivate StudyPlanRepository planRepository;@Autowiredprivate StudyPlanItemRepository itemRepository;@Overridepublic StudyPlanDTO createPlan(StudyPlanCreateDTO planDTO, Long userId) {// 创建学习计划StudyPlan plan = new StudyPlan();plan.setTitle(planDTO.getTitle());plan.setDescription(planDTO.getDescription());plan.setStartDate(planDTO.getStartDate());plan.setEndDate(planDTO.getEndDate());plan.setUserId(userId);plan.setStatus(PlanStatus.IN_PROGRESS);plan.setProgress(0);// 保存计划StudyPlan savedPlan = planRepository.save(plan);// 处理计划项if (planDTO.getItems() != null && !planDTO.getItems().isEmpty()) {List<StudyPlanItem> items = planDTO.getItems().stream().map(itemDTO -> {StudyPlanItem item = new StudyPlanItem();item.setPlan(savedPlan);item.setTitle(itemDTO.getTitle());item.setDescription(itemDTO.getDescription());item.setPlanDate(itemDTO.getPlanDate());item.setStartTime(itemDTO.getStartTime());item.setEndTime(itemDTO.getEndTime());item.setStatus(ItemStatus.UNFINISHED);item.setPriority(itemDTO.getPriority());return item;}).collect(Collectors.toList());itemRepository.saveAll(items);}return convertToDTO(savedPlan);}@Overridepublic Page<StudyPlanDTO> getPlansByUser(Long userId, Pageable pageable) {Page<StudyPlan> plans = planRepository.findByUserId(userId, pageable);return plans.map(this::convertToDTO);}@Overridepublic StudyPlanDTO getPlanById(Long id, Long userId) {StudyPlan plan = planRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("计划不存在"));// 验证权限if (!plan.getUserId().equals(userId)) {throw new AccessDeniedException("无权查看此计划");}return convertToDTO(plan);}@Overridepublic StudyPlanDTO updatePlan(Long id, StudyPlanUpdateDTO planDTO, Long userId) {StudyPlan plan = planRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("计划不存在"));// 验证权限if (!plan.getUserId().equals(userId)) {throw new AccessDeniedException("无权修改此计划");}// 更新计划信息plan.setTitle(planDTO.getTitle());plan.setDescription(planDTO.getDescription());plan.setStartDate(planDTO.getStartDate());plan.setEndDate(planDTO.getEndDate());plan.setStatus(planDTO.getStatus());// 保存更新StudyPlan updatedPlan = planRepository.save(plan);// 更新进度updatePlanProgress(updatedPlan.getId());return convertToDTO(updatedPlan);}@Overridepublic void deletePlan(Long id, Long userId) {StudyPlan plan = planRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("计划不存在"));// 验证权限if (!plan.getUserId().equals(userId)) {throw new AccessDeniedException("无权删除此计划");}// 删除计划项itemRepository.deleteByPlanId(id);// 删除计划planRepository.delete(plan);}@Overridepublic StudyPlanItemDTO createPlanItem(StudyPlanItemCreateDTO itemDTO, Long planId, Long userId) {StudyPlan plan = planRepository.findById(planId).orElseThrow(() -> new ResourceNotFoundException("计划不存在"));// 验证权限if (!plan.getUserId().equals(userId)) {throw new AccessDeniedException("无权添加计划项");}// 创建计划项StudyPlanItem item = new StudyPlanItem();item.setPlan(plan);item.setTitle(itemDTO.getTitle());item.setDescription(itemDTO.getDescription());item.setPlanDate(itemDTO.getPlanDate());item.setStartTime(itemDTO.getStartTime());item.setEndTime(itemDTO.getEndTime());item.setStatus(ItemStatus.UNFINISHED);item.setPriority(itemDTO.getPriority());// 保存计划项StudyPlanItem savedItem = itemRepository.save(item);// 更新计划进度updatePlanProgress(planId);return convertToDTO(savedItem);}private void updatePlanProgress(Long planId) {StudyPlan plan = planRepository.findById(planId).orElseThrow(() -> new ResourceNotFoundException("计划不存在"));List<StudyPlanItem> items = itemRepository.findByPlanId(planId);if (items.isEmpty()) {plan.setProgress(0);} else {long finishedCount = items.stream().filter(item -> item.getStatus() == ItemStatus.FINISHED).count();int progress = (int) (finishedCount * 100 / items.size());plan.setProgress(progress);}// 如果所有项都完成,将计划状态设为已完成if (plan.getProgress() == 100 && plan.getStatus() == PlanStatus.IN_PROGRESS) {plan.setStatus(PlanStatus.COMPLETED);}planRepository.save(plan);}private StudyPlanDTO convertToDTO(StudyPlan plan) {StudyPlanDTO dto = new StudyPlanDTO();BeanUtils.copyProperties(plan, dto);// 获取计划项List<StudyPlanItem> items = itemRepository.findByPlanId(plan.getId());if (items != null && !items.isEmpty()) {dto.setItems(items.stream().map(this::convertItemToDTO).collect(Collectors.toList()));}return dto;}private StudyPlanItemDTO convertItemToDTO(StudyPlanItem item) {StudyPlanItemDTO dto = new StudyPlanItemDTO();BeanUtils.copyProperties(item, dto);dto.setPlanId(item.getPlan().getId());return dto;}
}
5.2 前端实现
前端使用 uniapp 框架,采用组件化开发方式,主要实现以下功能:
5.2.1 登录注册页面
- 微信一键登录
- 手机号 + 验证码登录
- 密码登录
- 注册功能
5.2.2 资料列表与详情页面
- 分类导航
- 资料列表展示
- 搜索功能
- 资料详情展示
- 下载功能
- 评论功能
5.2.3 学习计划页面
- 计划列表
- 计划详情
- 计划项管理
- 进度统计
- 日历视图
5.2.4 学习笔记页面
- 笔记列表
- 笔记详情
- 新建笔记
- 编辑笔记
- 分享笔记
5.2.5 个人中心页面
- 个人信息展示
- 资料收藏
- 关注用户
- 学习统计
- 设置功能
以下是 uniapp 前端的部分核心代码:
登录页面实现
javascript
<template><view class="login-container"><view class="logo">
博主介绍:硕士研究生,专注于信息化技术领域开发与管理,会使用java、标准c/c++等开发语言,以及毕业项目实战✌
从事基于java BS架构、CS架构、c/c++ 编程工作近16年,拥有近12年的管理工作经验,拥有较丰富的技术架构思想、较扎实的技术功底和资深的项目管理经验。
先后担任过技术总监、部门经理、项目经理、开发组长、java高级工程师及c++工程师等职位,在工业互联网、国家标识解析体系、物联网、分布式集群架构、大数据通道处理、接口开发、远程教育、办公OA、财务软件(工资、记账、决策、分析、报表统计等方面)、企业内部管理软件(ERP、CRM等)、arggis地图等信息化建设领域有较丰富的实战工作经验;拥有BS分布式架构集群、数据库负载集群架构、大数据存储集群架构,以及高并发分布式集群架构的设计、开发和部署实战经验;拥有大并发访问、大数据存储、即时消息等瓶颈解决方案和实战经验。
拥有产品研发和发明专利申请相关工作经验,完成发明专利构思、设计、编写、申请等工作,并获得发明专利1枚。
-----------------------------------------------------------------------------------
大家在毕设选题、项目升级、论文写作,就业毕业等相关问题都可以给我留言咨询,非常乐意帮助更多的人或加w 908925859。
相关博客地址:
csdn专业技术博客:https://blog.csdn.net/mr_lili_1986?type=blog
Iteye博客: https://www.iteye.com/blog/user/mr-lili-1986-163-com
门户:http://www.petsqi.cn
七、其他案例: