一、个人简介
💖💖作者:计算机编程果茶熊 💙💙个人简介:曾长期从事计算机专业培训教学,担任过编程老师,同时本人也热爱上课教学,擅长Java、微信小程序、Python、Golang、安卓Android等多个IT方向。会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。平常喜欢分享一些自己开发中遇到的问题的解决办法,也喜欢交流技术,大家有技术代码这一块的问题可以问我! 💛💛想说的话:感谢大家的关注与支持! 💜💜 网站实战项目 安卓/小程序实战项目 大数据实战项目 计算机毕业设计选题 💕💕文末获取源码联系计算机编程果茶熊
二、系统介绍
开发语言:Java+Python 数据库:MySQL 系统架构:B/S 后端框架:SpringBoot(Spring+SpringMVC+Mybatis)+Django 前端:Vue+HTML+CSS+JavaScript+jQuery
本系统是一个基于Spring Boot和Vue技术栈开发的智能家教服务平台,采用B/S架构实现家教供需双方的高效对接。系统通过前后端分离的设计模式,利用MySQL数据库进行数据持久化管理,为家长、教员提供全流程的家教服务支持。平台核心功能涵盖家长与教员的双向管理、教员信息的精准录入与检索、家教时段的灵活安排、课程类型与家教分类的多维度划分、家教信息的发布与浏览、家教接单的实时响应、授课完成的状态跟踪、教学资源的共享管理、学习反馈与教学评价的互动机制、家教需求的定制化匹配、家教申请的审核流程、授课反馈的及时记录、教师评价的透明化展示以及留言反馈的沟通渠道。系统通过整合这些功能模块,构建起一个信息透明、流程规范、服务高效的家教服务生态,有效解决了传统家教市场信息不对称、匹配效率低、服务质量难追踪等实际问题,为家教行业的数字化转型提供了切实可行的技术解决方案。
三、视频解说
四、部分功能展示
五、部分代码展示
/**
* 核心功能一: 家教信息智能匹配与发布管理
* 处理家教信息的发布、搜索匹配、状态更新等核心业务
*/
@PostMapping("/publishTutorInfo")
public Result publishTutorInfo(@RequestBody TutorInfo tutorInfo, HttpServletRequest request) {
// 获取当前登录教员ID
String token = request.getHeader("Authorization");
Long teacherId = JwtUtil.getUserId(token);
// 验证教员资质状态
Teacher teacher = teacherMapper.selectById(teacherId);
if (teacher == null || teacher.getStatus() != 1) {
return Result.error("教员资质审核未通过,无法发布家教信息");
}
// 检查时段冲突
QueryWrapper<TutorInfo> timeCheckWrapper = new QueryWrapper<>();
timeCheckWrapper.eq("teacher_id", teacherId)
.eq("time_slot_id", tutorInfo.getTimeSlotId())
.in("status", Arrays.asList(1, 2)); // 已发布或已接单状态
if (tutorInfoMapper.selectCount(timeCheckWrapper) > 0) {
return Result.error("该时段已有家教安排,请选择其他时段");
}
// 计算匹配度分数并推荐给合适的家长
tutorInfo.setTeacherId(teacherId);
tutorInfo.setStatus(1); // 状态设为已发布
tutorInfo.setPublishTime(new Date());
tutorInfo.setViewCount(0);
tutorInfoMapper.insert(tutorInfo);
// 查询符合条件的家教需求进行智能匹配
QueryWrapper<TutorDemand> demandWrapper = new QueryWrapper<>();
demandWrapper.eq("course_type_id", tutorInfo.getCourseTypeId())
.eq("status", 1) // 待匹配状态
.apply("FIND_IN_SET({0}, time_slot_ids)", tutorInfo.getTimeSlotId());
List<TutorDemand> matchedDemands = tutorDemandMapper.selectList(demandWrapper);
for (TutorDemand demand : matchedDemands) {
// 计算匹配度: 考虑价格、地域、评分等因素
int matchScore = calculateMatchScore(tutorInfo, demand);
if (matchScore >= 60) { // 匹配度阈值
// 创建匹配推荐记录
MatchRecommend recommend = new MatchRecommend();
recommend.setTutorInfoId(tutorInfo.getId());
recommend.setDemandId(demand.getId());
recommend.setParentId(demand.getParentId());
recommend.setMatchScore(matchScore);
recommend.setCreateTime(new Date());
matchRecommendMapper.insert(recommend);
// 发送推送通知给家长
sendNotification(demand.getParentId(), "系统为您匹配到合适的教员");
}
}
return Result.success("家教信息发布成功,已为您匹配" + matchedDemands.size() + "条需求");
}
/**
* 核心功能二: 家教接单与授课全流程管理
* 处理家长接单申请、教员确认、授课进度跟踪、完成确认等业务
*/
@PostMapping("/applyTutorOrder")
@Transactional(rollbackFor = Exception.class)
public Result applyTutorOrder(@RequestBody TutorApplication application, HttpServletRequest request) {
String token = request.getHeader("Authorization");
Long parentId = JwtUtil.getUserId(token);
// 验证家教信息是否可接单
TutorInfo tutorInfo = tutorInfoMapper.selectById(application.getTutorInfoId());
if (tutorInfo == null || tutorInfo.getStatus() != 1) {
return Result.error("该家教信息已失效或已被接单");
}
// 检查家长是否有未完成的订单
QueryWrapper<TutorOrder> orderCheckWrapper = new QueryWrapper<>();
orderCheckWrapper.eq("parent_id", parentId)
.in("status", Arrays.asList(1, 2, 3)) // 待确认、进行中、待评价
.gt("course_count - completed_count", 0);
int unfinishedCount = tutorOrderMapper.selectCount(orderCheckWrapper);
if (unfinishedCount >= 3) {
return Result.error("您当前有" + unfinishedCount + "个未完成订单,请完成后再申请新订单");
}
// 创建家教申请记录
application.setParentId(parentId);
application.setTeacherId(tutorInfo.getTeacherId());
application.setStatus(0); // 待教员确认
application.setApplyTime(new Date());
tutorApplicationMapper.insert(application);
// 更新家教信息浏览量和申请数
tutorInfo.setApplyCount(tutorInfo.getApplyCount() + 1);
tutorInfoMapper.updateById(tutorInfo);
// 通知教员有新的申请
sendNotification(tutorInfo.getTeacherId(), "您有新的家教申请,请及时处理");
return Result.success("申请提交成功,请等待教员确认");
}
@PostMapping("/confirmApplication")
@Transactional(rollbackFor = Exception.class)
public Result confirmApplication(@RequestParam Long applicationId, @RequestParam Integer confirm) {
TutorApplication application = tutorApplicationMapper.selectById(applicationId);
if (application == null || application.getStatus() != 0) {
return Result.error("申请不存在或已处理");
}
if (confirm == 1) {
// 教员确认接单,创建正式订单
TutorOrder order = new TutorOrder();
order.setApplicationId(applicationId);
order.setParentId(application.getParentId());
order.setTeacherId(application.getTeacherId());
order.setTutorInfoId(application.getTutorInfoId());
order.setCourseCount(application.getCourseCount());
order.setCompletedCount(0);
order.setTotalAmount(application.getTotalAmount());
order.setStatus(2); // 进行中
order.setCreateTime(new Date());
tutorOrderMapper.insert(order);
application.setStatus(1); // 已确认
application.setConfirmTime(new Date());
tutorApplicationMapper.updateById(application);
// 更新家教信息状态为已接单
TutorInfo tutorInfo = tutorInfoMapper.selectById(application.getTutorInfoId());
tutorInfo.setStatus(2);
tutorInfo.setOrderId(order.getId());
tutorInfoMapper.updateById(tutorInfo);
sendNotification(application.getParentId(), "教员已确认您的申请,可以开始授课");
return Result.success("接单成功,订单已生成");
} else {
// 教员拒绝申请
application.setStatus(2); // 已拒绝
application.setRejectReason("教员时间安排冲突");
tutorApplicationMapper.updateById(application);
sendNotification(application.getParentId(), "很抱歉,教员无法接受您的申请");
return Result.success("已拒绝该申请");
}
}
/**
* 核心功能三: 教学质量评价与反馈体系
* 处理授课完成确认、学习反馈、教学评价、教师信誉计算等业务
*/
@PostMapping("/submitCourseFeedback")
@Transactional(rollbackFor = Exception.class)
public Result submitCourseFeedback(@RequestBody CourseFeedback feedback, HttpServletRequest request) {
String token = request.getHeader("Authorization");
Long teacherId = JwtUtil.getUserId(token);
// 验证订单和授课记录
TutorOrder order = tutorOrderMapper.selectById(feedback.getOrderId());
if (order == null || !order.getTeacherId().equals(teacherId)) {
return Result.error("订单不存在或无权限操作");
}
// 检查是否重复提交
QueryWrapper<CourseFeedback> checkWrapper = new QueryWrapper<>();
checkWrapper.eq("order_id", feedback.getOrderId())
.eq("course_index", feedback.getCourseIndex());
if (courseFeedbackMapper.selectCount(checkWrapper) > 0) {
return Result.error("该课时反馈已提交,请勿重复提交");
}
// 保存授课反馈
feedback.setTeacherId(teacherId);
feedback.setParentId(order.getParentId());
feedback.setSubmitTime(new Date());
feedback.setStatus(0); // 待家长确认
courseFeedbackMapper.insert(feedback);
// 更新订单完成课时数
order.setCompletedCount(order.getCompletedCount() + 1);
// 判断是否全部完成
if (order.getCompletedCount().equals(order.getCourseCount())) {
order.setStatus(3); // 待评价
order.setFinishTime(new Date());
// 释放教员时段
TutorInfo tutorInfo = tutorInfoMapper.selectById(order.getTutorInfoId());
tutorInfo.setStatus(4); // 已完成
tutorInfoMapper.updateById(tutorInfo);
}
tutorOrderMapper.updateById(order);
sendNotification(order.getParentId(), "教员已提交第" + feedback.getCourseIndex() + "课时反馈,请查看确认");
return Result.success("授课反馈提交成功");
}
@PostMapping("/submitTeacherEvaluation")
@Transactional(rollbackFor = Exception.class)
public Result submitTeacherEvaluation(@RequestBody TeacherEvaluation evaluation, HttpServletRequest request) {
String token = request.getHeader("Authorization");
Long parentId = JwtUtil.getUserId(token);
// 验证订单状态
TutorOrder order = tutorOrderMapper.selectById(evaluation.getOrderId());
if (order == null || !order.getParentId().equals(parentId)) {
return Result.error("订单不存在或无权限评价");
}
if (order.getStatus() != 3) {
return Result.error("订单未完成,暂不能评价");
}
// 保存评价信息
evaluation.setParentId(parentId);
evaluation.setTeacherId(order.getTeacherId());
evaluation.setEvaluateTime(new Date());
// 计算综合评分
BigDecimal avgScore = BigDecimal.valueOf(
(evaluation.getTeachingScore() + evaluation.getAttitudeScore() +
evaluation.getEffectScore() + evaluation.getPunctualityScore()) / 4.0
).setScale(1, RoundingMode.HALF_UP);
evaluation.setAvgScore(avgScore);
teacherEvaluationMapper.insert(evaluation);
// 更新订单状态为已完成
order.setStatus(4);
tutorOrderMapper.updateById(order);
// 更新教员综合评分和评价数
Teacher teacher = teacherMapper.selectById(order.getTeacherId());
int totalEvaluations = teacher.getEvaluationCount() + 1;
BigDecimal newAvgScore = teacher.getAvgScore()
.multiply(BigDecimal.valueOf(teacher.getEvaluationCount()))
.add(avgScore)
.divide(BigDecimal.valueOf(totalEvaluations), 1, RoundingMode.HALF_UP);
teacher.setAvgScore(newAvgScore);
teacher.setEvaluationCount(totalEvaluations);
teacher.setCompletedOrders(teacher.getCompletedOrders() + 1);
// 根据评分更新教员等级
if (newAvgScore.compareTo(BigDecimal.valueOf(4.8)) >= 0 && totalEvaluations >= 20) {
teacher.setLevel(5); // 金牌教员
} else if (newAvgScore.compareTo(BigDecimal.valueOf(4.5)) >= 0 && totalEvaluations >= 10) {
teacher.setLevel(4); // 优秀教员
}
teacherMapper.updateById(teacher);
sendNotification(order.getTeacherId(), "家长已完成评价,综合评分:" + avgScore);
return Result.success("评价提交成功,感谢您的反馈");
}
// 辅助方法:计算匹配度分数
private int calculateMatchScore(TutorInfo tutorInfo, TutorDemand demand) {
int score = 0;
// 课程类型完全匹配 +30分
if (tutorInfo.getCourseTypeId().equals(demand.getCourseTypeId())) {
score += 30;
}
// 价格匹配度 +25分
BigDecimal priceDiff = tutorInfo.getHourlyRate().subtract(demand.getExpectedPrice()).abs();
BigDecimal priceRatio = priceDiff.divide(demand.getExpectedPrice(), 2, RoundingMode.HALF_UP);
if (priceRatio.compareTo(BigDecimal.valueOf(0.1)) <= 0) {
score += 25;
} else if (priceRatio.compareTo(BigDecimal.valueOf(0.2)) <= 0) {
score += 15;
}
// 教员评分 +25分
Teacher teacher = teacherMapper.selectById(tutorInfo.getTeacherId());
score += teacher.getAvgScore().multiply(BigDecimal.valueOf(5)).intValue();
// 地域距离 +20分
if (tutorInfo.getRegion().equals(demand.getRegion())) {
score += 20;
}
return score;
}
private void sendNotification(Long userId, String message) {
// 推送通知实现(可接入WebSocket或消息队列)
Notification notification = new Notification();
notification.setUserId(userId);
notification.setMessage(message);
notification.setCreateTime(new Date());
notification.setIsRead(0);
notificationMapper.insert(notification);
}
六、部分文档展示
七、END
💕💕文末获取源码联系计算机编程果茶熊