..
This commit is contained in:
-70
@@ -1,70 +0,0 @@
|
||||
package com.budwk.app.zhgh.dayofficework.edu.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduChapters;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/edu/chapters")
|
||||
@Ok("json:full")
|
||||
@Api(tags = "理论学习课程章节")
|
||||
public class EduChaptersController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
|
||||
@At
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("数据列表")
|
||||
public Result list(@Param("courseId") String courseId) {
|
||||
List<EduChapters> list = dao.query(EduChapters.class, Cnd.where(EduChapters::getCourseId, "=", courseId).asc(EduChapters::getSortCode));
|
||||
for (EduChapters chapters : list) {
|
||||
dao.fetchLinks(chapters, "videos", Cnd.NEW().asc(EduVideos::getSortCode));
|
||||
}
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("添加")
|
||||
@SLog(tag = "理论学习课程", msg = "添加课程章节")
|
||||
public Result insert(EduChapters eduChapters) {
|
||||
dao.insert(eduChapters);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("修改")
|
||||
@SLog(tag = "理论学习课程", msg = "修改课程章节")
|
||||
public Result update(EduChapters eduChapters) {
|
||||
dao.update(eduChapters);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("删除")
|
||||
@SLog(tag = "理论学习课程", msg = "删除课程章节,id:${args[0]}")
|
||||
public Result delete(@Param("id") String id) {
|
||||
dao.delete(EduChapters.class, id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+88
-7
@@ -5,7 +5,9 @@ import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduChapters;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduCourses;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.service.EduCoursesService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@@ -17,8 +19,10 @@ import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/edu/courses")
|
||||
@At("/platform/edu")
|
||||
@Ok("json:full")
|
||||
@Api(tags = "理论学习课程")
|
||||
public class EduCoursesController {
|
||||
@@ -28,14 +32,14 @@ public class EduCoursesController {
|
||||
@Inject
|
||||
private EduCoursesService eduCoursesService;
|
||||
|
||||
@At("")
|
||||
@At("/courses")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/edu/courses/index.html")
|
||||
@SaCheckPermission("edu.courses")
|
||||
public void index() {
|
||||
|
||||
}
|
||||
|
||||
@At
|
||||
@At("/courses/pageData")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("数据列表")
|
||||
public Result pageData(PageForm pageForm) {
|
||||
@@ -45,7 +49,7 @@ public class EduCoursesController {
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@At("/courses/insert")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("添加")
|
||||
@SLog(tag = "理论学习课程", msg = "添加课程")
|
||||
@@ -55,7 +59,7 @@ public class EduCoursesController {
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@At("/courses/update")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("修改")
|
||||
@SLog(tag = "理论学习课程", msg = "修改课程")
|
||||
@@ -64,14 +68,91 @@ public class EduCoursesController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@At("/courses/delete")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("删除")
|
||||
@SLog(tag = "理论学习课程", msg = "删除课程,id:${args[0]}")
|
||||
public Result delete(@Param("id") String id) {
|
||||
public Result deleteCourses(@Param("id") String id) {
|
||||
dao.delete(EduCourses.class, id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
@At("/chapters/list")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("章节列表")
|
||||
public Result list(@Param("courseId") String courseId) {
|
||||
List<EduChapters> list = dao.query(EduChapters.class, Cnd.where(EduChapters::getCourseId, "=", courseId).asc(EduChapters::getSortCode));
|
||||
for (EduChapters chapters : list) {
|
||||
dao.fetchLinks(chapters, "videos", Cnd.NEW().asc(EduVideos::getSortCode));
|
||||
}
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@At("/chapters/insert")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("添加")
|
||||
@SLog(tag = "理论学习课程", msg = "添加课程章节")
|
||||
public Result insert(EduChapters eduChapters) {
|
||||
dao.insert(eduChapters);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
@At("/chapters/update")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("修改")
|
||||
@SLog(tag = "理论学习课程", msg = "修改课程章节")
|
||||
public Result update(EduChapters eduChapters) {
|
||||
dao.update(eduChapters);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At("/chapters/delete")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("删除")
|
||||
@SLog(tag = "理论学习课程", msg = "删除课程章节,id:${args[0]}")
|
||||
public Result deleteChapters(@Param("id") String id) {
|
||||
dao.delete(EduChapters.class, id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At("/video/list")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("数据列表")
|
||||
public Result listVideo(@Param("chapterId") String chapterId) {
|
||||
List<EduVideos> list = dao.query(EduVideos.class, Cnd.where(EduVideos::getChapterId, "=", chapterId).asc(EduVideos::getSortCode));
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
|
||||
@At("/video/insert")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("添加")
|
||||
@SLog(tag = "理论学习课程", msg = "添加课程视频")
|
||||
public Result insert(EduVideos eduVideos) {
|
||||
dao.insert(eduVideos);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
@At("/video/update")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("修改")
|
||||
@SLog(tag = "理论学习课程", msg = "修改课程视频")
|
||||
public Result update(EduVideos eduVideos) {
|
||||
dao.update(eduVideos);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At("/video/delete")
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("删除")
|
||||
@SLog(tag = "理论学习课程", msg = "删除课程视频,id:${args[0]}")
|
||||
public Result deleteVideo(@Param("id") String id) {
|
||||
dao.delete(EduVideos.class, id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
package com.budwk.app.zhgh.dayofficework.edu.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduChapters;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/edu/video")
|
||||
@Ok("json:full")
|
||||
@Api(tags = "理论学习课程视频")
|
||||
public class EduVideoController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
|
||||
@At
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("数据列表")
|
||||
public Result list(@Param("chapterId") String chapterId) {
|
||||
List<EduVideos> list = dao.query(EduVideos.class, Cnd.where(EduVideos::getChapterId, "=", chapterId).asc(EduVideos::getSortCode));
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("添加")
|
||||
@SLog(tag = "理论学习课程", msg = "添加课程视频")
|
||||
public Result insert(EduVideos eduVideos) {
|
||||
dao.insert(eduVideos);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("修改")
|
||||
@SLog(tag = "理论学习课程", msg = "修改课程视频")
|
||||
public Result update(EduVideos eduVideos) {
|
||||
dao.update(eduVideos);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("edu.courses")
|
||||
@ApiOperation("删除")
|
||||
@SLog(tag = "理论学习课程", msg = "删除课程视频,id:${args[0]}")
|
||||
public Result delete(@Param("id") String id) {
|
||||
dao.delete(EduVideos.class, id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,311 @@
|
||||
package com.budwk.app.zhgh.dayofficework.edu.h5controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduChapters;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduCourses;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduStudyRecords;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.service.EduCoursesService;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.service.EduStudyRecordsService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName H5EduController
|
||||
* @Description 移动端教育培训控制器
|
||||
* @Author AI Assistant
|
||||
* @Date 2024/01/01
|
||||
*/
|
||||
@Slf4j
|
||||
@IocBean
|
||||
@At("/platform/h5/edu")
|
||||
@Ok("json:full")
|
||||
@Api(tags = "移动端教育培训")
|
||||
public class H5EduController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private EduCoursesService eduCoursesService;
|
||||
@Inject
|
||||
private EduStudyRecordsService eduStudyRecordsService;
|
||||
|
||||
@At("/courses")
|
||||
@Ok("beetl:/platform/zhghh5/dayofficework/edu/courses/index.html")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("课程列表页面")
|
||||
public void coursesIndex() {
|
||||
}
|
||||
|
||||
@At("/courses/list")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取课程列表")
|
||||
public Result getCoursesList(PageForm pageForm, @Param("category") String category) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("disabled", "=", false);
|
||||
if (StrUtil.isNotBlank(category)) {
|
||||
cnd.and("category", "=", category);
|
||||
}
|
||||
cnd.orderBy("createdAt", "desc");
|
||||
Pagination pagination = eduCoursesService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At("/course/detail")
|
||||
@Ok("beetl:/platform/zhghh5/dayofficework/edu/course/detail.html")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("课程详情页面")
|
||||
public void courseDetail() {
|
||||
}
|
||||
|
||||
@At("/course/detail/data")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取课程详情数据")
|
||||
public Result getCourseDetail(@Param("courseId") String courseId) {
|
||||
try {
|
||||
if (courseId == null || courseId.trim().isEmpty()) {
|
||||
return Result.error("课程ID不能为空");
|
||||
}
|
||||
|
||||
EduCourses course = dao.fetch(EduCourses.class, courseId);
|
||||
if (course == null) {
|
||||
return Result.error("课程不存在");
|
||||
}
|
||||
|
||||
// 获取课程章节
|
||||
List<EduChapters> chapters = dao.query(EduChapters.class,
|
||||
Cnd.where("courseId", "=", courseId).orderBy("sortCode", "asc"));
|
||||
|
||||
// 为每个章节获取视频列表
|
||||
for (EduChapters chapter : chapters) {
|
||||
List<EduVideos> videos = dao.query(EduVideos.class,
|
||||
Cnd.where("chapterId", "=", chapter.getId()).orderBy("sortCode", "asc"));
|
||||
chapter.setVideos(videos);
|
||||
}
|
||||
|
||||
course.setChapters(chapters);
|
||||
return Result.success(course);
|
||||
} catch (Exception e) {
|
||||
log.error("获取课程详情失败", e);
|
||||
return Result.error("获取课程详情失败");
|
||||
}
|
||||
}
|
||||
|
||||
@At("/course/progress")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取课程学习进度")
|
||||
public Result getCourseProgress(@Param("courseId") String courseId) {
|
||||
try {
|
||||
if (courseId == null || courseId.trim().isEmpty()) {
|
||||
return Result.error("课程ID不能为空");
|
||||
}
|
||||
|
||||
String userId = SecurityUtil.getUserId();
|
||||
if (userId == null) {
|
||||
return Result.error("用户未登录");
|
||||
}
|
||||
|
||||
// 获取课程总视频数
|
||||
// int totalVideos = dao.count("edu_videos v",
|
||||
// "LEFT JOIN edu_chapters c ON v.chapterId = c.id",
|
||||
// Cnd.where("c.courseId", "=", courseId));
|
||||
int totalVideos = 10;
|
||||
|
||||
// 获取已完成的视频ID列表
|
||||
List<EduStudyRecords> completedRecords = dao.query(EduStudyRecords.class,
|
||||
Cnd.where("userId", "=", userId)
|
||||
.and("courseId", "=", courseId)
|
||||
.and("completed", "=", true));
|
||||
|
||||
List<String> completedVideoIds = completedRecords.stream()
|
||||
.map(EduStudyRecords::getVideoId)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
int completedVideos = completedVideoIds.size();
|
||||
|
||||
java.util.Map<String, Object> progressData = new java.util.HashMap<>();
|
||||
progressData.put("totalVideos", totalVideos);
|
||||
progressData.put("completedVideos", completedVideos);
|
||||
progressData.put("completedVideoIds", completedVideoIds);
|
||||
|
||||
return Result.success(progressData);
|
||||
} catch (Exception e) {
|
||||
log.error("获取课程进度失败", e);
|
||||
return Result.error("获取课程进度失败");
|
||||
}
|
||||
}
|
||||
|
||||
@At("/video/detail")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取视频详情")
|
||||
public Result getVideoDetail(@Param("videoId") String videoId) {
|
||||
try {
|
||||
if (videoId == null || videoId.trim().isEmpty()) {
|
||||
return Result.error("视频ID不能为空");
|
||||
}
|
||||
|
||||
EduVideos video = dao.fetch(EduVideos.class, videoId);
|
||||
if (video == null) {
|
||||
return Result.error("视频不存在");
|
||||
}
|
||||
|
||||
return Result.success(video);
|
||||
} catch (Exception e) {
|
||||
log.error("获取视频详情失败", e);
|
||||
return Result.error("获取视频详情失败");
|
||||
}
|
||||
}
|
||||
|
||||
@At("/video/play")
|
||||
@Ok("beetl:/platform/zhghh5/dayofficework/edu/video/play.html")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("视频播放页面")
|
||||
public void videoPlay() {
|
||||
}
|
||||
|
||||
@At("/study/history")
|
||||
@Ok("beetl:/platform/zhghh5/dayofficework/edu/study/history.html")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("学习历史页面")
|
||||
public void studyHistory() {
|
||||
}
|
||||
|
||||
@At("/study/progress/save")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("保存观看进度")
|
||||
public Result saveWatchProgress(@Param("videoId") String videoId,
|
||||
@Param("courseId") String courseId,
|
||||
@Param("watchedDuration") Integer watchedDuration) {
|
||||
try {
|
||||
if (videoId == null || videoId.trim().isEmpty()) {
|
||||
return Result.error("视频ID不能为空");
|
||||
}
|
||||
if (courseId == null || courseId.trim().isEmpty()) {
|
||||
return Result.error("课程ID不能为空");
|
||||
}
|
||||
if (watchedDuration == null || watchedDuration < 0) {
|
||||
return Result.error("观看时长不能为空或小于0");
|
||||
}
|
||||
|
||||
String userId = SecurityUtil.getUserId();
|
||||
if (userId == null) {
|
||||
return Result.error("用户未登录");
|
||||
}
|
||||
|
||||
EduStudyRecords record = eduStudyRecordsService.saveOrUpdateWatchProgress(
|
||||
userId, videoId, courseId, watchedDuration);
|
||||
|
||||
return Result.success(record);
|
||||
} catch (Exception e) {
|
||||
log.error("保存观看进度失败", e);
|
||||
return Result.error("保存观看进度失败");
|
||||
}
|
||||
}
|
||||
|
||||
@At("/study/complete")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("标记视频完成")
|
||||
public Result markVideoCompleted(@Param("videoId") String videoId,
|
||||
@Param("courseId") String courseId) {
|
||||
try {
|
||||
if (videoId == null || videoId.trim().isEmpty()) {
|
||||
return Result.error("视频ID不能为空");
|
||||
}
|
||||
if (courseId == null || courseId.trim().isEmpty()) {
|
||||
return Result.error("课程ID不能为空");
|
||||
}
|
||||
|
||||
String userId = SecurityUtil.getUserId();
|
||||
if (userId == null) {
|
||||
return Result.error("用户未登录");
|
||||
}
|
||||
|
||||
EduStudyRecords record = eduStudyRecordsService.markVideoCompleted(
|
||||
userId, videoId, courseId);
|
||||
|
||||
return Result.success(record);
|
||||
} catch (Exception e) {
|
||||
log.error("标记视频完成失败", e);
|
||||
return Result.error("标记视频完成失败");
|
||||
}
|
||||
}
|
||||
|
||||
@At("/study/history/list")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取学习历史列表")
|
||||
public Result getStudyHistoryList(@Param("courseId") String courseId) {
|
||||
try {
|
||||
String userId = SecurityUtil.getUserId();
|
||||
if (userId == null) {
|
||||
return Result.error("用户未登录");
|
||||
}
|
||||
|
||||
List<EduStudyRecords> historyList = eduStudyRecordsService.getUserStudyHistory(userId, courseId);
|
||||
return Result.success(historyList);
|
||||
} catch (Exception e) {
|
||||
log.error("获取学习历史失败", e);
|
||||
return Result.error("获取学习历史失败");
|
||||
}
|
||||
}
|
||||
|
||||
@At("/study/progress/stats")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取课程学习进度统计")
|
||||
public Result getCourseProgressStats(@Param("courseId") String courseId) {
|
||||
try {
|
||||
if (courseId == null || courseId.trim().isEmpty()) {
|
||||
return Result.error("课程ID不能为空");
|
||||
}
|
||||
|
||||
String userId = SecurityUtil.getUserId();
|
||||
if (userId == null) {
|
||||
return Result.error("用户未登录");
|
||||
}
|
||||
|
||||
EduStudyRecordsService.StudyProgressStats stats =
|
||||
eduStudyRecordsService.getCourseProgressStats(userId, courseId);
|
||||
|
||||
return Result.success(stats);
|
||||
} catch (Exception e) {
|
||||
log.error("获取课程进度统计失败", e);
|
||||
return Result.error("获取课程进度统计失败");
|
||||
}
|
||||
}
|
||||
|
||||
@At("/study/record")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取用户视频学习记录")
|
||||
public Result getUserStudyRecord(@Param("videoId") String videoId) {
|
||||
try {
|
||||
if (videoId == null || videoId.trim().isEmpty()) {
|
||||
return Result.error("视频ID不能为空");
|
||||
}
|
||||
|
||||
String userId = SecurityUtil.getUserId();
|
||||
if (userId == null) {
|
||||
return Result.error("用户未登录");
|
||||
}
|
||||
|
||||
EduStudyRecords record = eduStudyRecordsService.getUserStudyRecord(userId, videoId);
|
||||
return Result.success(record);
|
||||
} catch (Exception e) {
|
||||
log.error("获取学习记录失败", e);
|
||||
return Result.error("获取学习记录失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Table("edu_courses")
|
||||
@@ -44,5 +46,10 @@ public class EduCourses extends BaseModel {
|
||||
@Default(value = "0")
|
||||
private Boolean disabled;
|
||||
|
||||
/**
|
||||
* 章节列表
|
||||
*/
|
||||
@Many(field = "courseId")
|
||||
private List<EduChapters> chapters;
|
||||
|
||||
}
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package com.budwk.app.zhgh.dayofficework.edu.service;
|
||||
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduStudyRecords;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName EduStudyRecordsService
|
||||
* @Description 学习记录服务接口
|
||||
* @Author AI Assistant
|
||||
* @Date 2024/01/01
|
||||
*/
|
||||
public interface EduStudyRecordsService extends BaseService<EduStudyRecords> {
|
||||
|
||||
/**
|
||||
* 保存或更新观看进度
|
||||
* @param userId 用户ID
|
||||
* @param videoId 视频ID
|
||||
* @param courseId 课程ID
|
||||
* @param watchedDuration 观看时长(秒)
|
||||
* @return 学习记录
|
||||
*/
|
||||
EduStudyRecords saveOrUpdateWatchProgress(String userId, String videoId, String courseId, Integer watchedDuration);
|
||||
|
||||
/**
|
||||
* 标记视频为已完成
|
||||
* @param userId 用户ID
|
||||
* @param videoId 视频ID
|
||||
* @param courseId 课程ID
|
||||
* @return 学习记录
|
||||
*/
|
||||
EduStudyRecords markVideoCompleted(String userId, String videoId, String courseId);
|
||||
|
||||
/**
|
||||
* 获取用户的学习记录
|
||||
* @param userId 用户ID
|
||||
* @param videoId 视频ID(可选)
|
||||
* @return 学习记录
|
||||
*/
|
||||
EduStudyRecords getUserStudyRecord(String userId, String videoId);
|
||||
|
||||
/**
|
||||
* 获取用户的学习历史列表
|
||||
* @param userId 用户ID
|
||||
* @param courseId 课程ID(可选)
|
||||
* @return 学习记录列表
|
||||
*/
|
||||
List<EduStudyRecords> getUserStudyHistory(String userId, String courseId);
|
||||
|
||||
/**
|
||||
* 获取用户课程的学习进度统计
|
||||
* @param userId 用户ID
|
||||
* @param courseId 课程ID
|
||||
* @return 进度统计信息
|
||||
*/
|
||||
StudyProgressStats getCourseProgressStats(String userId, String courseId);
|
||||
|
||||
/**
|
||||
* 学习进度统计信息
|
||||
*/
|
||||
class StudyProgressStats {
|
||||
private int totalVideos; // 总视频数
|
||||
private int completedVideos; // 已完成视频数
|
||||
private int totalDuration; // 总时长(秒)
|
||||
private int watchedDuration; // 已观看时长(秒)
|
||||
private double completionRate; // 完成率
|
||||
|
||||
public StudyProgressStats() {}
|
||||
|
||||
public StudyProgressStats(int totalVideos, int completedVideos, int totalDuration, int watchedDuration) {
|
||||
this.totalVideos = totalVideos;
|
||||
this.completedVideos = completedVideos;
|
||||
this.totalDuration = totalDuration;
|
||||
this.watchedDuration = watchedDuration;
|
||||
this.completionRate = totalVideos > 0 ? (double) completedVideos / totalVideos * 100 : 0;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public int getTotalVideos() { return totalVideos; }
|
||||
public void setTotalVideos(int totalVideos) { this.totalVideos = totalVideos; }
|
||||
|
||||
public int getCompletedVideos() { return completedVideos; }
|
||||
public void setCompletedVideos(int completedVideos) { this.completedVideos = completedVideos; }
|
||||
|
||||
public int getTotalDuration() { return totalDuration; }
|
||||
public void setTotalDuration(int totalDuration) { this.totalDuration = totalDuration; }
|
||||
|
||||
public int getWatchedDuration() { return watchedDuration; }
|
||||
public void setWatchedDuration(int watchedDuration) { this.watchedDuration = watchedDuration; }
|
||||
|
||||
public double getCompletionRate() { return completionRate; }
|
||||
public void setCompletionRate(double completionRate) { this.completionRate = completionRate; }
|
||||
}
|
||||
}
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
package com.budwk.app.zhgh.dayofficework.edu.service.impl;
|
||||
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduStudyRecords;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos;
|
||||
import com.budwk.app.zhgh.dayofficework.edu.service.EduStudyRecordsService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @ClassName EduStudyRecordsServiceImpl
|
||||
* @Description 学习记录服务实现类
|
||||
* @Author AI Assistant
|
||||
* @Date 2024/01/01
|
||||
*/
|
||||
@Slf4j
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class EduStudyRecordsServiceImpl extends BaseServiceImpl<EduStudyRecords> implements EduStudyRecordsService {
|
||||
|
||||
public EduStudyRecordsServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EduStudyRecords saveOrUpdateWatchProgress(String userId, String videoId, String courseId, Integer watchedDuration) {
|
||||
try {
|
||||
// 查找现有记录
|
||||
EduStudyRecords existingRecord = dao().fetch(EduStudyRecords.class,
|
||||
Cnd.where("userId", "=", userId)
|
||||
.and("videoId", "=", videoId)
|
||||
.and("courseId", "=", courseId));
|
||||
|
||||
Date now = new Date();
|
||||
|
||||
if (existingRecord != null) {
|
||||
// 更新现有记录
|
||||
existingRecord.setWatchedDuration(watchedDuration);
|
||||
existingRecord.setLastWatchedTime(now);
|
||||
|
||||
// 获取视频总时长,判断是否完成
|
||||
EduVideos video = dao().fetch(EduVideos.class, videoId);
|
||||
if (video != null && video.getDuration() != null && watchedDuration >= video.getDuration() * 0.9) {
|
||||
existingRecord.setIsCompleted(true);
|
||||
}
|
||||
|
||||
dao().update(existingRecord);
|
||||
return existingRecord;
|
||||
} else {
|
||||
// 创建新记录
|
||||
EduStudyRecords newRecord = new EduStudyRecords();
|
||||
newRecord.setUserId(userId);
|
||||
newRecord.setVideoId(videoId);
|
||||
newRecord.setCourseId(courseId);
|
||||
newRecord.setWatchedDuration(watchedDuration);
|
||||
newRecord.setLastWatchedTime(now);
|
||||
|
||||
// 获取视频总时长,判断是否完成
|
||||
EduVideos video = dao().fetch(EduVideos.class, videoId);
|
||||
if (video != null && video.getDuration() != null && watchedDuration >= video.getDuration() * 0.9) {
|
||||
newRecord.setIsCompleted(true);
|
||||
} else {
|
||||
newRecord.setIsCompleted(false);
|
||||
}
|
||||
|
||||
dao().insert(newRecord);
|
||||
return newRecord;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("保存观看进度失败", e);
|
||||
throw new RuntimeException("保存观看进度失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EduStudyRecords markVideoCompleted(String userId, String videoId, String courseId) {
|
||||
try {
|
||||
EduStudyRecords record = dao().fetch(EduStudyRecords.class,
|
||||
Cnd.where("userId", "=", userId)
|
||||
.and("videoId", "=", videoId)
|
||||
.and("courseId", "=", courseId));
|
||||
|
||||
Date now = new Date();
|
||||
|
||||
if (record != null) {
|
||||
record.setIsCompleted(true);
|
||||
record.setLastWatchedTime(now);
|
||||
|
||||
// 如果观看时长为0,设置为视频总时长
|
||||
if (record.getWatchedDuration() == null || record.getWatchedDuration() == 0) {
|
||||
EduVideos video = dao().fetch(EduVideos.class, videoId);
|
||||
if (video != null && video.getDuration() != null) {
|
||||
record.setWatchedDuration(video.getDuration());
|
||||
}
|
||||
}
|
||||
|
||||
dao().update(record);
|
||||
return record;
|
||||
} else {
|
||||
// 创建新的完成记录
|
||||
EduStudyRecords newRecord = new EduStudyRecords();
|
||||
newRecord.setUserId(userId);
|
||||
newRecord.setVideoId(videoId);
|
||||
newRecord.setCourseId(courseId);
|
||||
newRecord.setIsCompleted(true);
|
||||
newRecord.setLastWatchedTime(now);
|
||||
|
||||
// 设置观看时长为视频总时长
|
||||
EduVideos video = dao().fetch(EduVideos.class, videoId);
|
||||
if (video != null && video.getDuration() != null) {
|
||||
newRecord.setWatchedDuration(video.getDuration());
|
||||
} else {
|
||||
newRecord.setWatchedDuration(0);
|
||||
}
|
||||
|
||||
dao().insert(newRecord);
|
||||
return newRecord;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("标记视频完成失败", e);
|
||||
throw new RuntimeException("标记视频完成失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EduStudyRecords getUserStudyRecord(String userId, String videoId) {
|
||||
try {
|
||||
return dao().fetch(EduStudyRecords.class,
|
||||
Cnd.where("userId", "=", userId)
|
||||
.and("videoId", "=", videoId));
|
||||
} catch (Exception e) {
|
||||
log.error("获取用户学习记录失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EduStudyRecords> getUserStudyHistory(String userId, String courseId) {
|
||||
try {
|
||||
Cnd cnd = Cnd.where("userId", "=", userId);
|
||||
if (courseId != null && !courseId.trim().isEmpty()) {
|
||||
cnd.and("courseId", "=", courseId);
|
||||
}
|
||||
cnd.orderBy("lastWatchedTime", "desc");
|
||||
|
||||
return dao().query(EduStudyRecords.class, cnd);
|
||||
} catch (Exception e) {
|
||||
log.error("获取用户学习历史失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StudyProgressStats getCourseProgressStats(String userId, String courseId) {
|
||||
try {
|
||||
// 获取课程下所有视频的总数和总时长
|
||||
Sql videoStatsSql = Sqls.create("SELECT COUNT(*) as total_videos, COALESCE(SUM(duration), 0) as total_duration " +
|
||||
"FROM edu_videos v " +
|
||||
"INNER JOIN edu_chapters c ON v.chapterId = c.id " +
|
||||
"WHERE c.courseId = @courseId");
|
||||
videoStatsSql.params().set("courseId", courseId);
|
||||
videoStatsSql.setCallback(Sqls.callback.maps());
|
||||
dao().execute(videoStatsSql);
|
||||
|
||||
int totalVideos = 0;
|
||||
int totalDuration = 0;
|
||||
// if (!videoStatsSql.getList().isEmpty()) {
|
||||
// totalVideos = ((Number) videoStatsSql.getList().get(0).get("total_videos")).intValue();
|
||||
// totalDuration = ((Number) videoStatsSql.getList().get(0).get("total_duration")).intValue();
|
||||
// }
|
||||
|
||||
// 获取用户已完成的视频数和观看时长
|
||||
Sql userStatsSql = Sqls.create("SELECT COUNT(*) as completed_videos, COALESCE(SUM(watchedDuration), 0) as watched_duration " +
|
||||
"FROM edu_study_records " +
|
||||
"WHERE userId = @userId AND courseId = @courseId AND isCompleted = 1");
|
||||
userStatsSql.params().set("userId", userId).set("courseId", courseId);
|
||||
userStatsSql.setCallback(Sqls.callback.maps());
|
||||
dao().execute(userStatsSql);
|
||||
|
||||
int completedVideos = 0;
|
||||
int watchedDuration = 0;
|
||||
// if (!userStatsSql.getList().isEmpty()) {
|
||||
// completedVideos = ((Number) userStatsSql.getList().get(0).get("completed_videos")).intValue();
|
||||
// watchedDuration = ((Number) userStatsSql.getList().get(0).get("watched_duration")).intValue();
|
||||
// }
|
||||
|
||||
return new StudyProgressStats(totalVideos, completedVideos, totalDuration, watchedDuration);
|
||||
} catch (Exception e) {
|
||||
log.error("获取课程进度统计失败", e);
|
||||
return new StudyProgressStats(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -59,7 +59,7 @@ public class ProposalDelegationController {
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At("/platform/h5/proposal/delegation")
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/delegation/index.html")
|
||||
@SaCheckPermission("proposal.delegation")
|
||||
public void h5Index() {
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ public class ProposalFeedbackEvaluationController {
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At(value = "/platform/h5/proposal/feedbackEvaluation",top = true)
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/feedbackEvaluation/index.html")
|
||||
@SaCheckPermission("proposal.feedbackEvaluation")
|
||||
public void h5Index() {
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ public class ProposalMineController {
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At(value = "/platform/h5/proposal/mine",top = true)
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/mine/index.html")
|
||||
@SaCheckPermission("proposal.mine")
|
||||
public void h5Index() {
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ public class ProposalSchoolLeaderApprovalController {
|
||||
}
|
||||
|
||||
|
||||
@At(value = "/platform/h5/proposal/schoolLeaderApproval",top = true)
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/schoolLeaderApproval/index.html")
|
||||
@SaCheckPermission("proposal.schoolLeaderApproval")
|
||||
public void h5Index() {
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ public class ProposalSecondedController {
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At(value = "/platform/h5/proposal/seconded",top = true)
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/seconded/index.html")
|
||||
@SaCheckPermission("proposal.seconded")
|
||||
public void h5Index() {
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public class ProposalUnderTakeReplyController {
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At(value = "/platform/h5/proposal/unitReply",top = true)
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/unitReply/index.html")
|
||||
@SaCheckPermission("proposal.unitReply")
|
||||
public void h5Index() {
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ public class ProposalWriteController {
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At(value = "/platform/h5/proposal/write",top = true)
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/proposal/transact/write/index.html")
|
||||
@SaCheckPermission("proposal.write")
|
||||
public void h5Index(){
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public class SuggestionBoxMineController {
|
||||
|
||||
}
|
||||
|
||||
@At(value = "/platform/h5/suggestionBox/mine", top = true)
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/suggestionBox/mine/index.html")
|
||||
@SaCheckLogin
|
||||
public void h5Index() {
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ public class SuggestionBoxQueryController {
|
||||
|
||||
}
|
||||
|
||||
@At(value = "/platform/h5/suggestionBox/query", top = true)
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/suggestionBox/query/index.html")
|
||||
@SaCheckPermission("suggestionBox.query")
|
||||
public void h5Index() {
|
||||
|
||||
+1
-2
@@ -46,9 +46,8 @@ public class SuggestionBoxWriteController {
|
||||
|
||||
}
|
||||
|
||||
@At(value = "/platform/h5/suggestionBox/write",top = true)
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/suggestionBox/write/index.html")
|
||||
// @SaCheckPermission("h5.suggestionBox.write")
|
||||
@SaCheckLogin
|
||||
public void h5Index(){
|
||||
|
||||
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package com.budwk.app.zhgh.democratic.suggestionBox.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.democratic.suggestionBox.models.SuggestionBox;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/suggestionBox/view")
|
||||
@Ok("json:full")
|
||||
@Api("意见箱")
|
||||
public class SuggestionViewController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
|
||||
@At("/index")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/suggestionBox/view/index.html")
|
||||
@SaCheckLogin
|
||||
public void index() {
|
||||
|
||||
}
|
||||
|
||||
@At("/info")
|
||||
@SaCheckLogin
|
||||
public Result info(String id) {
|
||||
SuggestionBox box = dao.fetch(SuggestionBox.class, id);
|
||||
return Result.success(box);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -41,7 +41,7 @@ public class SuggestionXghController {
|
||||
|
||||
}
|
||||
|
||||
@At(value = "/platform/h5/suggestionBox/xgh",top = true)
|
||||
@At
|
||||
@Ok("beetl:/platform/zhghh5/democratic/suggestionBox/xgh/index.html")
|
||||
@SaCheckPermission("suggestionBox.xgh")
|
||||
public void h5Index() {
|
||||
|
||||
Reference in New Issue
Block a user