diff --git a/pom.xml b/pom.xml
index 6c0c137..7b7ec21 100644
--- a/pom.xml
+++ b/pom.xml
@@ -93,11 +93,6 @@
runtime
true
-
-
-
-
-
com.mysql
mysql-connector-j
@@ -170,6 +165,17 @@
mysql
test
+
+ org.apache.poi
+ poi-ooxml
+ 5.2.3
+
+
+ javax.servlet
+ javax.servlet-api
+ 4.0.1
+ provided
+
diff --git a/src/main/java/org/cmh/backend/Config/SecurityConfig.java b/src/main/java/org/cmh/backend/Config/SecurityConfig.java
index c917d0a..c5a4336 100644
--- a/src/main/java/org/cmh/backend/Config/SecurityConfig.java
+++ b/src/main/java/org/cmh/backend/Config/SecurityConfig.java
@@ -4,6 +4,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@@ -11,13 +13,22 @@ public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
- // Use the new API to disable CSRF
+ // Disable CSRF
http.csrf(AbstractHttpConfigurer::disable)
- // Permit all requests
+ // Permit all requests to all endpoints
.authorizeHttpRequests(authorize -> authorize
- .anyRequest().permitAll()
- );
+ .anyRequest().permitAll() // Allow all requests without authentication
+ )
+ // Disable form login
+ .formLogin(AbstractHttpConfigurer::disable)
+ // Disable logout
+ .logout(AbstractHttpConfigurer::disable);
return http.build();
}
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
}
diff --git a/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java
new file mode 100644
index 0000000..a386572
--- /dev/null
+++ b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseController.java
@@ -0,0 +1,138 @@
+package org.cmh.backend.CourseManagement.controller;
+
+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.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
+ public ResponseEntity getCoursesByRange(@RequestParam Integer start, @RequestParam Integer end, @RequestParam String token) {
+ if (start >= end) {
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+ long courseCount = courseService.getCourseCount();
+ return new ResponseEntity<>(new GetCourseListResponse(courseCount, courseService.getCoursesByRange(start, end)), HttpStatus.OK);
+ }
+
+ @GetMapping("/{id}")
+ 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
+ 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}")
+ 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}")
+ 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);
+ }
+ }
+ @GetMapping("/sort")
+ public ResponseEntity sortCourses(@RequestParam String token,
+ @RequestParam String sortField,
+ @RequestParam String sortDirection,
+ @RequestParam Integer start,
+ @RequestParam Integer end) {
+ if (start >= end) {
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+
+ try {
+ long courseCount = courseService.getCourseCount();
+ List sortedCourses = courseService.sortCourses(sortField, sortDirection, start, end);
+
+ return new ResponseEntity<>(new GetCourseListResponse(courseCount, sortedCourses), HttpStatus.OK);
+ } catch (Exception e) {
+ logger.error("Sort courses failed with parameters: sortField={}, sortDirection={}, start={}, end={}",
+ sortField, sortDirection, 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/controller/CourseFileController.java b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseFileController.java
new file mode 100644
index 0000000..94cbf38
--- /dev/null
+++ b/src/main/java/org/cmh/backend/CourseManagement/controller/CourseFileController.java
@@ -0,0 +1,64 @@
+package org.cmh.backend.CourseManagement.controller;
+
+import org.cmh.backend.CourseManagement.dto.UploadFileResponse;
+import org.springframework.core.io.UrlResource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.core.io.Resource;
+import org.springframework.web.multipart.MultipartFile;
+
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+@RestController
+@RequestMapping("/courses")
+public class CourseFileController {
+ private static final String UPLOAD_DIR = "uploads/";
+
+ @PostMapping("/upload")
+ public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file) {
+ if (file.isEmpty()) {
+ return new ResponseEntity<>(new UploadFileResponse("文件不能为空", null), HttpStatus.BAD_REQUEST);
+ }
+
+ try {
+ // 确保上传目录存在
+ Path uploadDirPath = Paths.get(UPLOAD_DIR);
+ if (!Files.exists(uploadDirPath)) {
+ Files.createDirectories(uploadDirPath);
+ }
+
+ // 生成文件路径
+ byte[] bytes = file.getBytes();
+ Path path = Paths.get(UPLOAD_DIR + file.getOriginalFilename());
+ Files.write(path, bytes);
+
+ // 返回成功信息
+ return new ResponseEntity<>(new UploadFileResponse("文件上传成功", "/api/courses/files/" + file.getOriginalFilename()), HttpStatus.OK);
+ } catch (IOException e) {
+ return new ResponseEntity<>(new UploadFileResponse("文件上传失败", null), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+ @GetMapping("/files/{filename}")
+ public ResponseEntity getFile(@PathVariable String filename) {
+ try {
+ Path filePath = Paths.get(UPLOAD_DIR).resolve(filename).normalize();
+ Resource resource = new UrlResource(filePath.toUri());
+
+ if (resource.exists() && resource.isReadable()) {
+ return ResponseEntity.ok()
+ .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
+ .body(resource);
+ } else {
+ return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+ }
+ } catch (Exception e) {
+ return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+}
diff --git a/src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java b/src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java
new file mode 100644
index 0000000..86b1ff7
--- /dev/null
+++ b/src/main/java/org/cmh/backend/CourseManagement/dto/CourseRequest.java
@@ -0,0 +1,16 @@
+package org.cmh.backend.CourseManagement.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.cmh.backend.Utils.JwtRequest;
+
+@Getter
+@Setter
+public class CourseRequest extends JwtRequest {
+ private String title;
+ private String description;
+ private String orderNo;
+ private String author;
+ private String videoPath;
+ private String imagePath;
+}
\ No newline at end of file
diff --git a/src/main/java/org/cmh/backend/CourseManagement/dto/GetCourseListResponse.java b/src/main/java/org/cmh/backend/CourseManagement/dto/GetCourseListResponse.java
new file mode 100644
index 0000000..8e9d3d9
--- /dev/null
+++ b/src/main/java/org/cmh/backend/CourseManagement/dto/GetCourseListResponse.java
@@ -0,0 +1,16 @@
+package org.cmh.backend.CourseManagement.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import org.cmh.backend.CourseManagement.model.Course;
+
+import java.util.List;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class GetCourseListResponse {
+ Long courseCount;
+ List courseList;
+}
\ No newline at end of file
diff --git a/src/main/java/org/cmh/backend/CourseManagement/dto/MessageResponse.java b/src/main/java/org/cmh/backend/CourseManagement/dto/MessageResponse.java
new file mode 100644
index 0000000..92a14fa
--- /dev/null
+++ b/src/main/java/org/cmh/backend/CourseManagement/dto/MessageResponse.java
@@ -0,0 +1,12 @@
+package org.cmh.backend.CourseManagement.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class MessageResponse {
+ String message;
+}
\ 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/dto/UploadFileResponse.java b/src/main/java/org/cmh/backend/CourseManagement/dto/UploadFileResponse.java
new file mode 100644
index 0000000..2a8edb3
--- /dev/null
+++ b/src/main/java/org/cmh/backend/CourseManagement/dto/UploadFileResponse.java
@@ -0,0 +1,15 @@
+package org.cmh.backend.CourseManagement.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class UploadFileResponse extends MessageResponse {
+ private String url;
+
+ public UploadFileResponse(String message, String url) {
+ super(message);
+ this.url = url;
+ }
+}
diff --git a/src/main/java/org/cmh/backend/CourseManagement/model/Course.java b/src/main/java/org/cmh/backend/CourseManagement/model/Course.java
new file mode 100644
index 0000000..137fae8
--- /dev/null
+++ b/src/main/java/org/cmh/backend/CourseManagement/model/Course.java
@@ -0,0 +1,21 @@
+package org.cmh.backend.CourseManagement.model;
+
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.Setter;
+
+@Entity
+@Getter
+@Setter
+public class Course {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private String title;
+ private String description;
+ private String orderNo;
+ private String author;
+ private String videoPath;
+ private String imagePath;
+}
\ 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
new file mode 100644
index 0000000..40e0281
--- /dev/null
+++ b/src/main/java/org/cmh/backend/CourseManagement/repository/CourseRepository.java
@@ -0,0 +1,13 @@
+package org.cmh.backend.CourseManagement.repository;
+
+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;
+
+@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
new file mode 100644
index 0000000..3e00d0f
--- /dev/null
+++ b/src/main/java/org/cmh/backend/CourseManagement/service/CourseService.java
@@ -0,0 +1,82 @@
+package org.cmh.backend.CourseManagement.service;
+
+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.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+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) {
+ Pageable pageable = PageRequest.of(start, end - start);
+ return courseRepository.findAll(pageable).getContent();
+ }
+
+ 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.setVideoPath(request.getVideoPath()); // 确保保存视频路径
+ course.setImagePath(request.getImagePath()); // 确保保存图片路径
+ courseRepository.save(course);
+ }
+
+ public void updateCourse(Long id, CourseRequest request) {
+ 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());
+ course.setVideoPath(request.getVideoPath()); // 确保更新视频路径
+ course.setImagePath(request.getImagePath()); // 确保更新图片路径
+ courseRepository.save(course);
+ }
+
+ public void deleteCourse(Long id) {
+ courseRepository.deleteById(id);
+ }
+
+ 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 getCourseCountByCriteria(String title, String author, String description, String sortOrder) {
+ return courseRepository.count(CourseSpecification.searchCourses(title, author, description, sortOrder));
+ }
+ public List sortCourses(String sortField, String sortDirection, int start, int end) {
+ Pageable pageable = PageRequest.of(start, end - start);
+ return courseRepository.findAll(
+ CourseSpecification.sortCourses(sortField, sortDirection),
+ pageable
+ ).getContent();
+ }
+}
\ 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..23411a4
--- /dev/null
+++ b/src/main/java/org/cmh/backend/CourseManagement/specification/CourseSpecification.java
@@ -0,0 +1,44 @@
+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]));
+ };
+ }
+ public static Specification sortCourses(String sortField, String sortDirection) {
+ return (root, query, cb) -> {
+ if ("asc".equalsIgnoreCase(sortDirection)) {
+ query.orderBy(cb.asc(root.get(sortField)));
+ } else if ("desc".equalsIgnoreCase(sortDirection)) {
+ query.orderBy(cb.desc(root.get(sortField)));
+ }
+ return cb.conjunction();
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/cmh/backend/MeetingManagement/controller/MeetingController.java b/src/main/java/org/cmh/backend/MeetingManagement/controller/MeetingController.java
new file mode 100644
index 0000000..349c2ce
--- /dev/null
+++ b/src/main/java/org/cmh/backend/MeetingManagement/controller/MeetingController.java
@@ -0,0 +1,153 @@
+package org.cmh.backend.MeetingManagement.controller;
+
+import org.cmh.backend.MeetingManagement.model.Meeting;
+import org.cmh.backend.MeetingManagement.service.MeetingService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Map;
+
+
+@RestController
+@RequestMapping("/meetings")
+public class MeetingController {
+
+ @Autowired
+ private MeetingService meetingService;
+
+ private final DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+
+ @GetMapping("/listAll")
+ public ResponseEntity> listAll() {
+ List data = meetingService.getAllMeetings();
+ return ResponseEntity.ok(data);
+ }
+
+ @PostMapping("/addMeeting")
+ public ResponseEntity add(@RequestBody Map credentials) {
+ try {
+ Meeting meeting = new Meeting();
+ if (credentials.get("id") != null) {
+ meeting.setId(Long.parseLong(credentials.get("id")));
+ }
+ meeting.setName(credentials.get("name"));
+ meeting.setOrganizer(credentials.get("organizer"));
+
+ // Parse startTime and endTime to OffsetDateTime, then convert to LocalDateTime
+ OffsetDateTime startTime = OffsetDateTime.parse(credentials.get("startTime"), formatter);
+ OffsetDateTime endTime = OffsetDateTime.parse(credentials.get("endTime"), formatter);
+ meeting.setStartTime(startTime.toLocalDateTime());
+ meeting.setEndTime(endTime.toLocalDateTime());
+
+ meeting.setContent(credentials.get("content"));
+ meeting.setStatus(credentials.get("status"));
+
+ Meeting meetingAdd = meetingService.createMeeting(meeting);
+ return new ResponseEntity<>(meetingAdd, HttpStatus.CREATED);
+ } catch (Exception e) {
+ return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
+ }
+ }
+
+ @PostMapping("/deleteMeeting")
+ public ResponseEntity delete(@RequestBody Map credentials) {
+ try {
+ meetingService.deleteMeeting(Long.valueOf(credentials.get("id")));
+ return new ResponseEntity<>("success", HttpStatus.OK);
+ } catch (Exception e) {
+ return new ResponseEntity<>("failure", HttpStatus.BAD_REQUEST);
+ }
+ }
+
+
+ @PostMapping("/updateMeeting")
+ public ResponseEntity update(@RequestBody Map credentials) {
+ try {
+ // Validate and parse id
+ String idStr = credentials.get("id");
+ if (idStr == null || idStr.isEmpty()) {
+ throw new IllegalArgumentException("ID cannot be null or empty");
+ }
+ Long id = Long.parseLong(idStr);
+
+ // Validate and parse other fields
+ String name = credentials.get("name");
+ if (name == null || name.isEmpty()) {
+ throw new IllegalArgumentException("Name cannot be null or empty");
+ }
+
+ String organizer = credentials.get("organizer");
+ if (organizer == null || organizer.isEmpty()) {
+ throw new IllegalArgumentException("Organizer cannot be null or empty");
+ }
+
+ String startTimeStr = credentials.get("startTime");
+ if (startTimeStr == null || startTimeStr.isEmpty()) {
+ throw new IllegalArgumentException("Start time cannot be null or empty");
+ }
+ LocalDateTime startTime = LocalDateTime.parse(startTimeStr, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
+
+ String endTimeStr = credentials.get("endTime");
+ if (endTimeStr == null || endTimeStr.isEmpty()) {
+ throw new IllegalArgumentException("End time cannot be null or empty");
+ }
+ LocalDateTime endTime = LocalDateTime.parse(endTimeStr, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
+
+ String content = credentials.get("content");
+ if (content == null || content.isEmpty()) {
+ throw new IllegalArgumentException("Content cannot be null or empty");
+ }
+
+ String status = credentials.get("status");
+ if (status == null || status.isEmpty()) {
+ throw new IllegalArgumentException("Status cannot be null or empty");
+ }
+
+ // Create and update meeting
+ Meeting meeting = new Meeting();
+ meeting.setId(id);
+ meeting.setName(name);
+ meeting.setOrganizer(organizer);
+ meeting.setStartTime(startTime);
+ meeting.setEndTime(endTime);
+ meeting.setContent(content);
+ meeting.setStatus(status);
+
+ Meeting updatedMeeting = meetingService.updateMeeting(meeting.getId(), meeting);
+ return new ResponseEntity<>(updatedMeeting, HttpStatus.OK);
+ } catch (IllegalArgumentException e) {
+ return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
+ } catch (Exception e) {
+ return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ @PostMapping("/getMeetingById")
+ public ResponseEntity getById(@RequestBody Map credentials) {
+ try {
+ Meeting meeting = meetingService.getMeetingById(Long.valueOf(credentials.get("id"))).orElse(null);
+ return new ResponseEntity<>(meeting, HttpStatus.OK);
+ } catch (Exception e) {
+ return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
+ }
+ }
+
+ @PostMapping("/searchMeetings")
+ public ResponseEntity> searchMeetings(@RequestBody Map params) {
+ String name = params.get("name");
+ String organizer = params.get("organizer");
+ OffsetDateTime startTimeStr = OffsetDateTime.parse(params.get("startTime"), formatter);
+ LocalDateTime startTime1 = (startTimeStr.toLocalDateTime());
+ //LocalDateTime startTime = startTimeStr != null ? LocalDateTime.parse(startTimeStr) : null;
+
+ List meetings = meetingService.searchMeetings(name, organizer, startTime1);
+ return new ResponseEntity<>(meetings, HttpStatus.OK);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/cmh/backend/MeetingManagement/model/Meeting.java b/src/main/java/org/cmh/backend/MeetingManagement/model/Meeting.java
new file mode 100644
index 0000000..ff06aef
--- /dev/null
+++ b/src/main/java/org/cmh/backend/MeetingManagement/model/Meeting.java
@@ -0,0 +1,48 @@
+package org.cmh.backend.MeetingManagement.model;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import lombok.Getter;
+import lombok.Setter;
+import java.time.LocalDateTime;
+
+@Setter
+@Getter
+@Entity
+public class Meeting {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+ private String name;
+ private String organizer;
+ private LocalDateTime startTime; // Changed to LocalDateTime
+ private LocalDateTime endTime; // Changed to LocalDateTime
+ private String content;
+ private String status;
+
+ public Meeting() {}
+
+ public Meeting(String name, String organizer, LocalDateTime startTime, LocalDateTime endTime, String content, String status) {
+ this.name = name;
+ this.organizer = organizer;
+ this.startTime = startTime;
+ this.endTime = endTime;
+ this.content = content;
+ this.status = status;
+ }
+
+ @Override
+ public String toString() {
+ return "Meeting{" +
+ "id=" + id +
+ ", name='" + name + '\'' +
+ ", organizer='" + organizer + '\'' +
+ ", startTime=" + startTime +
+ ", endTime=" + endTime +
+ ", content='" + content + '\'' +
+ ", status='" + status + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/cmh/backend/MeetingManagement/repository/MeetingRepository.java b/src/main/java/org/cmh/backend/MeetingManagement/repository/MeetingRepository.java
new file mode 100644
index 0000000..20a987c
--- /dev/null
+++ b/src/main/java/org/cmh/backend/MeetingManagement/repository/MeetingRepository.java
@@ -0,0 +1,15 @@
+package org.cmh.backend.MeetingManagement.repository;
+
+import org.cmh.backend.MeetingManagement.model.Meeting;
+import org.springframework.data.jpa.repository.JpaRepository;
+import java.time.LocalDateTime;
+import java.util.List;
+import org.springframework.data.jpa.repository.Query;
+
+public interface MeetingRepository extends JpaRepository {
+ @Query("SELECT m FROM Meeting m WHERE " +
+ "(?1 IS NULL OR m.name LIKE %?1%) AND " +
+ "(?2 IS NULL OR m.organizer LIKE %?2%) AND " +
+ "(?3 IS NULL OR m.startTime >= ?3)")
+ List searchMeetings(String name, String organizer, LocalDateTime startTime);
+}
diff --git a/src/main/java/org/cmh/backend/MeetingManagement/service/MeetingService.java b/src/main/java/org/cmh/backend/MeetingManagement/service/MeetingService.java
new file mode 100644
index 0000000..b9de395
--- /dev/null
+++ b/src/main/java/org/cmh/backend/MeetingManagement/service/MeetingService.java
@@ -0,0 +1,74 @@
+package org.cmh.backend.MeetingManagement.service;
+
+import org.cmh.backend.MeetingManagement.model.Meeting;
+import org.cmh.backend.MeetingManagement.repository.MeetingRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class MeetingService {
+ @Autowired
+ private MeetingRepository meetingRepository;
+
+ public List getAllMeetings() {
+ return meetingRepository.findAll();
+ }
+
+ public Optional getMeetingById(Long id) {
+ return meetingRepository.findById(id);
+ }
+
+ public Meeting createMeeting(Meeting meeting) {
+ validateMeeting(meeting);
+ return meetingRepository.save(meeting);
+ }
+
+ public Meeting updateMeeting(Long id, Meeting meetingDetails) {
+ validateMeeting(meetingDetails);
+ Meeting meeting = meetingRepository.findById(id)
+ .orElseThrow(() -> new RuntimeException("Meeting not found with id " + id));
+ meeting.setName(meetingDetails.getName());
+ meeting.setOrganizer(meetingDetails.getOrganizer());
+ meeting.setStartTime(meetingDetails.getStartTime());
+ meeting.setEndTime(meetingDetails.getEndTime());
+ meeting.setContent(meetingDetails.getContent());
+ meeting.setStatus(meetingDetails.getStatus());
+ return meetingRepository.save(meeting);
+ }
+
+ public void deleteMeeting(Long id) {
+ Meeting meeting = meetingRepository.findById(id)
+ .orElseThrow(() -> new RuntimeException("Meeting not found with id " + id));
+ meetingRepository.delete(meeting);
+ }
+
+ private void validateMeeting(Meeting meeting) {
+ if (meeting.getName() == null || meeting.getName().isEmpty()) {
+ throw new RuntimeException("会议名称不能为空");
+ }
+ if (meeting.getOrganizer() == null || meeting.getOrganizer().isEmpty()) {
+ throw new RuntimeException("组织者不能为空");
+ }
+ if (meeting.getStartTime() == null) {
+ throw new RuntimeException("开始时间不能为空");
+ }
+ if (meeting.getEndTime() == null) {
+ throw new RuntimeException("结束时间不能为空");
+ }
+ if (meeting.getStatus() == null || meeting.getStatus().isEmpty()) {
+ throw new RuntimeException("状态不能为空");
+ }
+ }
+
+
+ public List searchMeetings(String name, String organizer, LocalDateTime startTime) {
+ // 根据条件搜索会议
+ return meetingRepository.searchMeetings(name, organizer, startTime);
+ }
+ }
+
+
diff --git a/src/main/java/org/cmh/backend/NewsManagement/controller/FileController.java b/src/main/java/org/cmh/backend/NewsManagement/controller/NewsFileController.java
similarity index 92%
rename from src/main/java/org/cmh/backend/NewsManagement/controller/FileController.java
rename to src/main/java/org/cmh/backend/NewsManagement/controller/NewsFileController.java
index b48660a..16eb41d 100644
--- a/src/main/java/org/cmh/backend/NewsManagement/controller/FileController.java
+++ b/src/main/java/org/cmh/backend/NewsManagement/controller/NewsFileController.java
@@ -15,12 +15,12 @@ import java.nio.file.Path;
import java.nio.file.Paths;
@RestController
-@CrossOrigin // 如果前端和后端不在同一个域名或端口下,需要启用跨域
-public class FileController {
+@RequestMapping("/news")
+public class NewsFileController {
private static final String UPLOAD_DIR = "uploads/";
- @PostMapping("/news/uploadPic")
+ @PostMapping("/uploadPic")
public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return new ResponseEntity<>(new UploadFileResponse("文件不能为空", null), HttpStatus.BAD_REQUEST);
@@ -45,7 +45,7 @@ public class FileController {
}
}
- @GetMapping("/news/files/{filename}")
+ @GetMapping("/files/{filename}")
public ResponseEntity getFile(@PathVariable String filename) {
try {
Path filePath = Paths.get(UPLOAD_DIR).resolve(filename).normalize();
diff --git a/src/main/java/org/cmh/backend/authentication/dto/ProfileResponse.java b/src/main/java/org/cmh/backend/authentication/dto/ProfileResponse.java
new file mode 100644
index 0000000..d60fed8
--- /dev/null
+++ b/src/main/java/org/cmh/backend/authentication/dto/ProfileResponse.java
@@ -0,0 +1,19 @@
+package org.cmh.backend.authentication.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class ProfileResponse {
+ private String username;
+ private String email;
+ private String role;
+ private String phoneNumber;
+ private String company;
+ private LocalDateTime createdDate;
+}
diff --git a/src/main/java/org/cmh/backend/authentication/dto/UpdateRequest.java b/src/main/java/org/cmh/backend/authentication/dto/UpdateRequest.java
new file mode 100644
index 0000000..9ba3ea3
--- /dev/null
+++ b/src/main/java/org/cmh/backend/authentication/dto/UpdateRequest.java
@@ -0,0 +1,15 @@
+package org.cmh.backend.authentication.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class UpdateRequest {
+ private String username;
+ private String email;
+ private String phoneNumber;
+ private String company;
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 2a38a12..3cd6354 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -23,7 +23,8 @@ server.servlet.encoding.charset=utf-8
# verificationCode
verification.code.images.path=src/main/resources/static/verificationCodeImages
# set the max size of a single file
-spring.servlet.multipart.max-file-size=50MB
+spring.servlet.multipart.max-file-size=500MB
# set the max size of the total request
-spring.servlet.multipart.max-request-size=50MB
+spring.servlet.multipart.max-request-size=500MB
+
diff --git a/src/test/java/org/cmh/backend/BackendApplicationTests.java b/src/test/java/org/cmh/backend/BackendApplicationTests.java
deleted file mode 100644
index 8bc26ca..0000000
--- a/src/test/java/org/cmh/backend/BackendApplicationTests.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.cmh.backend;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.context.annotation.Import;
-
-@Import(TestcontainersConfiguration.class)
-@SpringBootTest
-class BackendApplicationTests {
-
- @Test
- void contextLoads() {
- }
-
-}
diff --git a/src/test/java/org/cmh/backend/TestBackendApplication.java b/src/test/java/org/cmh/backend/TestBackendApplication.java
deleted file mode 100644
index a752147..0000000
--- a/src/test/java/org/cmh/backend/TestBackendApplication.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.cmh.backend;
-
-import org.springframework.boot.SpringApplication;
-
-public class TestBackendApplication {
-
- public static void main(String[] args) {
- SpringApplication.from(BackendApplication::main).with(TestcontainersConfiguration.class).run(args);
- }
-
-}
diff --git a/src/test/java/org/cmh/backend/TestcontainersConfiguration.java b/src/test/java/org/cmh/backend/TestcontainersConfiguration.java
deleted file mode 100644
index 27f9122..0000000
--- a/src/test/java/org/cmh/backend/TestcontainersConfiguration.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.cmh.backend;
-
-import org.springframework.boot.test.context.TestConfiguration;
-import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
-import org.springframework.context.annotation.Bean;
-import org.testcontainers.containers.MariaDBContainer;
-import org.testcontainers.containers.MySQLContainer;
-import org.testcontainers.utility.DockerImageName;
-
-@TestConfiguration(proxyBeanMethods = false)
-class TestcontainersConfiguration {
-
- @Bean
- @ServiceConnection
- MariaDBContainer> mariaDbContainer() {
- return new MariaDBContainer<>(DockerImageName.parse("mariadb:latest"));
- }
-
- @Bean
- @ServiceConnection
- MySQLContainer> mysqlContainer() {
- return new MySQLContainer<>(DockerImageName.parse("mysql:latest"));
- }
-
-}
diff --git a/src/test/java/org/cmh/backend/Utils/JwtVerifyAspectTest.java b/src/test/java/org/cmh/backend/Utils/JwtVerifyAspectTest.java
deleted file mode 100644
index 22b12e1..0000000
--- a/src/test/java/org/cmh/backend/Utils/JwtVerifyAspectTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.cmh.backend.Utils;
-
-import org.cmh.backend.authentication.service.UserService;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mockito;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.EnableAspectJAutoProxy;
-import org.springframework.context.annotation.Import;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@RunWith(SpringRunner.class)
-public class JwtVerifyAspectTest {
-
- @Configuration
- @EnableAspectJAutoProxy
- @Import({JwtVerifyAspect.class})
- static class Config {
- @Bean
- public JwtUtil jwtUtil() {
- return Mockito.mock(JwtUtil.class);
- }
-
- @Bean
- public UserService userService() {
- return Mockito.mock(UserService.class);
- }
- }
-
- private JwtUtil jwtUtil = new JwtUtil();
-
- @InjectMocks
- private JwtVerifyAspect jwtVerifyAspect;
-
- @BeforeClass
- public static void setUpClass() {
- // Static setup if needed
- }
-
- @Before
- public void setUp() {
- Mockito.when(jwtUtil.isTokenValid("validToken")).thenReturn(true);
- Mockito.when(jwtUtil.isTokenValid("invalidToken")).thenReturn(false);
- }
-
- // TODO:这个测试跑不动,有问题,先取消掉
-// @Test
-// public void testVerify() {
-// SomeController validTokenController = new SomeController("validToken");
-// SomeController invalidTokenController = new SomeController("invalidToken");
-//
-// Assert.assertTrue("Valid token should pass verification", validTokenController.run());
-// Assert.assertFalse("Invalid token should fail verification", invalidTokenController.run());
-// }
-}
-
-class SomeController {
- private SomeJwtRequest request;
-
- SomeController(String token) {
- this.request = new SomeJwtRequest(token, "test");
- }
-
- public boolean run() {
- try {
- return verify(request);
- } catch (JwtValidationException e) {
- return false;
- }
- }
-
- @JwtVerify
- public boolean verify(SomeJwtRequest request) {
- return true;
- }
-}
-
-class SomeJwtRequest extends JwtRequest {
- String msg;
-
- public SomeJwtRequest(String token, String msg) {
- super.setToken(token);
- this.msg = msg;
- }
-}
\ No newline at end of file