深入解析:基于“SpringBoot+uniapp的考研书库微信小程序设计与实现7000字论文

摘要
本文设计并实现了一个基于 SpringBoot 后端和 uniapp 前端的考研书库微信小程序,旨在为考研学生提供便捷的电子资料查询、在线学习和社交交流平台。环境采用前后端分离架构,借助 RESTful API 实现数据交互,支持用户注册登录、资料分类检索、笔记共享、学习计划管理等功能。论文详细阐述了系统需求分析、架构设计、数据库设计、功能模块实现及测试评估过程,最终验证了系统的可行性和实用性。

关键词
SpringBoot;uniapp;微信小程序;考研书库;在线学习平台

1 引言

1.1 研究背景与意义

随着考研人数的逐年增长,考生对优质学习资源的需求日益迫切。传统的考研资料获取方式存在信息分散、更新不及时、检索困难等问题,无法满足考生高效备考的需求。开发一个集资料整合、学习管理和社交交流于一体的考研书库平台,具有重要的现实意义:

  • 整合优质考研资源,解除信息碎片化问题
  • 献出个性化学习支持,提高备考效率
  • 构建学习社区,促进考生间的交流与互助
  • 降低学习成本,实现资源共享与优化调整
1.2 国内外研究现状

国内外针对在线学习平台的研究已经取得了一定进展:

  • 国外:Coursera、edX 等平台提供了丰富的课程资源,但针对考研的专业化平台较少
  • 国内:考研帮、新东方在线等平台主要以课程服务为主,资料共享功能相对薄弱
  • 技术层面:SpringBoot 框架在后端开发中广泛应用,uniapp 在跨平台小程序开发中展现出显著优势

然而,现有的考研学习平台在资料整合深度、个性化服务和社交互动方面仍存在不足。

1.3 研究内容与目标

本文研究内容包括:

  1. 考研书库微信小脚本的需求分析与功能设计
  2. 基于 SpringBoot 的后端架构设计与实现
  3. 基于 uniapp 的前端界面开发与交互实现
  4. 数据库设计与优化
  5. 系统测试与性能评估

研究目标是开发一个功能完善、性能稳定、界面友好的考研书库微信小程序,满足考研学生的学习需求。

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

CREATETABLE`users` ( `id` bigint(20) NOT NULLAUTO_INCREMENT COMMENT'用户ID', `username` varchar(50) NOT NULLCOMMENT'用户名', `password` varchar(100) NOT NULLCOMMENT'密码(加密存储)', `nickname` varchar(50) DEFAULT NULLCOMMENT'昵称', `avatar` varchar(255) DEFAULT NULLCOMMENT'头像URL', `email` varchar(100) DEFAULT NULLCOMMENT'邮箱', `phone` varchar(20) DEFAULT NULLCOMMENT'手机号', `gender` tinyint(1) DEFAULT NULLCOMMENT'性别(0:未知,1:男,2:女)', `school` varchar(100) DEFAULT NULLCOMMENT'学校', `major` varchar(100) DEFAULT NULLCOMMENT'专业', `target_school` varchar(100) DEFAULT NULLCOMMENT'目标院校', `target_major` varchar(100) DEFAULT NULLCOMMENT'目标专业', `role` varchar(20) NOT NULL DEFAULT 'user'COMMENT'角色(user/admin)', `status` tinyint(1) NOT NULL DEFAULT '1'COMMENT'状态(0:禁用,1:启用)', `create_time` datetimeNOT NULLCOMMENT'创建时间', `update_time` datetimeNOT NULLCOMMENT'更新时间', PRIMARYKEY(`id`), UNIQUEKEY`idx_username` (`username`), UNIQUEKEY`idx_email` (`email`) ) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='用户表';

资料表 (resources)

sql

CREATETABLE`resources` ( `id` bigint(20) NOT NULLAUTO_INCREMENT COMMENT'资料ID', `title` varchar(100) NOT NULLCOMMENT'资料标题', `description` text COMMENT'资料描述', `category_id` bigint(20) NOT NULLCOMMENT'分类ID', `uploader_id` bigint(20) NOT NULLCOMMENT'上传者ID', `file_path` varchar(255) NOT NULLCOMMENT'文档路径', `file_size` bigint(20) NOT NULLCOMMENT'文件大小(字节)', `file_type` varchar(20) NOT NULLCOMMENT'文件类型(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` datetimeNOT NULLCOMMENT'创建时间', `update_time` datetimeNOT NULLCOMMENT'更新时间', PRIMARYKEY(`id`),KEY`idx_category_id` (`category_id`),KEY`idx_uploader_id` (`uploader_id`),KEY `idx_status` (`status`) ) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='资料表';

资料分类表 (resource_categories)

sql

CREATETABLE`resource_categories` ( `id` bigint(20) NOT NULLAUTO_INCREMENT COMMENT'分类ID', `name` varchar(50) NOT NULLCOMMENT'分类名称', `parent_id` bigint(20) DEFAULT NULLCOMMENT'父分类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` datetimeNOT NULLCOMMENT'创建时间', `update_time` datetimeNOT NULLCOMMENT'更新时间', PRIMARYKEY(`id`),KEY`idx_parent_id` (`parent_id`) ) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='资料分类表';

资料标签表 (resource_tags)

sql

CREATETABLE`resource_tags` ( `id` bigint(20) NOT NULLAUTO_INCREMENT COMMENT'标签ID', `name` varchar(50) NOT NULLCOMMENT'标签名称', `count` int(11) NOT NULL DEFAULT '0'COMMENT'使用次数', `status` tinyint(1) NOT NULL DEFAULT '1'COMMENT'状态(0:禁用,1:启用)', `create_time` datetimeNOT NULLCOMMENT'创建时间', `update_time` datetimeNOT NULLCOMMENT'更新时间', PRIMARYKEY(`id`), UNIQUEKEY`idx_name` (`name`) ) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='资料标签表';

资料 - 标签关联表 (resource_tag_relations)

sql

CREATETABLE`resource_tag_relations` ( `id` bigint(20) NOT NULLAUTO_INCREMENT COMMENT'关联ID', `resource_id` bigint(20) NOT NULLCOMMENT'资料ID', `tag_id` bigint(20) NOT NULLCOMMENT'标签ID', `create_time` datetimeNOT NULLCOMMENT'创建时间', PRIMARYKEY(`id`), UNIQUEKEY`idx_resource_tag` (`resource_id`,`tag_id`),KEY`idx_tag_id` (`tag_id`) ) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='资料-标签关联表';

资料评论表 (resource_comments)

sql

CREATETABLE`resource_comments` ( `id` bigint(20) NOT NULLAUTO_INCREMENT COMMENT'评论ID', `resource_id` bigint(20) NOT NULLCOMMENT'资料ID', `user_id` bigint(20) NOT NULLCOMMENT'评论用户ID', `parent_id` bigint(20) DEFAULT NULLCOMMENT'父评论ID', `content` textNOT NULLCOMMENT'评论内容', `like_count` int(11) NOT NULL DEFAULT '0'COMMENT'点赞数', `status` tinyint(1) NOT NULL DEFAULT '1'COMMENT'状态(0:禁用,1:启用)', `create_time` datetimeNOT NULLCOMMENT'创建时间', `update_time` datetimeNOT NULLCOMMENT'更新时间', PRIMARYKEY(`id`),KEY`idx_resource_id` (`resource_id`),KEY`idx_user_id` (`user_id`),KEY`idx_parent_id` (`parent_id`) ) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='资料评论表';

学习计划表 (study_plans)

sql

CREATETABLE`study_plans` ( `id` bigint(20) NOT NULLAUTO_INCREMENT COMMENT'计划ID', `user_id` bigint(20) NOT NULLCOMMENT'用户ID', `title` varchar(100) NOT NULLCOMMENT'计划标题', `description` text COMMENT'计划描述', `start_date` date NOT NULLCOMMENT'开始日期', `end_date` date NOT NULLCOMMENT'结束日期', `status` tinyint(1) NOT NULL DEFAULT '0'COMMENT'状态(0:进行中,1:已完成,2:已取消)', `progress` int(11) NOT NULL DEFAULT '0'COMMENT'进度(0-100)', `create_time` datetimeNOT NULLCOMMENT'创建时间', `update_time` datetimeNOT NULLCOMMENT'更新时间', PRIMARYKEY(`id`),KEY`idx_user_id` (`user_id`),KEY `idx_status` (`status`) ) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='学习计划表';

学习计划项表 (study_plan_items)

sql

CREATETABLE`study_plan_items` ( `id` bigint(20) NOT NULLAUTO_INCREMENT COMMENT'计划项ID', `plan_id` bigint(20) NOT NULLCOMMENT'计划ID', `title` varchar(100) NOT NULLCOMMENT'计划项标题', `description` text COMMENT'计划项描述', `plan_date` date NOT NULLCOMMENT'计划日期', `start_time` time DEFAULT NULLCOMMENT'开始时间', `end_time` time DEFAULT NULLCOMMENT'结束时间', `status` tinyint(1) NOT NULL DEFAULT '0'COMMENT'状态(0:未完成,1:已搞定)', `priority` tinyint(1) NOT NULL DEFAULT '2'COMMENT'优先级(1:高,2:中,3:低)', `create_time` datetimeNOT NULLCOMMENT'创建时间', `update_time` datetimeNOT NULLCOMMENT'更新时间', PRIMARYKEY(`id`),KEY`idx_plan_id` (`plan_id`),KEY`idx_plan_date` (`plan_date`), KEY `idx_status` (`status`) ) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='学习计划项表';

学习笔记表 (study_notes)

sql

CREATETABLE`study_notes` ( `id` bigint(20) NOT NULLAUTO_INCREMENT COMMENT'笔记ID', `user_id` bigint(20) NOT NULLCOMMENT'用户ID', `title` varchar(100) NOT NULLCOMMENT'笔记标题', `content` textNOT NULLCOMMENT'笔记内容', `resource_id` bigint(20) DEFAULT NULLCOMMENT'关联资料ID', `category_id` bigint(20) DEFAULT NULLCOMMENT'分类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` datetimeNOT NULLCOMMENT'创建时间', `update_time` datetimeNOT NULLCOMMENT'更新时间', PRIMARYKEY(`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=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='学习笔记表';

用户关注表 (user_follows)

sql

CREATETABLE`user_follows` ( `id` bigint(20) NOT NULLAUTO_INCREMENT COMMENT'关注ID', `follower_id` bigint(20) NOT NULLCOMMENT'关注者ID', `followed_id` bigint(20) NOT NULLCOMMENT'被关注者ID', `create_time` datetimeNOT NULLCOMMENT'创建时间', PRIMARYKEY(`id`), UNIQUEKEY`idx_follower_followed` (`follower_id`,`followed_id`),KEY`idx_followed_id` (`followed_id`) ) ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='用户关注表';
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 newJwtAuthenticationFilter(); } @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 newBCryptPasswordEncoder(); } @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 publicclassResourceServiceImpl implements ResourceService { @Autowired private ResourceRepository resourceRepository; @Autowired private ResourceCategoryRepository categoryRepository; @Autowired private FileStorageService fileStorageService; @Overridepublic ResourceDTO uploadResource(MultipartFilefile, ResourceCreateDTO resourceDTO, Long userId) {//否存在就是验证分类 ResourceCategory category=categoryRepository.findById(resourceDTO.getCategoryId()) .orElseThrow(() ->new ResourceNotFoundException("分类不存在")); // 保存文件 StringfileName=fileStorageService.storeFile(file); StringfileDownloadUri= "/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()) {//标签关联逻辑 }returnconvertToDTO(savedResource); } @OverridepublicPageResourceDTO>getAllResources(Pageable pageable) {PageResource>resources=resourceRepository.findAllByStatus(ResourceStatus.APPROVED, pageable);returnresources.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);returnconvertToDTO(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) { //标签更新逻辑 }returnconvertToDTO(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());//设置标签 ListResourceTag> tags =resource.getTags();if(tags != null &&!tags.isEmpty()) { dto.setTagNames(tags.stream().map(ResourceTag::getName).collect(Collectors.toList())); }returndto; } }

学习计划服务实现

java

@Service @Transactional publicclassStudyPlanServiceImpl implements StudyPlanService { @Autowired private StudyPlanRepository planRepository; @Autowired private 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()) { ListStudyPlanItem> 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());returnitem; }) .collect(Collectors.toList()); itemRepository.saveAll(items); }returnconvertToDTO(savedPlan); } @OverridepublicPageStudyPlanDTO>getPlansByUser(Long userId, Pageable pageable) {PageStudyPlan> plans =planRepository.findByUserId(userId, pageable);returnplans.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("无权查看此计划"); } returnconvertToDTO(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());returnconvertToDTO(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);returnconvertToDTO(savedItem); } private void updatePlanProgress(Long planId) { StudyPlan plan=planRepository.findById(planId) .orElseThrow(() ->new ResourceNotFoundException("计划不存在")); ListStudyPlanItem> 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);//获取计划项 ListStudyPlanItem> items =itemRepository.findByPlanId(plan.getId());if(items != null &&!items.isEmpty()) { dto.setItems(items.stream().map(this::convertItemToDTO).collect(Collectors.toList())); }returndto; } private StudyPlanItemDTO convertItemToDTO(StudyPlanItem item) { StudyPlanItemDTO dto=new StudyPlanItemDTO(); BeanUtils.copyProperties(item, dto); dto.setPlanId(item.getPlan().getId());returndto; } }

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

  

七、其他案例: 

 

  

 

posted on 2025-07-13 16:04  ljbguanli  阅读(16)  评论(0)    收藏  举报