feat: 优化课程任务管理功能

1. 添加按部门查询课程任务接口,返回数据中包含用户名
2. 优化任务更新逻辑,只更新非空字段
3. 添加自动更新时间戳功能
4. 更新API文档,完善接口说明
This commit is contained in:
Hvemi_han 2024-12-20 11:06:32 +08:00
parent 3db4fb2f98
commit d1aafdae85
6 changed files with 394 additions and 7 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -394,6 +394,96 @@
}
```
### 6. 按部门ID查询课程任务
- **接口**`GET /api/lesson-tasks/department/{departmentId}`
- **描述**:获取指定部门下正常状态用户的课程任务列表(分页)
- **认证**:需要
- **路径参数**
- `departmentId`: 部门ID
- **查询参数**
- `page`: 页码从1开始
- `size`: 每页数量默认10
- **成功响应**
```json
{
"code": 10000,
"message": "成功",
"data": {
"content": [
{
"id": 1,
"courseName": "物理",
"microLessonName": "微课1-1",
"userId": 1,
"username": "教师账号1", // 新增:用户名字段
"progressStatus": 4,
"scriptUploadTime": 1734498510000,
"scriptConfirmTime": 1734498510000,
"videoCaptureTime": 1734498510000,
"videoConfirmTime": 1734498510000,
"finishTime": 1734498510000,
"advise": null,
"createdAt": 1734578081000,
"updatedAt": 1734580393000
}
],
"totalElements": 10,
"totalPages": 1,
"size": 10,
"number": 0,
"first": true,
"last": true,
"empty": false
}
}
```
### 7. 更新课程任务进度
- **接口**`PUT /api/lesson-tasks/{id}`
- **描述**:更新课程任务的进度状态和建议
- **认证**:需要
- **路径参数**
- `id`: 课程任务ID
- **请求体**
```json
{
"progressStatus": 2, // 进度状态(可选)
"advise": "{\"method\":\"wechat\",\"uploaded\":true}" // 建议(可选)
}
```
- **说明**
- 更新进度状态时会自动更新对应的时间戳:
- 状态1更新scriptUploadTime
- 状态2更新scriptConfirmTime
- 状态3更新videoCaptureTime
- 状态4更新videoConfirmTime
- 状态5更新finishTime
- 只会更新请求体中包含的字段,未提供的字段保持不变
- **成功响应**
```json
{
"code": 10000,
"message": "成功",
"data": {
"id": 10,
"courseName": "测试课程",
"microLessonName": "测试微课",
"userId": 1,
"progressStatus": 2,
"scriptUploadTime": null,
"scriptConfirmTime": 1734663755667,
"videoCaptureTime": null,
"videoConfirmTime": null,
"finishTime": null,
"advise": "{\"method\":\"wechat\",\"uploaded\":true}",
"createdAt": 1734602440561,
"updatedAt": 1734663755000
}
}
```
## 注意事项
1. 所有需要认证的接口必须在请求头中携带有效的 JWT 令牌

View File

@ -3,6 +3,7 @@ package com.huertian.jinduguanli.controller;
import com.huertian.jinduguanli.common.ApiResponse;
import com.huertian.jinduguanli.common.ErrorCode;
import com.huertian.jinduguanli.dto.LessonTaskRequest;
import com.huertian.jinduguanli.dto.LessonTaskDTO;
import com.huertian.jinduguanli.entity.LessonTask;
import com.huertian.jinduguanli.service.LessonTaskService;
import jakarta.validation.Valid;
@ -51,6 +52,22 @@ public class LessonTaskController {
}
}
@GetMapping("/department/{departmentId}")
public ApiResponse<Page<LessonTaskDTO>> getTasksByDepartment(
@PathVariable Long departmentId,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
logger.info("收到部门课程任务查询请求部门ID: {}", departmentId);
try {
PageRequest pageRequest = PageRequest.of(page - 1, size);
Page<LessonTaskDTO> tasks = lessonTaskService.findByDepartmentIdAndNormalUser(departmentId, pageRequest);
return ApiResponse.success(tasks);
} catch (Exception e) {
logger.error("查询部门课程任务失败", e);
return new ApiResponse<>(ErrorCode.SYSTEM_ERROR, "获取部门课程任务失败", null);
}
}
@PostMapping
public ApiResponse<LessonTask> createTask(@Valid @RequestBody LessonTaskRequest request) {
logger.info("收到创建课程任务请求");

View File

@ -0,0 +1,154 @@
package com.huertian.jinduguanli.dto;
import com.huertian.jinduguanli.entity.LessonTask;
import lombok.Data;
@Data
public class LessonTaskDTO {
private Long id;
private String courseName;
private String microLessonName;
private Long userId;
private String username; // 添加用户名字段
private Integer progressStatus;
private Long scriptUploadTime;
private Long scriptConfirmTime;
private Long videoCaptureTime;
private Long videoConfirmTime;
private Long finishTime;
private String advise;
private Long createdAt;
private Long updatedAt;
// LessonTask 实体转换为 DTO
public static LessonTaskDTO fromEntity(LessonTask lessonTask, String username) {
LessonTaskDTO dto = new LessonTaskDTO();
dto.setId(lessonTask.getId());
dto.setCourseName(lessonTask.getCourseName());
dto.setMicroLessonName(lessonTask.getMicroLessonName());
dto.setUserId(lessonTask.getUserId());
dto.setUsername(username);
dto.setProgressStatus(lessonTask.getProgressStatus());
dto.setScriptUploadTime(lessonTask.getScriptUploadTime());
dto.setScriptConfirmTime(lessonTask.getScriptConfirmTime());
dto.setVideoCaptureTime(lessonTask.getVideoCaptureTime());
dto.setVideoConfirmTime(lessonTask.getVideoConfirmTime());
dto.setFinishTime(lessonTask.getFinishTime());
dto.setAdvise(lessonTask.getAdvise());
dto.setCreatedAt(lessonTask.getCreatedAt());
dto.setUpdatedAt(lessonTask.getUpdatedAt());
return dto;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getMicroLessonName() {
return microLessonName;
}
public void setMicroLessonName(String microLessonName) {
this.microLessonName = microLessonName;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getProgressStatus() {
return progressStatus;
}
public void setProgressStatus(Integer progressStatus) {
this.progressStatus = progressStatus;
}
public Long getScriptUploadTime() {
return scriptUploadTime;
}
public void setScriptUploadTime(Long scriptUploadTime) {
this.scriptUploadTime = scriptUploadTime;
}
public Long getScriptConfirmTime() {
return scriptConfirmTime;
}
public void setScriptConfirmTime(Long scriptConfirmTime) {
this.scriptConfirmTime = scriptConfirmTime;
}
public Long getVideoCaptureTime() {
return videoCaptureTime;
}
public void setVideoCaptureTime(Long videoCaptureTime) {
this.videoCaptureTime = videoCaptureTime;
}
public Long getVideoConfirmTime() {
return videoConfirmTime;
}
public void setVideoConfirmTime(Long videoConfirmTime) {
this.videoConfirmTime = videoConfirmTime;
}
public Long getFinishTime() {
return finishTime;
}
public void setFinishTime(Long finishTime) {
this.finishTime = finishTime;
}
public String getAdvise() {
return advise;
}
public void setAdvise(String advise) {
this.advise = advise;
}
public Long getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Long createdAt) {
this.createdAt = createdAt;
}
public Long getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Long updatedAt) {
this.updatedAt = updatedAt;
}
}

View File

@ -4,9 +4,61 @@ import com.huertian.jinduguanli.entity.LessonTask;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Repository
public interface LessonTaskRepository extends JpaRepository<LessonTask, Long> {
Page<LessonTask> findByUserId(Long userId, Pageable pageable);
/**
* 查询指定部门的所有课程任务
* 通过连接users表查询属于指定部门的所有用户的课程任务
*/
@Query("SELECT lt FROM LessonTask lt JOIN User u ON lt.userId = u.id WHERE u.departmentId = :departmentId")
List<LessonTask> findByDepartmentId(@Param("departmentId") Long departmentId);
/**
* 分页查询指定部门的所有课程任务
*/
@Query("SELECT lt FROM LessonTask lt JOIN User u ON lt.userId = u.id WHERE u.departmentId = :departmentId")
Page<LessonTask> findByDepartmentId(@Param("departmentId") Long departmentId, Pageable pageable);
/**
* 按部门ID和状态查询课程任务分页
*/
@Query("SELECT lt FROM LessonTask lt JOIN User u ON lt.userId = u.id WHERE u.departmentId = :departmentId AND (:status IS NULL OR lt.progressStatus = :status)")
Page<LessonTask> findByDepartmentIdAndStatus(
@Param("departmentId") Long departmentId,
@Param("status") Integer status,
Pageable pageable);
/**
* 按部门ID和用户状态查询课程任务分页
*/
@Query("SELECT lt FROM LessonTask lt JOIN User u ON lt.userId = u.id WHERE u.departmentId = :departmentId AND (:userStatus IS NULL OR u.status = :userStatus)")
Page<LessonTask> findByDepartmentIdAndUserStatus(
@Param("departmentId") Long departmentId,
@Param("userStatus") Integer userStatus,
Pageable pageable);
/**
* 按部门ID查询正常状态用户的课程任务分页
*/
@Query("SELECT lt FROM LessonTask lt JOIN User u ON lt.userId = u.id WHERE u.departmentId = :departmentId AND u.status = 1")
Page<LessonTask> findByDepartmentIdAndNormalUser(
@Param("departmentId") Long departmentId,
Pageable pageable);
/**
* 按部门ID查询正常状态用户的课程任务分页包含用户名
*/
@Query("SELECT new map(lt as lessonTask, u.username as username) FROM LessonTask lt JOIN User u ON lt.userId = u.id WHERE u.departmentId = :departmentId AND u.status = 1")
Page<Map<String, Object>> findByDepartmentIdAndNormalUserWithUsername(
@Param("departmentId") Long departmentId,
Pageable pageable);
}

View File

@ -1,5 +1,6 @@
package com.huertian.jinduguanli.service;
import com.huertian.jinduguanli.dto.LessonTaskDTO;
import com.huertian.jinduguanli.dto.LessonTaskRequest;
import com.huertian.jinduguanli.entity.LessonTask;
import com.huertian.jinduguanli.repository.LessonTaskRepository;
@ -66,17 +67,46 @@ public class LessonTaskService {
@Transactional
@CacheEvict(value = { "lessonTasks", "lessonTask" }, allEntries = true)
public LessonTask update(Long id, LessonTaskRequest request) {
logger.info("开始更新课程任务 - 任务ID: {}, 课程名称: {}, 小课名称: {}",
id, request.getCourseName(), request.getMicroLessonName());
logger.info("开始更新课程任务 - 任务ID: {}, 进度状态: {}", id, request.getProgressStatus());
LessonTask task = findById(id);
// 保留原有的进度状态如果请求中包含新的进度状态则更新
Integer originalStatus = task.getProgressStatus();
BeanUtils.copyProperties(request, task);
if (task.getProgressStatus() == null) {
task.setProgressStatus(originalStatus);
// 只更新非空字段
if (request.getProgressStatus() != null) {
task.setProgressStatus(request.getProgressStatus());
// 根据进度状态更新时间戳
long currentTime = System.currentTimeMillis();
switch (request.getProgressStatus()) {
case 1: // 脚本上传
task.setScriptUploadTime(currentTime);
break;
case 2: // 脚本确认
task.setScriptConfirmTime(currentTime);
break;
case 3: // 视频拍摄
task.setVideoCaptureTime(currentTime);
break;
case 4: // 视频确认
task.setVideoConfirmTime(currentTime);
break;
case 5: // 任务完成
task.setFinishTime(currentTime);
break;
}
}
if (request.getAdvise() != null) {
task.setAdvise(request.getAdvise());
}
if (request.getCourseName() != null) {
task.setCourseName(request.getCourseName());
}
if (request.getMicroLessonName() != null) {
task.setMicroLessonName(request.getMicroLessonName());
}
if (request.getUserId() != null) {
task.setUserId(request.getUserId());
}
task.setUpdatedAt(System.currentTimeMillis());
LessonTask updatedTask = lessonTaskRepository.save(task);
logger.info("更新课程任务成功 - 任务ID: {}", updatedTask.getId());
return updatedTask;
@ -94,6 +124,50 @@ public class LessonTaskService {
logger.info("删除课程任务成功 - 任务ID: {}", id);
}
/**
* 根据部门ID查询正常状态用户的课程任务列表分页包含用户名
*
* @param departmentId 部门ID
* @param pageable 分页参数
* @return 课程任务分页数据
*/
public Page<LessonTaskDTO> findByDepartmentIdAndNormalUser(Long departmentId, Pageable pageable) {
logger.info("查询部门正常用户的课程任务部门ID: {}", departmentId);
Page<java.util.Map<String, Object>> result = lessonTaskRepository.findByDepartmentIdAndNormalUserWithUsername(departmentId, pageable);
return result.map(map -> {
LessonTask lessonTask = (LessonTask) map.get("lessonTask");
String username = (String) map.get("username");
return LessonTaskDTO.fromEntity(lessonTask, username);
});
}
/**
* 根据部门ID和状态查询课程任务列表分页
*
* @param departmentId 部门ID
* @param status 任务状态可选0-脚本上传, 1-脚本确认, 2-视频拍摄, 3-后期制作, 4-任务完成
* @param pageable 分页参数
* @return 课程任务分页数据
*/
public Page<LessonTask> findByDepartmentIdAndStatus(Long departmentId, Integer status, Pageable pageable) {
logger.info("查询部门课程任务部门ID: {}, 状态: {}", departmentId, status);
return lessonTaskRepository.findByDepartmentIdAndStatus(departmentId, status, pageable);
}
/**
* 根据部门ID和用户状态查询课程任务列表分页
*
* @param departmentId 部门ID
* @param userStatus 用户状态可选1-正常, 0-禁用
* @param pageable 分页参数
* @return 课程任务分页数据
*/
public Page<LessonTask> findByDepartmentIdAndUserStatus(Long departmentId, Integer userStatus, Pageable pageable) {
logger.info("查询部门课程任务部门ID: {}, 用户状态: {}", departmentId, userStatus);
return lessonTaskRepository.findByDepartmentIdAndUserStatus(departmentId, userStatus, pageable);
}
private void validateRequest(LessonTaskRequest request) {
if (request.getCourseName() == null || request.getCourseName().trim().isEmpty()) {
throw new IllegalArgumentException("课程名称不能为空");