ChenSiTong 6 лет назад
Родитель
Сommit
e953a27d0f
40 измененных файлов с 710 добавлено и 159 удалено
  1. 20 21
      pom.xml
  2. 1 1
      src/main/java/nju/seec/helper/aspect/auth/AuthAspect.java
  3. 39 39
      src/main/java/nju/seec/helper/config/Swagger2Config.java
  4. 15 0
      src/main/java/nju/seec/helper/config/properties/MailProperties.java
  5. 2 2
      src/main/java/nju/seec/helper/config/properties/OssProperties.java
  6. 0 8
      src/main/java/nju/seec/helper/constant/Consts.java
  7. 11 6
      src/main/java/nju/seec/helper/controller/CodeController.java
  8. 70 0
      src/main/java/nju/seec/helper/controller/CommentController.java
  9. 4 1
      src/main/java/nju/seec/helper/controller/ControllerAdvice.java
  10. 17 20
      src/main/java/nju/seec/helper/controller/CourseController.java
  11. 2 1
      src/main/java/nju/seec/helper/controller/SlideController.java
  12. 4 3
      src/main/java/nju/seec/helper/controller/UserController.java
  13. 63 0
      src/main/java/nju/seec/helper/dao/CommentDAO.java
  14. 23 0
      src/main/java/nju/seec/helper/dao/PageDAO.java
  15. 17 0
      src/main/java/nju/seec/helper/dto/CommentDTO.java
  16. 9 3
      src/main/java/nju/seec/helper/dto/RegisterDTO.java
  17. 17 0
      src/main/java/nju/seec/helper/dto/ReplyDTO.java
  18. 18 0
      src/main/java/nju/seec/helper/dto/TopCommentDTO.java
  19. 42 0
      src/main/java/nju/seec/helper/entity/Comment.java
  20. 1 1
      src/main/java/nju/seec/helper/entity/Course.java
  21. 3 3
      src/main/java/nju/seec/helper/entity/Page.java
  22. 35 0
      src/main/java/nju/seec/helper/entity/Reply.java
  23. 2 1
      src/main/java/nju/seec/helper/entity/Slide.java
  24. 1 1
      src/main/java/nju/seec/helper/entity/User.java
  25. 56 0
      src/main/java/nju/seec/helper/service/CommentService.java
  26. 3 4
      src/main/java/nju/seec/helper/service/CourseService.java
  27. 5 15
      src/main/java/nju/seec/helper/service/impl/CodeServiceImpl.java
  28. 99 0
      src/main/java/nju/seec/helper/service/impl/CommentServiceImpl.java
  29. 2 2
      src/main/java/nju/seec/helper/service/impl/CourseServiceImpl.java
  30. 2 8
      src/main/java/nju/seec/helper/service/impl/SlideServiceImpl.java
  31. 10 0
      src/main/java/nju/seec/helper/util/Consts.java
  32. 30 0
      src/main/java/nju/seec/helper/util/MailUtils.java
  33. 1 1
      src/main/java/nju/seec/helper/util/OssUtils.java
  34. 1 1
      src/main/java/nju/seec/helper/util/exception/HelperException.java
  35. 30 0
      src/main/java/nju/seec/helper/vo/CommentVO.java
  36. 4 1
      src/main/java/nju/seec/helper/vo/CourseVO.java
  37. 23 0
      src/main/java/nju/seec/helper/vo/ReplyVO.java
  38. 3 2
      src/main/java/nju/seec/helper/vo/SlideVO.java
  39. 2 1
      src/main/java/nju/seec/helper/vo/UserVO.java
  40. 23 13
      src/main/resources/application-dev.yml

+ 20 - 21
pom.xml

@@ -52,12 +52,11 @@
             <artifactId>aliyun-sdk-oss</artifactId>
             <version>3.8.1</version>
         </dependency>
-
-        <!--        <dependency>-->
-        <!--            <groupId>com.h2database</groupId>-->
-        <!--            <artifactId>h2</artifactId>-->
-        <!--            <scope>runtime</scope>-->
-        <!--        </dependency>-->
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>28.1-jre</version>
+        </dependency>
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
@@ -85,24 +84,24 @@
             </exclusions>
         </dependency>
 
-<!--        <dependency>-->
-<!--            <groupId>io.springfox</groupId>-->
-<!--            <artifactId>springfox-swagger2</artifactId>-->
-<!--            <version>${swagger.version}</version>-->
-<!--        </dependency>-->
-<!--        <dependency>-->
-<!--            <groupId>io.springfox</groupId>-->
-<!--            <artifactId>springfox-swagger-ui</artifactId>-->
-<!--            <version>${swagger.version}</version>-->
-<!--        </dependency>-->
+        <!--        <dependency>-->
+        <!--            <groupId>io.springfox</groupId>-->
+        <!--            <artifactId>springfox-swagger2</artifactId>-->
+        <!--            <version>${swagger.version}</version>-->
+        <!--        </dependency>-->
+        <!--        <dependency>-->
+        <!--            <groupId>io.springfox</groupId>-->
+        <!--            <artifactId>springfox-swagger-ui</artifactId>-->
+        <!--            <version>${swagger.version}</version>-->
+        <!--        </dependency>-->
 
         <!-- 开发阶段用于假数据生成 -->
         <!-- https://mvnrepository.com/artifact/com.github.javafaker/javafaker -->
-        <dependency>
-            <groupId>com.github.javafaker</groupId>
-            <artifactId>javafaker</artifactId>
-            <version>1.0.1</version>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>com.github.javafaker</groupId>-->
+<!--            <artifactId>javafaker</artifactId>-->
+<!--            <version>1.0.1</version>-->
+<!--        </dependency>-->
     </dependencies>
 
     <build>

+ 1 - 1
src/main/java/nju/seec/helper/aspect/auth/AuthAspect.java

@@ -1,6 +1,6 @@
 package nju.seec.helper.aspect.auth;
 
-import nju.seec.helper.constant.Consts;
+import nju.seec.helper.util.Consts;
 import nju.seec.helper.dto.LoginUser;
 import nju.seec.helper.util.exception.HelperException;
 import org.aspectj.lang.JoinPoint;

+ 39 - 39
src/main/java/nju/seec/helper/config/Swagger2Config.java

@@ -1,39 +1,39 @@
-package nju.seec.helper.config;
-
-import io.swagger.annotations.Api;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.service.Contact;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
-
-/**
- * @author cst
- */
-@Configuration
-@EnableSwagger2
-public class Swagger2Config {
-    @Bean
-    public Docket createDocket() {
-        return new Docket(DocumentationType.SWAGGER_2)
-                .apiInfo(apiInfo())
-                .select()
-                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
-                .paths(PathSelectors.any())
-                .build();
-    }
-
-    private ApiInfo apiInfo() {
-        return new ApiInfoBuilder()
-                .title("SEEC-Helper后端API文档")
-                .contact(new Contact("ChenSiTong", "", "chen_st@foxmail.com"))
-                .description("")
-                .version("1.0")
-                .build();
-    }
-}
+//package nju.seec.helper.config;
+//
+//import io.swagger.annotations.Api;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import springfox.documentation.builders.ApiInfoBuilder;
+//import springfox.documentation.builders.PathSelectors;
+//import springfox.documentation.builders.RequestHandlerSelectors;
+//import springfox.documentation.service.ApiInfo;
+//import springfox.documentation.service.Contact;
+//import springfox.documentation.spi.DocumentationType;
+//import springfox.documentation.spring.web.plugins.Docket;
+//import springfox.documentation.swagger2.annotations.EnableSwagger2;
+//
+///**
+// * @author cst
+// */
+//@Configuration
+//@EnableSwagger2
+//public class Swagger2Config {
+//    @Bean
+//    public Docket createDocket() {
+//        return new Docket(DocumentationType.SWAGGER_2)
+//                .apiInfo(apiInfo())
+//                .select()
+//                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
+//                .paths(PathSelectors.any())
+//                .build();
+//    }
+//
+//    private ApiInfo apiInfo() {
+//        return new ApiInfoBuilder()
+//                .title("SEEC-Helper后端API文档")
+//                .contact(new Contact("ChenSiTong", "", "chen_st@foxmail.com"))
+//                .description("")
+//                .version("1.0")
+//                .build();
+//    }
+//}

+ 15 - 0
src/main/java/nju/seec/helper/config/properties/MailProperties.java

@@ -0,0 +1,15 @@
+package nju.seec.helper.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author cst
+ */
+@Data
+@Component
+@ConfigurationProperties("helper.mail")
+public class MailProperties {
+    private String from;
+}

+ 2 - 2
src/main/java/nju/seec/helper/constant/OssProperties.java → src/main/java/nju/seec/helper/config/properties/OssProperties.java

@@ -1,4 +1,4 @@
-package nju.seec.helper.constant;
+package nju.seec.helper.config.properties;
 
 import lombok.Data;
 import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -9,7 +9,7 @@ import org.springframework.stereotype.Component;
  */
 @Data
 @Component
-@ConfigurationProperties(prefix = "aliyun.oss")
+@ConfigurationProperties("aliyun.oss")
 public class OssProperties {
     private String endpoint;
     private String accessKeyId;

+ 0 - 8
src/main/java/nju/seec/helper/constant/Consts.java

@@ -1,8 +0,0 @@
-package nju.seec.helper.constant;
-
-/**
- * @author cst
- */
-public class Consts {
-    public static final String SESSION_USER_NAME = "helper_user";
-}

+ 11 - 6
src/main/java/nju/seec/helper/controller/CodeController.java

@@ -1,19 +1,18 @@
 package nju.seec.helper.controller;
 
-import io.swagger.annotations.Api;
+import nju.seec.helper.util.Consts;
 import nju.seec.helper.controller.response.EmptyResponse;
 import nju.seec.helper.service.CodeService;
+import nju.seec.helper.util.exception.HelperException;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import javax.validation.constraints.Email;
-import javax.validation.constraints.NotBlank;
+import java.util.regex.Pattern;
 
 /**
  * @author cst
  */
-@Api(tags = "验证码")
 @RestController
 @RequestMapping("/api/code")
 public class CodeController {
@@ -24,13 +23,19 @@ public class CodeController {
     }
 
     @PostMapping("/email")
-    public EmptyResponse sendEmailCode(@Email String email) {
+    public EmptyResponse sendEmailCode(String email) {
+        if (!Pattern.matches(Consts.SCHOOL_EMAIL_REGEX, email)) {
+            throw HelperException.of(HelperException.ExceptionType.PARAM_ERROR, "该邮箱不是南大校邮");
+        }
         codeService.sendEmailCode(email);
         return EmptyResponse.getInstance();
     }
 
     @PostMapping("/phone")
-    public EmptyResponse sendPhoneCode(@NotBlank String phone) {
+    public EmptyResponse sendPhoneCode(String phone) {
+        if (!Pattern.matches(Consts.PHONE_REGEX, phone)) {
+            throw HelperException.of(HelperException.ExceptionType.PARAM_ERROR, "手机号格式错误");
+        }
         codeService.sendPhoneCode(phone);
         return EmptyResponse.getInstance();
     }

+ 70 - 0
src/main/java/nju/seec/helper/controller/CommentController.java

@@ -0,0 +1,70 @@
+package nju.seec.helper.controller;
+
+import nju.seec.helper.aspect.auth.Auth;
+import nju.seec.helper.controller.response.EmptyResponse;
+import nju.seec.helper.controller.response.PageResourceResponse;
+import nju.seec.helper.controller.response.ResourceResponse;
+import nju.seec.helper.dto.CommentDTO;
+import nju.seec.helper.dto.LoginUser;
+import nju.seec.helper.dto.ReplyDTO;
+import nju.seec.helper.service.CommentService;
+import nju.seec.helper.util.enums.UserType;
+import nju.seec.helper.vo.CommentVO;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.web.PageableDefault;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * @author cst
+ */
+@RestController
+@RequestMapping("/api/comment")
+public class CommentController {
+    private final CommentService commentService;
+
+    public CommentController(CommentService commentService) {
+        this.commentService = commentService;
+    }
+
+    @Auth(roles = {UserType.TEACHER, UserType.STUDENT}, message = "发表评论")
+    @PostMapping
+    public ResourceResponse<CommentVO> createComment(LoginUser user,
+                                                     @Valid @RequestBody CommentDTO commentDTO) {
+        CommentVO commentVO = commentService.createComment(user, commentDTO);
+        return ResourceResponse.of(commentVO);
+    }
+
+    @Auth(roles = UserType.TEACHER, message = "回复评论")
+    @PostMapping("/reply")
+    public EmptyResponse replyComment(LoginUser user,
+                                      @Valid @RequestBody ReplyDTO replyDTO) {
+        commentService.replyComment(user, replyDTO);
+        return EmptyResponse.getInstance();
+    }
+
+    @Auth(roles = {UserType.TEACHER, UserType.STUDENT}, message = "删除评论")
+    @DeleteMapping("/{commentId}")
+    public EmptyResponse removeComment(LoginUser user,
+                                       @PathVariable Integer commentId) {
+        commentService.removeComment(user, commentId);
+        return EmptyResponse.getInstance();
+    }
+
+    @Auth(roles = UserType.TEACHER, message = "置顶评论")
+    @PostMapping("/{commentId}/top")
+    public EmptyResponse topComments(LoginUser user,
+                                     @PathVariable Integer commentId) {
+        commentService.topComment(user, commentId);
+        return EmptyResponse.getInstance();
+    }
+
+    @GetMapping("/page/{pageId}")
+    public PageResourceResponse<CommentVO> getComments(@PathVariable Integer pageId,
+                                                       @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
+        List<CommentVO> commentVOList = commentService.getCommentsByType(pageId, pageable);
+        return PageResourceResponse.of(commentVOList, pageable.getPageNumber(), pageable.getPageSize());
+    }
+}

+ 4 - 1
src/main/java/nju/seec/helper/controller/ControllerAdvice.java

@@ -1,5 +1,6 @@
 package nju.seec.helper.controller;
 
+import lombok.extern.slf4j.Slf4j;
 import nju.seec.helper.controller.response.ErrorResponse;
 import nju.seec.helper.util.exception.HelperException;
 import org.springframework.web.bind.MethodArgumentNotValidException;
@@ -9,11 +10,12 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
 /**
  * @author cst
  */
+@Slf4j
 @RestControllerAdvice
 public class ControllerAdvice {
     @ExceptionHandler(MethodArgumentNotValidException.class)
     public ErrorResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
-        return ErrorResponse.of(400, ex.getLocalizedMessage());
+        return ErrorResponse.of(400, ex.getBindingResult().toString());
     }
 
     @ExceptionHandler(HelperException.class)
@@ -23,6 +25,7 @@ public class ControllerAdvice {
 
     @ExceptionHandler(Exception.class)
     public ErrorResponse handleException(Exception e) {
+        log.error(e.getLocalizedMessage());
         return ErrorResponse.of(500, e.getLocalizedMessage());
     }
 }

+ 17 - 20
src/main/java/nju/seec/helper/controller/CourseController.java

@@ -9,12 +9,12 @@ import nju.seec.helper.dto.CourseDTO;
 import nju.seec.helper.dto.LoginUser;
 import nju.seec.helper.service.CourseService;
 import nju.seec.helper.util.enums.UserType;
-import nju.seec.helper.util.exception.HelperException;
 import nju.seec.helper.vo.CourseVO;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.web.PageableDefault;
 import org.springframework.web.bind.annotation.*;
 
+import javax.validation.Valid;
 import java.util.List;
 
 /**
@@ -32,7 +32,7 @@ public class CourseController {
     @Auth(roles = UserType.TEACHER, message = "创建课程")
     @PostMapping
     public ResourceResponse<CourseVO> createCourse(LoginUser user,
-                                                   @RequestBody CourseDTO courseDTO) {
+                                                   @Valid @RequestBody CourseDTO courseDTO) {
         CourseVO courseVO = courseService.createCourse(user, courseDTO);
         return ResourceResponse.of(courseVO);
     }
@@ -40,36 +40,33 @@ public class CourseController {
     @Auth(roles = UserType.STUDENT, message = "选课")
     @PostMapping("/choose")
     public EmptyResponse chooseCourse(LoginUser user,
-                                      @RequestBody ChooseDTO chooseDTO) {
+                                      @Valid @RequestBody ChooseDTO chooseDTO) {
         courseService.chooseCourse(user, chooseDTO);
         return EmptyResponse.getInstance();
     }
 
-    @Auth(roles = {UserType.TEACHER, UserType.STUDENT}, message = "查看课程")
     @GetMapping
+    public PageResourceResponse<CourseVO> getCourses(@RequestParam(required = false, defaultValue = "") String key,
+                                                     @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
+        List<CourseVO> courseVOList = courseService.getCourses(key, pageable);
+        return PageResourceResponse.of(courseVOList, pageable.getPageNumber(), pageable.getPageSize());
+    }
+
+    @Auth(roles = UserType.TEACHER, message = "获取所创课程")
+    @GetMapping("/teacher")
     public PageResourceResponse<CourseVO> teacherGetCourses(LoginUser user,
                                                             @RequestParam(required = false, defaultValue = "") String key,
                                                             @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
-        List<CourseVO> courseVOList;
-        switch (user.getType()) {
-            case TEACHER:
-                courseVOList = courseService.teacherGetCourses(user, key, pageable);
-                break;
-            case STUDENT:
-                courseVOList = courseService.studentGetCourses(user, key, pageable);
-                break;
-            default:
-                throw HelperException.of(HelperException.ExceptionType.FORBIDDEN, "您暂时无法查看课程");
-        }
+        List<CourseVO> courseVOList = courseService.teacherGetCourses(user, key, pageable);
         return PageResourceResponse.of(courseVOList, pageable.getPageNumber(), pageable.getPageSize());
     }
 
     @Auth(roles = UserType.STUDENT, message = "获取所选课程")
-    @GetMapping("/choose")
-    public PageResourceResponse<CourseVO> studentGetChooseCourses(LoginUser user,
-                                                                  @RequestParam(required = false, defaultValue = "") String key,
-                                                                  @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
-        List<CourseVO> courseVOList = courseService.studentGetChooseCourses(user, key, pageable);
+    @GetMapping("/student")
+    public PageResourceResponse<CourseVO> studentGetCourses(LoginUser user,
+                                                            @RequestParam(required = false, defaultValue = "") String key,
+                                                            @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
+        List<CourseVO> courseVOList = courseService.studentGetCourses(user, key, pageable);
         return PageResourceResponse.of(courseVOList, pageable.getPageNumber(), pageable.getPageSize());
     }
 }

+ 2 - 1
src/main/java/nju/seec/helper/controller/SlideController.java

@@ -12,6 +12,7 @@ import org.springframework.data.domain.Pageable;
 import org.springframework.data.web.PageableDefault;
 import org.springframework.web.bind.annotation.*;
 
+import javax.validation.Valid;
 import java.util.List;
 
 /**
@@ -29,7 +30,7 @@ public class SlideController {
     @Auth(roles = UserType.TEACHER, message = "创建幻灯片")
     @PostMapping
     public ResourceResponse<SlideVO> createSlide(LoginUser user,
-                                                 SlideDTO slideDTO) {
+                                                 @Valid SlideDTO slideDTO) {
         SlideVO slideVO = slideService.createSlide(user, slideDTO);
         return ResourceResponse.of(slideVO);
     }

+ 4 - 3
src/main/java/nju/seec/helper/controller/UserController.java

@@ -1,7 +1,7 @@
 package nju.seec.helper.controller;
 
 import nju.seec.helper.aspect.auth.Auth;
-import nju.seec.helper.constant.Consts;
+import nju.seec.helper.util.Consts;
 import nju.seec.helper.controller.response.ResourceResponse;
 import nju.seec.helper.dto.LoginDTO;
 import nju.seec.helper.dto.LoginUser;
@@ -12,6 +12,7 @@ import nju.seec.helper.vo.UserVO;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpSession;
+import javax.validation.Valid;
 
 /**
  * @author cst
@@ -26,13 +27,13 @@ public class UserController {
     }
 
     @PostMapping("/register")
-    public ResourceResponse<UserVO> register(@RequestBody RegisterDTO registerDTO) {
+    public ResourceResponse<UserVO> register(@Valid @RequestBody RegisterDTO registerDTO) {
         UserVO userVO = userService.createUser(registerDTO);
         return ResourceResponse.of(userVO);
     }
 
     @PostMapping("/login/email")
-    public ResourceResponse<UserVO> emailLogin(@RequestBody LoginDTO loginDTO,
+    public ResourceResponse<UserVO> emailLogin(@Valid @RequestBody LoginDTO loginDTO,
                                                HttpSession session) {
         UserVO userVO = userService.getUserByEmailAndPassword(loginDTO.getUsername(), loginDTO.getPassword());
         LoginUser user = new LoginUser();

+ 63 - 0
src/main/java/nju/seec/helper/dao/CommentDAO.java

@@ -0,0 +1,63 @@
+package nju.seec.helper.dao;
+
+import nju.seec.helper.entity.Comment;
+import nju.seec.helper.util.exception.HelperException;
+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.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author cst
+ */
+@Repository
+public interface CommentDAO extends JpaRepository<Comment, Integer> {
+    /**
+     * 封装findById
+     *
+     * @param id
+     * @return
+     */
+    default Comment findCommentById(Integer id) {
+        return this.findById(id)
+                .orElseThrow(() -> HelperException.of(HelperException.ExceptionType.NOT_FOUND, "找不到评论"));
+    }
+
+    /**
+     * 查询置顶评论数量
+     *
+     * @param pageId
+     * @return
+     */
+    @Query("select max(c.topNumber) from Comment c " +
+            "where c.pageId=?1 " +
+            "and c.topNumber is not null")
+    Integer countTopComments(Integer pageId);
+
+    /**
+     * 获取评论
+     *
+     * @param pageId
+     * @param pageable
+     * @return
+     */
+    @Query("select c from Comment c " +
+            "where c.pageId=?1 " +
+            "order by nullif(c.topNumber, 0) desc")
+    Page<Comment> findComments(Integer pageId, Pageable pageable);
+
+    /**
+     * 调整置顶评论顺序
+     *
+     * @param pageId
+     */
+    @Modifying
+    @Transactional(rollbackFor = Exception.class)
+    @Query("update Comment c " +
+            "set c.topNumber=null " +
+            "where c.pageId=?1")
+    void cleanTopComments(Integer pageId);
+}

+ 23 - 0
src/main/java/nju/seec/helper/dao/PageDAO.java

@@ -0,0 +1,23 @@
+package nju.seec.helper.dao;
+
+import nju.seec.helper.entity.Page;
+import nju.seec.helper.util.exception.HelperException;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+/**
+ * @author cst
+ */
+@Repository
+public interface PageDAO extends JpaRepository<Page, Integer> {
+    /**
+     * 封装findById
+     *
+     * @param id
+     * @return
+     */
+    default Page findPageById(Integer id) {
+        return this.findById(id)
+                .orElseThrow(() -> HelperException.of(HelperException.ExceptionType.NOT_FOUND, "找不到页面"));
+    }
+}

+ 17 - 0
src/main/java/nju/seec/helper/dto/CommentDTO.java

@@ -0,0 +1,17 @@
+package nju.seec.helper.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author cst
+ */
+@Data
+public class CommentDTO {
+    @NotNull
+    private Integer pageId;
+    @NotBlank
+    private String content;
+}

+ 9 - 3
src/main/java/nju/seec/helper/dto/RegisterDTO.java

@@ -1,10 +1,13 @@
 package nju.seec.helper.dto;
 
 import lombok.Data;
+import nju.seec.helper.util.Consts;
+import org.hibernate.validator.constraints.Length;
 
 import javax.validation.constraints.Email;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
 
 /**
  * @author cst
@@ -12,16 +15,19 @@ import javax.validation.constraints.NotNull;
 @Data
 public class RegisterDTO {
     @NotBlank(message = "姓名不能为空")
+    @Length(min = 2)
     private String name;
-    @Email(message = "邮箱格式不正确")
+    @Email(message = "邮箱格式错误")
+    @Pattern(regexp = Consts.SCHOOL_EMAIL_REGEX, message = "该邮箱不是南大校邮")
     private String email;
-    @NotBlank
+    @NotBlank(message = "验证码不能为空")
     private String emailCode;
     @NotBlank
+    @Pattern(regexp = Consts.PHONE_REGEX, message = "手机号格式错误")
     private String phone;
     @NotNull
     private String phoneCode;
 
-    @NotBlank
+    @NotBlank(message = "密码不能为空")
     private String password;
 }

+ 17 - 0
src/main/java/nju/seec/helper/dto/ReplyDTO.java

@@ -0,0 +1,17 @@
+package nju.seec.helper.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author cst
+ */
+@Data
+public class ReplyDTO {
+    @NotNull
+    private Integer commentId;
+    @NotBlank
+    private String content;
+}

+ 18 - 0
src/main/java/nju/seec/helper/dto/TopCommentDTO.java

@@ -0,0 +1,18 @@
+package nju.seec.helper.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * @author cst
+ */
+@Data
+public class TopCommentDTO {
+    @NotNull
+    private Integer pageId;
+    @NotEmpty
+    private List<Integer> commentIds;
+}

+ 42 - 0
src/main/java/nju/seec/helper/entity/Comment.java

@@ -0,0 +1,42 @@
+package nju.seec.helper.entity;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+import nju.seec.helper.util.enums.UserType;
+
+import javax.persistence.*;
+
+/**
+ * @author cst
+ */
+@Data
+@Accessors(chain = true)
+@Entity
+@Table(name = "comment")
+public class Comment {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+
+    @Column(name = "page_id", nullable = false)
+    private Integer pageId;
+
+    @Column(name = "top_number")
+    private Integer topNumber;
+
+    @Column(nullable = false)
+    private String content;
+
+    @Column(name = "user_id", nullable = false)
+    private Integer userId;
+
+    @Column(name = "user_name", nullable = false)
+    private String userName;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "user_type", nullable = false)
+    private UserType userType;
+
+    @OneToOne(mappedBy = "comment", cascade = CascadeType.ALL)
+    private Reply reply;
+}

+ 1 - 1
src/main/java/nju/seec/helper/entity/Course.java

@@ -40,6 +40,6 @@ public class Course {
     /**
      * 冗余信息,有利于课程搜索和信息展示
      */
-    @Column(name = "teacher_name")
+    @Column(name = "teacher_name", nullable = false)
     private String teacherName;
 }

+ 3 - 3
src/main/java/nju/seec/helper/entity/Page.java

@@ -15,9 +15,9 @@ public class Page {
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Integer id;
 
+    @Column(nullable = false)
     private Integer number;
 
-    @ManyToOne
-    @JoinColumn(name = "slide_id", nullable = false)
-    private Slide slide;
+    @Column(name = "teacher_id", nullable = false)
+    private Integer teacherId;
 }

+ 35 - 0
src/main/java/nju/seec/helper/entity/Reply.java

@@ -0,0 +1,35 @@
+package nju.seec.helper.entity;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+import org.hibernate.annotations.CreationTimestamp;
+
+import javax.persistence.*;
+import java.time.LocalDateTime;
+
+/**
+ * @author cst
+ */
+@Data
+@Accessors(chain = true)
+@Entity
+@Table(name = "reply")
+public class Reply {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+
+    @OneToOne
+    @JoinColumn(name = "comment_id")
+    private Comment comment;
+
+    @Column(name = "teacher_id", nullable = false)
+    private Integer teacherId;
+
+    @Column(nullable = false)
+    private String content;
+
+    @Column(name = "create_at", updatable = false)
+    @CreationTimestamp
+    private LocalDateTime createAt;
+}

+ 2 - 1
src/main/java/nju/seec/helper/entity/Slide.java

@@ -46,7 +46,8 @@ public class Slide {
     @UpdateTimestamp
     private LocalDateTime updateAt;
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "slide")
+    @OneToMany(cascade = CascadeType.ALL)
+    @JoinColumn(name = "slide_id")
     @OrderBy("number asc")
     private List<Page> pages;
 }

+ 1 - 1
src/main/java/nju/seec/helper/entity/User.java

@@ -25,7 +25,7 @@ public class User {
     private String email;
 
     @Enumerated(EnumType.STRING)
-    @Column(nullable = false)
+    @Column(nullable = false, updatable = false)
     private UserType type;
 
     @Column(nullable = false, unique = true)

+ 56 - 0
src/main/java/nju/seec/helper/service/CommentService.java

@@ -0,0 +1,56 @@
+package nju.seec.helper.service;
+
+import nju.seec.helper.dto.CommentDTO;
+import nju.seec.helper.dto.LoginUser;
+import nju.seec.helper.dto.ReplyDTO;
+import nju.seec.helper.vo.CommentVO;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+/**
+ * @author cst
+ */
+public interface CommentService {
+    /**
+     * 创建评论
+     *
+     * @param user
+     * @param commentDTO
+     * @return
+     */
+    CommentVO createComment(LoginUser user, CommentDTO commentDTO);
+
+    /**
+     * 删除评论
+     *
+     * @param user
+     * @param commentId
+     */
+    void removeComment(LoginUser user, Integer commentId);
+
+    /**
+     * 置顶评论
+     *
+     * @param user
+     * @param commentId
+     */
+    void topComment(LoginUser user, Integer commentId);
+
+    /**
+     * 根据类型获取评论
+     *
+     * @param pageId
+     * @param pageable
+     * @return
+     */
+    List<CommentVO> getCommentsByType(Integer pageId, Pageable pageable);
+
+    /**
+     * 回复评论
+     *
+     * @param user
+     * @param replyDTO
+     */
+    void replyComment(LoginUser user, ReplyDTO replyDTO);
+}

+ 3 - 4
src/main/java/nju/seec/helper/service/CourseService.java

@@ -40,14 +40,13 @@ public interface CourseService {
     List<CourseVO> teacherGetCourses(LoginUser teacher, String key, Pageable pageable);
 
     /**
-     * 学生获取所有课程
+     * 获取课程
      *
-     * @param student
      * @param key
      * @param pageable
      * @return
      */
-    List<CourseVO> studentGetCourses(LoginUser student, String key, Pageable pageable);
+    List<CourseVO> getCourses(String key, Pageable pageable);
 
     /**
      * 学生获取已选课程
@@ -57,5 +56,5 @@ public interface CourseService {
      * @param pageable
      * @return
      */
-    List<CourseVO> studentGetChooseCourses(LoginUser student, String key, Pageable pageable);
+    List<CourseVO> studentGetCourses(LoginUser student, String key, Pageable pageable);
 }

+ 5 - 15
src/main/java/nju/seec/helper/service/impl/CodeServiceImpl.java

@@ -1,10 +1,8 @@
 package nju.seec.helper.service.impl;
 
 import nju.seec.helper.service.CodeService;
+import nju.seec.helper.util.MailUtils;
 import nju.seec.helper.util.RedisUtils;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.mail.SimpleMailMessage;
-import org.springframework.mail.javamail.JavaMailSender;
 import org.springframework.stereotype.Service;
 
 import java.util.Random;
@@ -16,27 +14,19 @@ import java.util.concurrent.TimeUnit;
 @Service
 public class CodeServiceImpl implements CodeService {
     private static final int MAIL_CODE_LIVING_MINUTES = 5;
-    @Value("${spring.mail.username}")
-    private String from;
-
-    private final JavaMailSender mailSender;
 
+    private final MailUtils mailUtils;
     private final RedisUtils redisUtils;
 
-    public CodeServiceImpl(JavaMailSender mailSender, RedisUtils redisUtils) {
-        this.mailSender = mailSender;
+    public CodeServiceImpl(MailUtils mailUtils, RedisUtils redisUtils) {
+        this.mailUtils = mailUtils;
         this.redisUtils = redisUtils;
     }
 
     @Override
     public void sendEmailCode(String email) {
         String code = getSixBitsCode();
-        SimpleMailMessage mail = new SimpleMailMessage();
-        mail.setFrom(from);
-        mail.setTo(email);
-        mail.setSubject("【南京大学】");
-        mail.setText(String.format("您的验证码:%s,该验证码%d分钟内有效,请勿泄漏于他人!", code, MAIL_CODE_LIVING_MINUTES));
-        mailSender.send(mail);
+        mailUtils.sendSimpleMailMessage("【南京大学】", String.format("您的验证码:%s,该验证码%d分钟内有效,请勿泄漏于他人!", code, MAIL_CODE_LIVING_MINUTES), email);
         redisUtils.set(email, code, MAIL_CODE_LIVING_MINUTES, TimeUnit.MINUTES);
     }
 

+ 99 - 0
src/main/java/nju/seec/helper/service/impl/CommentServiceImpl.java

@@ -0,0 +1,99 @@
+package nju.seec.helper.service.impl;
+
+import nju.seec.helper.dao.CommentDAO;
+import nju.seec.helper.dao.PageDAO;
+import nju.seec.helper.dto.CommentDTO;
+import nju.seec.helper.dto.LoginUser;
+import nju.seec.helper.dto.ReplyDTO;
+import nju.seec.helper.entity.Comment;
+import nju.seec.helper.entity.Reply;
+import nju.seec.helper.service.CommentService;
+import nju.seec.helper.util.exception.HelperException;
+import nju.seec.helper.vo.CommentVO;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author cst
+ */
+@Service
+public class CommentServiceImpl implements CommentService {
+    private final CommentDAO commentDAO;
+    private final PageDAO pageDAO;
+
+    public CommentServiceImpl(CommentDAO commentDAO, PageDAO pageDAO) {
+        this.commentDAO = commentDAO;
+        this.pageDAO = pageDAO;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public CommentVO createComment(LoginUser user, CommentDTO commentDTO) {
+        Comment comment = new Comment();
+        comment.setPageId(commentDTO.getPageId())
+                .setUserId(user.getId())
+                .setUserName(user.getName())
+                .setUserType(user.getType())
+                .setContent(commentDTO.getContent());
+        comment = commentDAO.save(comment);
+        return new CommentVO(comment);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void removeComment(LoginUser user, Integer commentId) {
+        Comment comment = commentDAO.findCommentById(commentId);
+        if (!comment.getUserId().equals(user.getId())) {
+            throw HelperException.of(HelperException.ExceptionType.FORBIDDEN, "您无权删除该评论");
+        }
+        commentDAO.deleteById(commentId);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void topComment(LoginUser user, Integer commentId) {
+        Comment comment = commentDAO.findCommentById(commentId);
+        if (comment.getTopNumber() == null) {
+            if (!pageDAO.findPageById(comment.getPageId()).getTeacherId().equals(user.getId())) {
+                throw HelperException.of(HelperException.ExceptionType.FORBIDDEN, "您无权进行置顶操作");
+            }
+            Integer topCommentNum = commentDAO.countTopComments(comment.getPageId());
+            if (topCommentNum == null) {
+                topCommentNum = 0;
+            }
+            comment.setTopNumber(topCommentNum + 1);
+            commentDAO.save(comment);
+        }
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public List<CommentVO> getCommentsByType(Integer pageId, Pageable pageable) {
+        return commentDAO
+                .findComments(pageId, pageable)
+                .getContent()
+                .stream()
+                .map(CommentVO::new)
+                .collect(Collectors.toList());
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void replyComment(LoginUser user, ReplyDTO replyDTO) {
+        Comment comment = commentDAO.findCommentById(replyDTO.getCommentId());
+        if (!pageDAO.findPageById(comment.getPageId()).getTeacherId().equals(user.getId())) {
+            throw HelperException.of(HelperException.ExceptionType.FORBIDDEN, "您无权回复该评论");
+        }
+
+        Reply reply = new Reply();
+        reply.setComment(comment)
+                .setTeacherId(user.getId())
+                .setContent(replyDTO.getContent());
+        comment.setReply(reply);
+        commentDAO.save(comment);
+    }
+}

+ 2 - 2
src/main/java/nju/seec/helper/service/impl/CourseServiceImpl.java

@@ -80,7 +80,7 @@ public class CourseServiceImpl implements CourseService {
 
     @Transactional(readOnly = true)
     @Override
-    public List<CourseVO> studentGetCourses(LoginUser student, String key, Pageable pageable) {
+    public List<CourseVO> getCourses(String key, Pageable pageable) {
         return courseDAO
                 .findByNameContains(key, pageable)
                 .stream()
@@ -90,7 +90,7 @@ public class CourseServiceImpl implements CourseService {
 
     @Transactional(readOnly = true)
     @Override
-    public List<CourseVO> studentGetChooseCourses(LoginUser student, String key, Pageable pageable) {
+    public List<CourseVO> studentGetCourses(LoginUser student, String key, Pageable pageable) {
         return courseDAO
                 .findByIdInAndNameContains(
                         chooseDAO.findCourseIdsByStudentId(student.getId()),

+ 2 - 8
src/main/java/nju/seec/helper/service/impl/SlideServiceImpl.java

@@ -23,7 +23,6 @@ import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 import java.util.Objects;
-import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -38,10 +37,6 @@ public class SlideServiceImpl implements SlideService {
 
     private final OssUtils ossUtils;
 
-    private final static Set<String> SLIDE_FILE_TYPE_SET = ImmutableSet.of(
-            "application/pdf"
-    );
-
     public SlideServiceImpl(CourseDAO courseDAO, SlideDAO slideDAO, ChooseDAO chooseDAO, OssUtils ossUtils) {
         this.courseDAO = courseDAO;
         this.slideDAO = slideDAO;
@@ -77,12 +72,11 @@ public class SlideServiceImpl implements SlideService {
                 throw HelperException.of(HelperException.ExceptionType.FORBIDDEN, "不支持的文件类型");
         }
 
-        System.out.println(pageNum);
-
         slide.setPages(IntStream.rangeClosed(1, pageNum)
                 .mapToObj(number -> {
                     Page page = new Page();
-                    page.setSlide(slide);
+//                    page.setSlide(slide);
+                    page.setTeacherId(teacher.getId());
                     page.setNumber(number);
                     return page;
                 })

+ 10 - 0
src/main/java/nju/seec/helper/util/Consts.java

@@ -0,0 +1,10 @@
+package nju.seec.helper.util;
+
+/**
+ * @author cst
+ */
+public class Consts {
+    public static final String SESSION_USER_NAME = "helper_user";
+    public static final String SCHOOL_EMAIL_REGEX = ".+@(nju.edu.cn|smail.nju.edu.cn)";
+    public static final String PHONE_REGEX = "1[3|4|5|7|8]\\d{9}";
+}

+ 30 - 0
src/main/java/nju/seec/helper/util/MailUtils.java

@@ -0,0 +1,30 @@
+package nju.seec.helper.util;
+
+import nju.seec.helper.config.properties.MailProperties;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author cst
+ */
+@Component
+public class MailUtils {
+    private final MailProperties mailProperties;
+    private final JavaMailSender mailSender;
+
+    @SuppressWarnings("all")
+    public MailUtils(MailProperties mailProperties, JavaMailSender mailSender) {
+        this.mailProperties = mailProperties;
+        this.mailSender = mailSender;
+    }
+
+    public void sendSimpleMailMessage(String subject, String text, String... to) {
+        SimpleMailMessage message = new SimpleMailMessage();
+        message.setFrom(mailProperties.getFrom());
+        message.setTo(to);
+        message.setSubject(subject);
+        message.setText(text);
+        mailSender.send(message);
+    }
+}

+ 1 - 1
src/main/java/nju/seec/helper/util/OssUtils.java

@@ -3,7 +3,7 @@ package nju.seec.helper.util;
 import com.aliyun.oss.OSS;
 import com.aliyun.oss.OSSClientBuilder;
 import com.aliyun.oss.model.PutObjectRequest;
-import nju.seec.helper.constant.OssProperties;
+import nju.seec.helper.config.properties.OssProperties;
 import org.springframework.stereotype.Component;
 
 import java.io.InputStream;

+ 1 - 1
src/main/java/nju/seec/helper/util/exception/HelperException.java

@@ -15,7 +15,7 @@ public class HelperException extends RuntimeException {
     @Getter
     public enum ExceptionType {
         // http code
-        NOT_LOGIN(401), FORBIDDEN(403), NOT_FOUND(404), CONFLICT(409), ERROR(500);
+        PARAM_ERROR(400), NOT_LOGIN(401), FORBIDDEN(403), NOT_FOUND(404), CONFLICT(409), ERROR(500);
 
         private int code;
 

+ 30 - 0
src/main/java/nju/seec/helper/vo/CommentVO.java

@@ -0,0 +1,30 @@
+package nju.seec.helper.vo;
+
+import lombok.Data;
+import lombok.NonNull;
+import nju.seec.helper.entity.Comment;
+import nju.seec.helper.util.enums.UserType;
+
+/**
+ * @author cst
+ */
+@Data
+public class CommentVO {
+    private Integer id;
+    private Integer topNumber;
+    private String content;
+    private Integer userId;
+    private String userName;
+    private UserType userType;
+    private ReplyVO reply;
+
+    public CommentVO(@NonNull Comment comment) {
+        this.id = comment.getId();
+        this.topNumber = comment.getTopNumber();
+        this.content = comment.getContent();
+        this.userId = comment.getUserId();
+        this.userName = comment.getUserName();
+        this.userType = comment.getUserType();
+        this.reply = comment.getReply() != null ? new ReplyVO(comment.getReply()) : null;
+    }
+}

+ 4 - 1
src/main/java/nju/seec/helper/vo/CourseVO.java

@@ -1,6 +1,7 @@
 package nju.seec.helper.vo;
 
 import lombok.Data;
+import lombok.NonNull;
 import nju.seec.helper.entity.Course;
 
 /**
@@ -11,14 +12,16 @@ public class CourseVO {
     private Integer id;
     private String name;
     private String bio;
+    private String cover;
 
     private Integer teacherId;
     private String teacherName;
 
-    public CourseVO(Course course) {
+    public CourseVO(@NonNull Course course) {
         this.id = course.getId();
         this.name = course.getName();
         this.bio = course.getBio();
+        this.cover = course.getCover();
 
         this.teacherId = course.getTeacherId();
         this.teacherName = course.getTeacherName();

+ 23 - 0
src/main/java/nju/seec/helper/vo/ReplyVO.java

@@ -0,0 +1,23 @@
+package nju.seec.helper.vo;
+
+import lombok.Data;
+import lombok.NonNull;
+import nju.seec.helper.entity.Reply;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author cst
+ */
+@Data
+public class ReplyVO {
+    private Integer id;
+    private String content;
+    private LocalDateTime createAt;
+
+    public ReplyVO(@NonNull Reply reply) {
+        this.id = reply.getId();
+        this.content = reply.getContent();
+        this.createAt = reply.getCreateAt();
+    }
+}

+ 3 - 2
src/main/java/nju/seec/helper/vo/SlideVO.java

@@ -1,6 +1,7 @@
 package nju.seec.helper.vo;
 
 import lombok.Data;
+import lombok.NonNull;
 import nju.seec.helper.entity.Page;
 import nju.seec.helper.entity.Slide;
 import nju.seec.helper.util.enums.SlideState;
@@ -22,7 +23,7 @@ public class SlideVO {
     private LocalDateTime updateAt;
     private List<PageVO> pages;
 
-    public SlideVO(Slide slide) {
+    public SlideVO(@NonNull Slide slide) {
         this.id = slide.getId();
         this.courseId = slide.getCourseId();
         this.state = slide.getState();
@@ -41,7 +42,7 @@ public class SlideVO {
         private Integer id;
         private Integer number;
 
-        public PageVO(Page page) {
+        public PageVO(@NonNull Page page) {
             this.id = page.getId();
             this.number = page.getNumber();
         }

+ 2 - 1
src/main/java/nju/seec/helper/vo/UserVO.java

@@ -1,6 +1,7 @@
 package nju.seec.helper.vo;
 
 import lombok.Data;
+import lombok.NonNull;
 import nju.seec.helper.entity.User;
 import nju.seec.helper.util.enums.UserType;
 
@@ -15,7 +16,7 @@ public class UserVO {
     private String phone;
     private UserType type;
 
-    public UserVO(User user) {
+    public UserVO(@NonNull User user) {
         this.id = user.getId();
         this.name = user.getName();
         this.email = user.getEmail();

+ 23 - 13
src/main/resources/application-dev.yml

@@ -1,19 +1,15 @@
 spring:
+  datasource:
+    url: jdbc:mysql://localhost:3306/helper?setUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: 123456
   jpa:
     open-in-view: true
     hibernate:
       ddl-auto: update
     database: mysql
-    show-sql: true
-  datasource:
-    url: jdbc:mysql://localhost:3306/helper?setUnicode=true&characterEncoding=utf8
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    username: root
-    password: 123456
-  #  h2:
-  #    console:
-  #      enabled: true
-  #      path: /h2
+    database-platform: org.hibernate.dialect.MySQL8Dialect
   http:
     encoding:
       force: true
@@ -25,12 +21,26 @@ spring:
     host: smtp.qq.com
     username: chen_st@foxmail.com
     password: jgeiyvaojagnecjd
-    port: 465
-    protocol: smtps
+    properties:
+      mail:
+        smtp:
+          auth: true
+          starttls:
+            enable: true
+            required: true
+  servlet:
+    multipart:
+      max-file-size: 50MB
+      max-request-size: 100MB
 aliyun:
   oss:
     endpoint: oss-cn-hangzhou.aliyuncs.com
     access-key-id: LTAI4Fi1qmL4iuhH8t7G7r2H
     access-key-secret: 7tJWyQqa0cMkQGaPMMvtH6c0VLiOO2
     bucket-name: seec-helper-pdf
-    expiration-minutes: 10
+    expiration-minutes: 10
+
+# 自定义数据
+helper:
+  mail:
+    from: ${spring.mail.username}