diff --git a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java index 23a56c7..b9b2d82 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java +++ b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java @@ -1,26 +1,32 @@ package org.cmh.backend.CourseManagement.controller; -import jakarta.persistence.EntityNotFoundException; import org.cmh.backend.CourseManagement.dto.GetCourseListResponse; import org.cmh.backend.CourseManagement.dto.MessageResponse; import org.cmh.backend.CourseManagement.dto.CourseRequest; +import org.cmh.backend.CourseManagement.dto.SearchCourseRequest; import org.cmh.backend.CourseManagement.model.Course; import org.cmh.backend.CourseManagement.service.CourseService; -import org.cmh.backend.Utils.JwtVerify; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; +import jakarta.persistence.EntityNotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + @RestController @RequestMapping("/courses") public class CourseController { + + private static final Logger logger = LoggerFactory.getLogger(CourseController.class); + @Autowired private CourseService courseService; @GetMapping -// @JwtVerify public ResponseEntity getCoursesByRange(@RequestParam Integer start, @RequestParam Integer end, @RequestParam String token) { if (start >= end) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); @@ -30,49 +36,82 @@ public class CourseController { } @GetMapping("/{id}") -// @JwtVerify public ResponseEntity getCoursePage(@PathVariable Long id, @RequestParam String token) { try { return new ResponseEntity<>(courseService.getCourseById(id), HttpStatus.OK); } catch (EntityNotFoundException e) { + logger.error("Course not found with id: {}", id, e); return new ResponseEntity<>(HttpStatus.NOT_FOUND); } } @PostMapping -// @JwtVerify public ResponseEntity createCourse(@RequestBody CourseRequest request) { try { courseService.createCourse(request); } catch (DataIntegrityViolationException e) { + logger.error("Create course failed: Data integrity violation", e); return new ResponseEntity<>(new MessageResponse("创建失败,课程已存在或缺少字段"), HttpStatus.BAD_REQUEST); } catch (Exception e) { + logger.error("Create course failed: {}", e.getMessage(), e); return new ResponseEntity<>(new MessageResponse("创建失败:" + e.getMessage()), HttpStatus.BAD_REQUEST); } return new ResponseEntity<>(new MessageResponse("创建成功"), HttpStatus.CREATED); } @PutMapping("/{id}") -// @JwtVerify public ResponseEntity updateCourse(@PathVariable Long id, @RequestBody CourseRequest request) { try { courseService.updateCourse(id, request); } catch (DataIntegrityViolationException e) { + logger.error("Update course failed: Data integrity violation", e); return new ResponseEntity<>(new MessageResponse("修改失败,新标题已存在或缺少字段"), HttpStatus.BAD_REQUEST); + } catch (EntityNotFoundException e) { + logger.error("Course not found with id: {}", id, e); + return new ResponseEntity<>(new MessageResponse("修改失败: 课程不存在"), HttpStatus.NOT_FOUND); } catch (Exception e) { + logger.error("Update course failed: {}", e.getMessage(), e); return new ResponseEntity<>(new MessageResponse("修改失败:" + e.getMessage()), HttpStatus.BAD_REQUEST); } return new ResponseEntity<>(new MessageResponse("修改成功"), HttpStatus.OK); } @DeleteMapping("/{id}") -// @JwtVerify public ResponseEntity deleteCourse(@PathVariable Long id, @RequestParam String token) { try { courseService.deleteCourse(id); } catch (EntityNotFoundException e) { + logger.error("Course not found with id: {}", id, e); return new ResponseEntity<>(new MessageResponse("删除失败,课程不存在"), HttpStatus.BAD_REQUEST); + } catch (Exception e) { + logger.error("Delete course failed: {}", e.getMessage(), e); + return new ResponseEntity<>(new MessageResponse("删除失败:" + e.getMessage()), HttpStatus.BAD_REQUEST); } return new ResponseEntity<>(new MessageResponse("删除成功"), HttpStatus.OK); } + + @GetMapping("/search") + public ResponseEntity searchCourses(@RequestParam String token, + @RequestParam(required = false) String title, + @RequestParam(required = false) String author, + @RequestParam(required = false) String description, + @RequestParam(required = false) String sortOrder, + @RequestParam Integer start, + @RequestParam Integer end) { + if (start >= end) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + try { + SearchCourseRequest request = new SearchCourseRequest(token, title, author, description, sortOrder, start, end); + List courses = courseService.searchCourses(request); + long courseCount = courseService.getCourseCountByCriteria(title, author, description, sortOrder); + + return new ResponseEntity<>(new GetCourseListResponse(courseCount, courses), HttpStatus.OK); + } catch (Exception e) { + logger.error("Search courses failed with parameters: title={}, author={}, description={}, sortOrder={}, start={}, end={}", + title, author, description, sortOrder, start, end, e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/dto/SearchCourseRequest.java b/src/main/java/org/cmh/backend/CourseManagement/dto/SearchCourseRequest.java new file mode 100644 index 0000000..aac0c93 --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/dto/SearchCourseRequest.java @@ -0,0 +1,18 @@ +package org.cmh.backend.CourseManagement.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +public class SearchCourseRequest { + private String token; + private String title; + private String author; + private String description; + private String sortOrder; + private int start; + private int end; +} \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java b/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java index d65909a..40e0281 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java +++ b/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java @@ -4,7 +4,10 @@ import org.cmh.backend.CourseManagement.model.Course; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -public interface CourseRepository extends JpaRepository { +@Repository +public interface CourseRepository extends JpaRepository, JpaSpecificationExecutor { Page findAllByOrderByIdDesc(Pageable pageable); } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java index d8c3926..92546e7 100644 --- a/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java +++ b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java @@ -1,94 +1,72 @@ package org.cmh.backend.CourseManagement.service; -import jakarta.persistence.EntityNotFoundException; import org.cmh.backend.CourseManagement.dto.CourseRequest; +import org.cmh.backend.CourseManagement.dto.SearchCourseRequest; import org.cmh.backend.CourseManagement.model.Course; import org.cmh.backend.CourseManagement.repository.CourseRepository; +import org.cmh.backend.CourseManagement.specification.CourseSpecification; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; - -import java.util.ArrayList; +import jakarta.persistence.EntityNotFoundException; import java.util.List; @Service public class CourseService { + @Autowired private CourseRepository courseRepository; + public long getCourseCount() { + return courseRepository.count(); + } + public List getCoursesByRange(int start, int end) { - if (start < 0 || end <= start) { - throw new IllegalArgumentException("Invalid start or end range"); - } + Pageable pageable = PageRequest.of(start, end - start); + return courseRepository.findAll(pageable).getContent(); + } - int pageSize = end - start; // 计算每页的大小 - int startPageNumber = start / pageSize; // 计算起始页码 - int endPageNumber = (end - 1) / pageSize; // 计算结束页码 - - List result = new ArrayList<>(); - - for (int pageNumber = startPageNumber; pageNumber <= endPageNumber; pageNumber++) { - Pageable pageable = PageRequest.of(pageNumber, pageSize); - Page coursePage = courseRepository.findAllByOrderByIdDesc(pageable); - - if (coursePage.hasContent()) { - result.addAll(coursePage.getContent()); - } else { - break; // 如果没有更多内容,提前退出 - } - } - - int startIndex = start % pageSize; - int endIndex = startIndex + (end - start); - - if (endIndex > result.size()) { - endIndex = result.size(); - } - - return result.subList(startIndex, endIndex); + public Course getCourseById(Long id) { + return courseRepository.findById(id).orElseThrow(() -> new EntityNotFoundException("Course not found")); } public void createCourse(CourseRequest request) { Course course = new Course(); course.setTitle(request.getTitle()); + course.setAuthor(request.getAuthor()); course.setDescription(request.getDescription()); course.setOrderNo(request.getOrderNo()); - course.setAuthor(request.getAuthor()); - course.setVideoPath(request.getVideoPath()); - course.setImagePath(request.getImagePath()); courseRepository.save(course); } public void updateCourse(Long id, CourseRequest request) { - Course course = courseRepository.findById(id).orElse(null); - if (course != null) { - course.setTitle(request.getTitle()); - course.setDescription(request.getDescription()); - course.setOrderNo(request.getOrderNo()); - course.setAuthor(request.getAuthor()); - course.setVideoPath(request.getVideoPath()); - course.setImagePath(request.getImagePath()); - courseRepository.save(course); - } + Course course = courseRepository.findById(id).orElseThrow(() -> new EntityNotFoundException("Course not found")); + course.setTitle(request.getTitle()); + course.setAuthor(request.getAuthor()); + course.setDescription(request.getDescription()); + course.setOrderNo(request.getOrderNo()); + courseRepository.save(course); } public void deleteCourse(Long id) { - if (!courseRepository.existsById(id)) { - throw new EntityNotFoundException(); - } courseRepository.deleteById(id); } - public Course getCourseById(Long id) { - if (!courseRepository.existsById(id)) { - throw new EntityNotFoundException(); - } - return courseRepository.findById(id).orElse(null); + public List searchCourses(SearchCourseRequest request) { + Pageable pageable = PageRequest.of(request.getStart(), request.getEnd() - request.getStart()); + return courseRepository.findAll( + CourseSpecification.searchCourses( + request.getTitle(), + request.getAuthor(), + request.getDescription(), + request.getSortOrder() + ), + pageable + ).getContent(); } - public long getCourseCount() { - return courseRepository.count(); + public long getCourseCountByCriteria(String title, String author, String description, String sortOrder) { + return courseRepository.count(CourseSpecification.searchCourses(title, author, description, sortOrder)); } } \ No newline at end of file diff --git a/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java b/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java new file mode 100644 index 0000000..69be0ef --- /dev/null +++ b/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java @@ -0,0 +1,34 @@ +package org.cmh.backend.CourseManagement.specification; + +import org.cmh.backend.CourseManagement.model.Course; +import org.springframework.data.jpa.domain.Specification; + +import jakarta.persistence.criteria.Predicate; +import java.util.ArrayList; +import java.util.List; + +public class CourseSpecification { + + public static Specification searchCourses( + String title, String author, String description, String sortOrder) { + + return (root, query, criteriaBuilder) -> { + List predicates = new ArrayList<>(); + + if (title != null && !title.isEmpty()) { + predicates.add(criteriaBuilder.like(root.get("title"), "%" + title + "%")); + } + if (author != null && !author.isEmpty()) { + predicates.add(criteriaBuilder.like(root.get("author"), "%" + author + "%")); + } + if (description != null && !description.isEmpty()) { + predicates.add(criteriaBuilder.like(root.get("description"), "%" + description + "%")); + } + if (sortOrder != null && !sortOrder.isEmpty()) { + predicates.add(criteriaBuilder.like(root.get("orderNo"), "%" + sortOrder+ "%")); + } + + return criteriaBuilder.and(predicates.toArray(new Predicate[0])); + }; + } +} \ No newline at end of file