Compare commits

..

4 Commits

Author SHA1 Message Date
gengxin
978e1a7bf2 分析数据 img 是否为空 2025-03-21 15:26:41 +08:00
670788339
c9db78ea94 在线课-外部讲师 补充 2025-03-21 09:42:02 +08:00
670788339
f33de0c326 在线课-外部讲师 2025-03-20 20:57:49 +08:00
670788339
4be72391ad 在线课-外部讲师报错 添加讲师类型 2025-03-20 17:37:04 +08:00
10 changed files with 80 additions and 167 deletions

View File

@@ -8,11 +8,9 @@ import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.boe.feign.api.courseweb.entity.ExamTestDto;
import com.boe.feign.api.courseweb.entity.ProjectStudyDto;
import com.boe.feign.api.courseweb.remote.ExternalRemoteClient;
import com.boe.feign.api.courseweb.remote.OffCourseRemoteClient;
import com.boe.feign.api.courseweb.remote.ProjectAdminRemoteClient;
import com.boe.feign.api.courseweb.remote.ProjectRemoteClient;
import com.boe.feign.api.courseweb.reps.ExamStudyRecordParam;
import com.boe.feign.api.infrastructure.entity.CommonSearchVo;
import com.boe.feign.api.infrastructure.entity.Dict;
import com.boe.feign.api.infrastructure.remote.DictRemoteClient;
@@ -75,8 +73,6 @@ public class ThirdApi {
@Resource
private ProjectRemoteClient projectRemoteClient;
@Resource
ExternalRemoteClient externalRemoteClient;
@Resource
private DictRemoteClient dictRemoteClient;
@@ -266,19 +262,11 @@ public class ThirdApi {
}
public List<StudyCourse> getStudyCourseList(String studyId, String courseId, String token) {
log.info(" 1 studyId = "+ studyId + " ,courseId = " + courseId );
if ( studyId == null || courseId == null ){
log.error(" 在线课学习记录 参数不能为空 ");
return new ArrayList<>();
}
StudyCourseVo studyCourseVo = new StudyCourseVo();
studyCourseVo.setStudyId(studyId);
studyCourseVo.setCourseId(courseId);
ProjectStudyDto projectStudyDto = new ProjectStudyDto();
// BeanUtil.copyProperties(studyCourseVo, studyCourseVo);
projectStudyDto.setStudyId(Long.parseLong(studyId));
projectStudyDto.setCourseId(Long.parseLong(courseId));
log.info(" 12 在线课学习记录 studyId = "+ projectStudyDto.getStudyId() + " ,courseId = " + projectStudyDto.getCourseId() );
BeanUtil.copyProperties(studyCourseVo, studyCourseVo);
projectRemoteClient.updateStudyStatus(projectStudyDto);
return new ArrayList<>();
}
@@ -394,8 +382,4 @@ public class ThirdApi {
.body()).orElseThrow(() -> new RuntimeException("token校验失败"));
log.info("updateOrSaveCourse = " + resp);
}
public void syncExamStudyRecord(ExamStudyRecordParam param) {
externalRemoteClient.syncExamStudyRecord(param);
}
}

View File

@@ -314,8 +314,10 @@ public class CoursePortalApi extends ApiBaseController{
User user = userService.get(ct.getTeacherId());
if(t!=null) {
ct.setRemark(t.getDescription());
ct.setSupplier(t.getSupplier());
ct.setTeacherType(t.getTeacherType());
if(redisTemplate.opsForValue().get(ct.getTeacherId())!=null){
if(Objects.equals(redisTemplate.opsForValue().get(ct.getTeacherId()), "1")){
if(Objects.equals(redisTemplate.opsForValue().get(ct.getTeacherId()), "1") && ( t==null || t.getTeacherType() == 1)){
ct.setTeacherName("BOE教师");
}
teacherCourseDto.setCourseId(ct.getCourseId());
@@ -335,7 +337,7 @@ public class CoursePortalApi extends ApiBaseController{
List<String> list=new ArrayList<>();
list.add(ct.getTeacherId());
getTeacherInfo(request.getHeader("Xboe-Access-Token"),list);
if(Objects.equals(redisTemplate.opsForValue().get(ct.getTeacherId()), "1")){
if(Objects.equals(redisTemplate.opsForValue().get(ct.getTeacherId()), "1") && ( t==null || t.getTeacherType() == 1)){
ct.setTeacherName("BOE教师");
}
teacherCourseDto.setCourseId(ct.getCourseId());

View File

@@ -56,5 +56,4 @@ public class CourseTeacher extends IdBaseEntity {
/**讲师类型 1 内部讲师 2外部讲师*/
@Transient
private Integer teacherType;
}

View File

@@ -480,7 +480,7 @@ public class CourseServiceImpl implements ICourseService {
String sql = "SELECT DISTINCT\n" +
"rt.course_id\n" +
"FROM\n" +
"boe.student s INNER JOIN boe.router_task rt on s.pid=rt.router_id inner join boe_course c on c.id=rt.course_id\n" +
"boe_new.student s INNER JOIN boe_new.router_task rt on s.pid=rt.router_id inner join boe_course c on c.id=rt.course_id\n" +
"\n" +
"WHERE\n" +
"\n" +
@@ -503,7 +503,7 @@ public class CourseServiceImpl implements ICourseService {
String sql = "SELECT DISTINCT\n" +
"pt.course_id\n" +
"FROM\n" +
"boe.student s INNER JOIN boe.project_task pt on s.pid=pt.project_id inner join boe_course c on c.id=pt.course_id\n" +
"boe_new.student s INNER JOIN boe_new.project_task pt on s.pid=pt.project_id inner join boe_course c on c.id=pt.course_id\n" +
"\n" +
"WHERE\n" +
"\n" +
@@ -560,8 +560,8 @@ public class CourseServiceImpl implements ICourseService {
String sql = "SELECT DISTINCT\n" +
"\tc.id \n" +
"FROM\n" +
"\tboe.student s\n" +
"\tINNER JOIN boe.grow_task gt ON s.pid = gt.grow_id\n" +
"\tboe_new.student s\n" +
"\tINNER JOIN boe_new.grow_task gt ON s.pid = gt.grow_id\n" +
"\tINNER JOIN boe_course c ON gt.course_id = c.id \n" +
"WHERE\n" +
"\ts.type = 14 \n" +

View File

@@ -8,8 +8,6 @@ import java.util.Map;
import javax.annotation.Resource;
import com.boe.feign.api.courseweb.reps.ExamStudyRecordParam;
import com.xboe.api.ThirdApi;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -39,10 +37,7 @@ public class AloneExamServiceImpl implements IAloneExamService{
@Resource
AloneExamDao aeDao;
@Resource
private ThirdApi thirdApi;
@Override
@Transactional
public void save(AloneExamAnswer aea){
@@ -106,18 +101,7 @@ public class AloneExamServiceImpl implements IAloneExamService{
// //这种情况汶是不存在的
// }
}
try {
ExamStudyRecordParam param = new ExamStudyRecordParam();
param.setTestId(aea.getTestId());
param.setAid(aea.getAid());
thirdApi.syncExamStudyRecord(param);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@Override
@Transactional

View File

@@ -214,11 +214,11 @@ public class StudyCourseApi extends ApiBaseController{
redisTemplate.opsForValue().set(teacherVo.get(0).getTeacherId(), teacherVo.get(0).getStatus());
//设置过期时间为1天
redisTemplate.expire(teacherVo.get(0).getTeacherId(), 24 * 60 * 60, TimeUnit.SECONDS);
if (Objects.equals(redisTemplate.opsForValue().get(ct.getTeacherId()), "1") && t.getTeacherType() == 1 ){
if (Objects.equals(redisTemplate.opsForValue().get(ct.getTeacherId()), "1") && ( t==null || t.getTeacherType() == 1)){
ct.setTeacherName("BOE教师");
}
}
if (Objects.equals(redisTemplate.opsForValue().get(ct.getTeacherId()), "1") && t.getTeacherType() == 1 ){
if (Objects.equals(redisTemplate.opsForValue().get(ct.getTeacherId()), "1") && ( t==null || t.getTeacherType() == 1)){
ct.setTeacherName("BOE教师");
}
}
@@ -345,8 +345,6 @@ public class StudyCourseApi extends ApiBaseController{
}
//追加学习时长
studyService.appendStudyDuration(sci.getStudyId(),item.getId(),sci.getContentId(),sci.getDuration());
log.info(" 1 在线课学习记录 sci.getStudyId() = "+ sci.getStudyId() + " , sci.getCourseId() = " + sci.getCourseId() );
List<StudyCourse> allUserList = thirdApi.getStudyCourseList(sci.getStudyId() ,sci.getCourseId(), token);
log.info("在线课学习记录"+allUserList);
return success(item.getId());
@@ -367,8 +365,6 @@ public class StudyCourseApi extends ApiBaseController{
studyService.saveStudyInfo(sci,token);
//学习记录成功后处理
studyService.appendStudyDuration(sci.getStudyId(),sci.getStudyItemId(),sci.getContentId(),sci.getDuration());
log.info("在线课学习记录 sci.getStudyId() = "+ sci.getStudyId() + " , sci.getCourseId() = " + sci.getCourseId() );
List<StudyCourse> allUserList = thirdApi.getStudyCourseList(sci.getStudyId() ,sci.getCourseId(), token);
log.info("在线课学习记录"+allUserList);
//System.out.println("在线课学习记录"+allUserList);

View File

@@ -1,9 +1,18 @@
package com.xboe.school.study.api;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.xboe.core.orm.FieldFilters;
import com.xboe.core.orm.QueryBuilder;
import com.xboe.module.course.dao.CourseDao;
import com.xboe.module.course.dto.RankingDto;
import com.xboe.module.course.entity.Course;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@@ -42,6 +51,9 @@ public class StudyCourseESApi extends ApiBaseController{
@Autowired
IStudyCourseService service;
@Resource
private CourseDao courseDao;
@Resource
private PhpOnlineStudyRecordScheduledTasks phpOnlineStudyRecordScheduledTasks;
@@ -54,6 +66,58 @@ public class StudyCourseESApi extends ApiBaseController{
try {
dto.setAccountId(getCurrent().getAccountId());
PageList<CourseStudyDto> rs=search.search(page.getStartRow(),page.getPageSize(), dto);
List<CourseStudyDto> list = rs.getList();
List<String> emptyIds = new ArrayList<>();
log.info("test data gengxin CourseStudyDto list ==> {}", JSON.toJSONString(list));
if(CollectionUtil.isNotEmpty(list)){
log.info("test data gengxin CourseStudyDto isNotEmpty list ==> {}", JSON.toJSONString(list));
//todo 过滤数据
for(CourseStudyDto courseStudyDto : list){
log.info("test data gengxin CourseStudyDto isNotEmpty item ==> {}", JSON.toJSONString(courseStudyDto));
//在线课 录播课
if(courseStudyDto.getCourseType() == 20 || courseStudyDto.getCourseType() == 21){
if(StringUtils.isBlank(courseStudyDto.getCourseImage())){
emptyIds.add(courseStudyDto.getCourseId());
}
}
}
//todo 图片空返回结果
List<CourseStudyDto> emptyImgCourseStudyDtos = new ArrayList();
//在线课查询
if(CollectionUtil.isNotEmpty(emptyIds)){
QueryBuilder query = QueryBuilder.from(Course.class);
query.addFields("id","name","type","coverImg");
//todo 确认下 是否是这个字段
query.addFilter(FieldFilters.in("id",emptyIds));
query.addFilter(FieldFilters.eq("enabled",true));
query.addFilter(FieldFilters.eq("deleted",false));
List<Object[]> listFields = courseDao.findListFields(query.builder());
log.info("test data gengxin CourseStudyDto isNotEmpty listFields ==> {}", JSON.toJSONString(listFields));
if(CollectionUtil.isNotEmpty(listFields)){
for(Object[] objs : listFields) {
CourseStudyDto CourseStudyDtoResult=new CourseStudyDto();
CourseStudyDtoResult.setId((String) objs[0]);
CourseStudyDtoResult.setCourseName((String)objs[1]);
CourseStudyDtoResult.setCourseType((Integer) objs[2]);
CourseStudyDtoResult.setCourseImage((String)objs[3]);
emptyImgCourseStudyDtos.add(CourseStudyDtoResult);
}
}
log.info("test data gengxin CourseStudyDto isNotEmpty emptyImgCourseStudyDtos ==> {}", JSON.toJSONString(emptyImgCourseStudyDtos));
//todo 进行赋值处理 最外层
emptyImgCourseStudyDtos.forEach(item -> {
list.forEach(subjectItem -> {
if(item.getCourseId().equals(subjectItem.getCourseId())){
//赋值
subjectItem.setCourseImage(item.getCourseImage());
}
});
});
log.info("test data gengxin CourseStudyDto isNotEmpty result ==> {}", JSON.toJSONString(list));
}
}
return success(rs);
}catch(Exception e) {
log.error("查询报名学习ES失败",e);

View File

@@ -1,99 +0,0 @@
package com.xboe.school.study.api;
import com.xboe.school.study.service.IStudyService;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* @author by lyc
* @date 2025/3/3
*/
@Component
@Slf4j
@RequiredArgsConstructor
public class StudyCourseTask {
private final IStudyService studyService;
private final StringRedisTemplate redisTemplate;
/**
* 定时任务
* 获取redis 中学习结束的数据更新入库
* */
@XxlJob("saveStudyCourseItemLastTime")
public void saveStudyCourseItemLastTime() {
// 1. 定义匹配模式匹配所有目标key
final String KEY_PATTERN = "studyContentId:*:last_active";
// 2. 使用SCAN安全遍历避免阻塞
ScanOptions options = ScanOptions.scanOptions()
.match(KEY_PATTERN)
.count(100) // 分页大小
.build();
try (RedisConnection connection = Objects.requireNonNull(redisTemplate.getConnectionFactory()).getConnection()) {
Cursor<byte[]> cursor = connection.scan(options);
// 3. 遍历处理符合条件的key
while (cursor.hasNext()) {
String redisKey = new String(cursor.next());
// 4. 获取剩余TTL
Long ttl = redisTemplate.getExpire(redisKey, TimeUnit.SECONDS);
// 5. 过滤条件:剩余时间 >= 29天23小时30分钟转换为秒
// 总需时间 = (30天 - 30分钟) = 29天23小时30分钟 = 2590200秒
// 5分钟 300秒 || 2592000 - 300 = 2591700
if (ttl <= 2590200) {
try {
// 6. 提取studyContentId
String[] parts = redisKey.split(":");
if (parts.length < 2) continue;
String studyContentId = parts[1];
// 7. 获取存储的时间点(示例逻辑)
String lastStudyTimeStr = redisTemplate.opsForValue().get(redisKey);
if (lastStudyTimeStr == null) continue;
int lastStudyTime = Integer.parseInt(lastStudyTimeStr);
// 8. 更新数据库(调用已有服务方法)
studyService.updateStudyCourseItemLastTime(studyContentId, lastStudyTime, "system_job");
// 9. 删除Redis键原子操作
redisTemplate.delete(redisKey);
log.info("处理成功 key: {}, lastStudyTime: {}", redisKey, lastStudyTime);
} catch (Exception e) {
log.error("处理失败 key: {}", redisKey, e);
}
}
}
cursor.close();
} catch (Exception e) {
log.error("定时任务执行异常", e);
}
/* // 新增日志逻辑
if (ttl <= 172800) {
studyService.saveCourseExpireLog(
studyContentId,
lastStudyTime,
redisKey,
ttl,
"system_job"
);
}*/
}
}

View File

@@ -99,5 +99,4 @@ public interface IStudyService {
List<StudyCourseItem> getList(String courseId, String contentId, String name, Integer status);
void updateStudyCourseItemLastTime(String studyContentId, int lastStudyTime, String systemJob);
}

View File

@@ -1,6 +1,5 @@
package com.xboe.school.study.service.impl;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
@@ -16,7 +15,6 @@ import com.xboe.school.study.entity.StudyCourse;
import com.xboe.system.user.entity.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.xboe.common.OrderCondition;
@@ -53,10 +51,7 @@ public class StudyServiceImpl implements IStudyService{
@Autowired
UserDao userDao;
@Autowired
StringRedisTemplate redisTemplate;
@Override
public StudyCourseItem checkHas(String studyId,String contentId) {
List<StudyCourseItem> items = scItemDao.findList(FieldFilters.eq("studyId", studyId),FieldFilters.eq("contentId", contentId));
@@ -328,21 +323,9 @@ public class StudyServiceImpl implements IStudyService{
}
// 更新 前端传输已学习时长
@Override
public void updateLastTime(String studyContentId, int lastStudyTime,String aid) {
// 20250303 优化 多次更新改一次更新
// 更新Redis中的最后活跃时间带30秒过期
redisTemplate.opsForValue().set(
"studyContentId:" + studyContentId + ":last_active",
String.valueOf(lastStudyTime),
Duration.ofSeconds(2592000)
);
// Duration.ofDays(30) 也就是 2592000秒
}
@Override
@Transactional
public void updateStudyCourseItemLastTime(String studyContentId, int lastStudyTime,String aid) {
public void updateLastTime(String studyContentId, int lastStudyTime,String aid) {
// 更新最后的学习时间点
LocalDateTime now=LocalDateTime.now();
UpdateBuilder update=UpdateBuilder.from(StudyCourseItem.class);
@@ -352,6 +335,7 @@ public class StudyServiceImpl implements IStudyService{
update.addUpdateField("lastStudyTime", lastStudyTime);
update.addUpdateField("lastTime", now);
scItemDao.update(update.builder());
//增加用户的学习时长,在api中调用
}
@Override