Merge remote-tracking branch 'origin/master'

This commit is contained in:
YuCheng Hu 2022-10-24 14:57:10 -04:00
commit 5dac24adc2
30 changed files with 614 additions and 90 deletions

View File

@ -12,6 +12,10 @@ param (
[string]$PushPath = "/docker-hub/" [string]$PushPath = "/docker-hub/"
) )
#腾讯云镜像仓库
#[string]$PushServer = "ccr.ccs.tencentyun.com",
#[string]$PushPath = "/kiler398/"
function build { function build {
ExecuteShellText "mvn clean package -DskipTests" "源码Maven编译打包" ExecuteShellText "mvn clean package -DskipTests" "源码Maven编译打包"
} }

View File

@ -127,6 +127,12 @@
<version>0.9.1</version> <version>0.9.1</version>
</dependency> </dependency>
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.datatype</groupId> <groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId> <artifactId>jackson-datatype-jsr310</artifactId>

View File

@ -115,7 +115,7 @@ public class AuthController {
currentLoginUserResponse.setUserEmail(visaTrackUserDetail.getUser().getUserEmail()); currentLoginUserResponse.setUserEmail(visaTrackUserDetail.getUser().getUserEmail());
currentLoginUserResponse.setUserId(visaTrackUserDetail.getUser().getId().toString()); currentLoginUserResponse.setUserId(visaTrackUserDetail.getUser().getId().toString());
currentLoginUserResponse.setUserLoginDate(new Date()); currentLoginUserResponse.setUserLoginDate(new Date());
currentLoginUserResponse.setFavoriteVisaCaseList(userService.getFavoriteVisaCaseIdList(visaTrackUserDetail.getUser().getId()));
return currentLoginUserResponse; return currentLoginUserResponse;
} }

View File

@ -1,9 +1,24 @@
package com.northtecom.visatrack.api.controller.api; package com.northtecom.visatrack.api.controller.api;
import com.northtecom.visatrack.api.controller.vo.BlogCategoryReport;
import com.northtecom.visatrack.api.controller.vo.BlogSearchVo;
import com.northtecom.visatrack.api.controller.vo.BlogYearReport;
import com.northtecom.visatrack.api.data.entity.Blog;
import com.northtecom.visatrack.api.service.impl.BlogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.util.List;
/** /**
* Created with IntelliJ IDEA. * Created with IntelliJ IDEA.
* *
@ -15,9 +30,70 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping(BlogController.BASE_URL) @RequestMapping(BlogController.BASE_URL)
@Tag(name = BlogController.TAG_NAME, description = BlogController.TAG_DESCRIPTION) @Tag(name = BlogController.TAG_NAME, description = BlogController.TAG_DESCRIPTION)
public class BlogController { public class BlogController {
protected static final String DATA_NAME = "博客数据"; protected static final String DATA_NAME = "博客数据";
protected static final String BASE_URL = "/api/blog"; protected static final String BASE_URL = "/api/blog";
protected static final String TAG_NAME = "Blog"; protected static final String TAG_NAME = "Blog";
protected static final String TAG_DESCRIPTION = DATA_NAME + "管理API"; protected static final String TAG_DESCRIPTION = DATA_NAME + "管理API";
private final BlogService blogService;
public BlogController(BlogService blogService) {
this.blogService = blogService;
}
@GetMapping("/queryBlogCategoryReport/")
@Operation(summary = "获取博客分类统计", description = "获取博客分类统计")
public List<BlogCategoryReport> queryBlogCategoryReport() {
return this.blogService.reportCategory();
}
@GetMapping("/queryBlogYearReport/")
@Operation(summary = "获取博客年份统计", description = "获取博客年份统计")
public List<BlogYearReport> queryBlogYearReport() {
return this.blogService.reportYear();
}
@GetMapping("/searchBlog/")
@Operation(summary = "搜索博客", description = "搜索博客")
public Page<Blog> searchBlog(BlogSearchVo blogSearchVo) {
Pageable pageable = PageRequest.of(blogSearchVo.getPageIndex() - 1, blogSearchVo.getPageSize(),
getDefaultSort());
return this.blogService.queryAllPageBlog(pageable, blogSearchVo.getCategory(), blogSearchVo.getYear(),
blogSearchVo.getSearch());
}
@GetMapping("/GetBlogById/")
@Operation(summary = "通过Id获取博客详细内容", description = "通过Id获取博客详细内容")
public Blog getBlogById(String id) {
Blog blog = this.blogService.getBlogById(Long.valueOf(id));
this.blogService.updateBlogVisitCount(blog);
return blog;
}
@GetMapping("/GetPopularBlogs/{topCount}")
@Operation(summary = "获取最受欢迎的博客", description = "获取最受欢迎的博客,按照访问量倒序,且是今年的博客文章")
public List<Blog> GetPopularBlogs(@PathVariable("topCount") Integer topCount) {
Pageable pageable = PageRequest.of(0, topCount, Sort.sort(Blog.class).by(Blog::getVisitCount).descending());
BlogSearchVo blogSearchVo = new BlogSearchVo();
blogSearchVo.setYear(LocalDate.now().getYear() + "");
Page<Blog> blogPageData = this.blogService.queryAllPageBlog(pageable, blogSearchVo.getCategory(),
blogSearchVo.getYear(),
blogSearchVo.getSearch());
return blogPageData.getContent();
}
private Sort getDefaultSort() {
return Sort.sort(Blog.class).by(Blog::getPublishDatetime).descending();
}
} }

View File

@ -114,7 +114,7 @@ public class CrawlController {
InterruptedException, ParseException { InterruptedException, ParseException {
VisaCrawlRequest visaCrawlRequest = new VisaCrawlRequest(); VisaCrawlRequest visaCrawlRequest = new VisaCrawlRequest();
visaCrawlRequest.setDateKey(monthKey); visaCrawlRequest.setDateKey(monthKey);
visaCrawlRequest.setCrawlDetail(true); visaCrawlRequest.setCrawlDetail(false);
this.visaReportCheckeeService.crawlCheckeeVisa(visaCrawlRequest); this.visaReportCheckeeService.crawlCheckeeVisa(visaCrawlRequest);
return true; return true;
} }
@ -153,7 +153,7 @@ public class CrawlController {
try { try {
VisaCrawlRequest visaCrawlRequest = new VisaCrawlRequest(); VisaCrawlRequest visaCrawlRequest = new VisaCrawlRequest();
visaCrawlRequest.setDateKey(monthKey); visaCrawlRequest.setDateKey(monthKey);
visaCrawlRequest.setCrawlDetail(true); visaCrawlRequest.setCrawlDetail(false);
this.visaReportCheckeeService.crawlCheckeeVisa(visaCrawlRequest); this.visaReportCheckeeService.crawlCheckeeVisa(visaCrawlRequest);
} catch (Exception e) { } catch (Exception e) {
log.error("Crawl monthKey[{}] error", monthKey, e); log.error("Crawl monthKey[{}] error", monthKey, e);

View File

@ -1,13 +1,15 @@
package com.northtecom.visatrack.api.controller.api; package com.northtecom.visatrack.api.controller.api;
import com.northtecom.visatrack.api.controller.vo.VisaCaseResponse; import com.northtecom.visatrack.api.controller.vo.*;
import com.northtecom.visatrack.api.controller.vo.VisaCaseSearch;
import com.northtecom.visatrack.api.controller.vo.VisaSubmitRequest;
import com.northtecom.visatrack.api.data.entity.VisaCase; import com.northtecom.visatrack.api.data.entity.VisaCase;
import com.northtecom.visatrack.api.service.impl.MyFavouredVisaCaseService;
import com.northtecom.visatrack.api.service.impl.VisaCaseService; import com.northtecom.visatrack.api.service.impl.VisaCaseService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@ -30,9 +32,11 @@ public class VisaController {
protected static final String TAG_DESCRIPTION = DATA_NAME + "管理API"; protected static final String TAG_DESCRIPTION = DATA_NAME + "管理API";
private final VisaCaseService visaCaseService; private final VisaCaseService visaCaseService;
private final MyFavouredVisaCaseService myFavouredVisaCaseService;
public VisaController(VisaCaseService visaCaseService) { public VisaController(VisaCaseService visaCaseService, MyFavouredVisaCaseService myFavouredVisaCaseService) {
this.visaCaseService = visaCaseService; this.visaCaseService = visaCaseService;
this.myFavouredVisaCaseService = myFavouredVisaCaseService;
} }
// @GetMapping("/QueryByMonthKey") // @GetMapping("/QueryByMonthKey")
@ -71,21 +75,21 @@ public class VisaController {
@PostMapping("/AddVisaCase") @PostMapping("/AddVisaCase")
@Operation(summary = "添加签证数据", description = "添加签证数据") @Operation(summary = "添加签证数据", description = "添加签证数据")
public VisaCaseResponse AddVisaCase(@RequestBody VisaSubmitRequest request) { public VisaCaseResponse addVisaCase(@RequestBody VisaSubmitRequest request) {
VisaCase savedVisaCase = this.visaCaseService.AddVisaCase(request); VisaCase savedVisaCase = this.visaCaseService.AddVisaCase(request);
return new VisaCaseResponse(savedVisaCase); return new VisaCaseResponse(savedVisaCase);
} }
@PostMapping("/UpdateVisaCase/{id}") @PostMapping("/UpdateVisaCase/{id}")
@Operation(summary = "修改签证数据", description = "修改签证数据") @Operation(summary = "修改签证数据", description = "修改签证数据")
public VisaCaseResponse UpdateVisaCase(@RequestBody VisaSubmitRequest request, @PathVariable("id") Long id) { public VisaCaseResponse updateVisaCase(@RequestBody VisaSubmitRequest request, @PathVariable("id") Long id) {
VisaCase savedVisaCase = this.visaCaseService.UpdateVisaCase(request, id); VisaCase savedVisaCase = this.visaCaseService.UpdateVisaCase(request, id);
return new VisaCaseResponse(savedVisaCase); return new VisaCaseResponse(savedVisaCase);
} }
@GetMapping("/GetLastMonths") @GetMapping("/GetLastMonths")
@Operation(summary = "获取最近的月份", description = "获取最近的月份构造MonthlyCase下拉菜单") @Operation(summary = "获取最近的月份", description = "获取最近的月份构造MonthlyCase下拉菜单")
public List<String> GetLastMonths(Integer lastMonths) { public List<String> getLastMonths(Integer lastMonths) {
if (lastMonths <= 0) { if (lastMonths <= 0) {
return null; return null;
} }
@ -93,5 +97,29 @@ public class VisaController {
} }
@PostMapping("/FavouredVisaCase/")
@Operation(summary = "关注签证", description = "关注签证")
public void favouredVisaCase(@RequestBody FavouredVisaCaseRequest request) {
myFavouredVisaCaseService.favouredVisaCase(request.getUserId(), request.getVisaCaseId());
}
@PostMapping("/UnFavouredVisaCase/")
@Operation(summary = "取消关注签证", description = "取消关注签证")
public void unFavouredVisaCase(@RequestBody FavouredVisaCaseRequest request) {
myFavouredVisaCaseService.unFavouredVisaCase(request.getUserId(), request.getVisaCaseId());
}
@PreAuthorize("authentication.getPrincipal().toString()!=\"anonymousUser\"")
@GetMapping("/queryMyFavouredVisaCase/")
@Operation(summary = "获取我的关注签证列表", description = "获取我的关注签证列表")
public List<VisaCase> queryMyFavouredVisaCase() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
VisaTrackUserDetail userDetail = (VisaTrackUserDetail) authentication.getPrincipal();
return myFavouredVisaCaseService.queryFavouredVisaCases(userDetail.getId());
}
} }

View File

@ -0,0 +1,16 @@
package com.northtecom.visatrack.api.controller.vo;
import lombok.Data;
/**
* Created with IntelliJ IDEA.
*
* @Author: XieYang
* @Date: 2022/10/23/20:16
* @Description:
*/
@Data
public class BlogCategoryReport {
private String category;
private Integer total;
}

View File

@ -0,0 +1,19 @@
package com.northtecom.visatrack.api.controller.vo;
import lombok.Data;
/**
* Created with IntelliJ IDEA.
*
* @Author: XieYang
* @Date: 2022/10/23/22:03
* @Description:
*/
@Data
public class BlogSearchVo {
private String search;
private String category;
private String year;
private Integer pageIndex = 1;
private Integer pageSize = 10;
}

View File

@ -0,0 +1,16 @@
package com.northtecom.visatrack.api.controller.vo;
import lombok.Data;
/**
* Created with IntelliJ IDEA.
*
* @Author: XieYang
* @Date: 2022/10/23/20:17
* @Description:
*/
@Data
public class BlogYearReport {
private String year;
private Integer total;
}

View File

@ -2,7 +2,9 @@ package com.northtecom.visatrack.api.controller.vo;
import lombok.Data; import lombok.Data;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List;
/** /**
* Created with IntelliJ IDEA. * Created with IntelliJ IDEA.
@ -18,4 +20,5 @@ public class CustomerUserInfoResponse {
private String userEmail; private String userEmail;
private Date userLoginDate; private Date userLoginDate;
private String userActiveCode; private String userActiveCode;
private List<String> favoriteVisaCaseList = new ArrayList<>();
} }

View File

@ -0,0 +1,16 @@
package com.northtecom.visatrack.api.controller.vo;
import lombok.Data;
/**
* Created with IntelliJ IDEA.
*
* @Author: XieYang
* @Date: 2022/10/23/21:34
* @Description:
*/
@Data
public class FavouredVisaCaseRequest {
private Long visaCaseId;
private Long userId;
}

View File

@ -6,6 +6,7 @@ import org.hibernate.annotations.Type;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table; import javax.persistence.Table;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@ -17,25 +18,34 @@ import java.util.List;
*/ */
@Entity @Entity
@Data @Data
@Table(name = "blog") @Table(name = "blog", indexes = {
@Index(name = "ix_blog_category", columnList = "category"),
@Index(name = "ix_blog_title", columnList = "title"),
@Index(name = "ix_blog_summary", columnList = "summary"),
@Index(name = "ix_blog_author_name", columnList = "author_name"),
@Index(name = "ix_blog_publish_time", columnList = "publish_time")
})
@org.hibernate.annotations.Table(appliesTo = "blog", comment = "Blog") @org.hibernate.annotations.Table(appliesTo = "blog", comment = "Blog")
public class Blog extends BaseEntity<Long> { public class Blog extends BaseEntity<Long> {
@Column(name = "author_name", columnDefinition = "varchar(255) COMMENT 'Author name'") @Column(name = "author_name", columnDefinition = "varchar(50) COMMENT 'Author name'")
private String authorName; private String authorName;
@Column(name = "category", columnDefinition = "varchar(255) COMMENT 'Category'") @Column(name = "category", columnDefinition = "varchar(50) COMMENT 'Category'")
private String category; private String category;
@Column(name = "title", columnDefinition = "varchar(255) COMMENT 'Title'") @Column(name = "title", columnDefinition = "varchar(300) COMMENT 'Title'")
private String blogTitle; private String blogTitle;
@Column(name = "content", columnDefinition = "TEXT COMMENT 'Content'") @Column(name = "content", columnDefinition = "LONGTEXT COMMENT 'Content'")
private String blogCover;
@Column(name = "cover", columnDefinition = "varchar(255) COMMENT 'Cover'")
private String blogSummary;
@Column(name = "summary", columnDefinition = "LONGTEXT COMMENT 'Summary'")
private String blogContent; private String blogContent;
@Column(name = "cover", columnDefinition = "varchar(200) COMMENT 'Cover'")
private String blogCover;
@Column(name = "summary", columnDefinition = "TEXT COMMENT 'Summary'")
private String blogSummary;
@Column(name = "publish_time", columnDefinition = "DateTime COMMENT 'Publish time'") @Column(name = "publish_time", columnDefinition = "DateTime COMMENT 'Publish time'")
private LocalDateTime publishDatetime; private LocalDateTime publishDatetime;
@Type(type = "json") @Type(type = "json")
@Column(columnDefinition = "json") @Column(columnDefinition = "json COMMENT 'Tags'")
private List<String> keywords; private List<String> tags;
@Column(name = "visit_count", columnDefinition = "INT COMMENT 'Visit count'")
private Integer visitCount;
} }

View File

@ -0,0 +1,43 @@
package com.northtecom.visatrack.api.data.entity;
import com.northtecom.visatrack.api.base.data.BaseEntity;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;
import java.time.LocalDate;
/**
* Created with IntelliJ IDEA.
*
* @Author: XieYang
* @Date: 2022/10/23/10:41
* @Description:
*/
@Entity
@Data
@Table(name = "my_favoured_visa_case", indexes = {
@Index(name = "my_favoured_visa_case_user_id", columnList = "user_id"),
@Index(name = "my_favoured_visa_case_visa_case_id", columnList = "visa_case_id")
})
@org.hibernate.annotations.Table(appliesTo = "my_favoured_visa_case", comment = "My favoured visa case")
public class MyFavouredVisaCase extends BaseEntity<Long> {
/**
* 用户 Id
*/
@Column(name = "user_id", columnDefinition = "varchar(50) COMMENT 'user id'")
private Long userId;
/**
* 关注的 visa case id
*/
@Column(name = "visa_case_id", columnDefinition = "varchar(50) COMMENT 'visa case id'")
private Long visaCaseId;
/**
* 关注时间
*/
@Column(name = "favoured_time", columnDefinition = "Date COMMENT 'favoured time'")
private LocalDate favouredDate;
}

View File

@ -18,7 +18,16 @@ import java.util.Date;
*/ */
@Entity @Entity
@Data @Data
@Table(name = "visa_case") @Table(name = "visa_case", indexes = {
@Index(name = "ix_visa_case_visa_category", columnList = "visa_category"),
@Index(name = "ix_visa_case_visa_status", columnList = "visa_status"),
@Index(name = "ix_visa_case_embassy_consulate", columnList = "embassy_consulate"),
@Index(name = "ix_visa_case_date_visa_interview", columnList = "date_visa_interview"),
@Index(name = "ix_visa_case_date_visa_check_completed", columnList = "date_visa_check_completed"),
@Index(name = "ix_visa_case_save_user_id", columnList = "save_user_id"),
@Index(name = "ix_visa_case_is_crawled", columnList = "is_crawled"),
@Index(name = "ix_visa_case_crawled_time", columnList = "crawled_time"),
})
@org.hibernate.annotations.Table(appliesTo = "visa_case", comment = "Visa case") @org.hibernate.annotations.Table(appliesTo = "visa_case", comment = "Visa case")
public class VisaCase extends BaseEntity<Long> { public class VisaCase extends BaseEntity<Long> {
/** /**

View File

@ -3,10 +3,7 @@ package com.northtecom.visatrack.api.data.entity;
import com.northtecom.visatrack.api.base.data.BaseEntity; import com.northtecom.visatrack.api.base.data.BaseEntity;
import lombok.Data; import lombok.Data;
import javax.persistence.Column; import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Date; import java.util.Date;
@ -20,7 +17,9 @@ import java.util.Date;
@Entity @Entity
@Data @Data
@Table(name = "visa_checkee_crawl_data", uniqueConstraints = { @Table(name = "visa_checkee_crawl_data", uniqueConstraints = {
@UniqueConstraint(columnNames = {"case_num"}) @UniqueConstraint(columnNames = {"case_num"})}, indexes = {
@Index(name = "ix_visa_checkee_crawl_data_month", columnList = "month"),
@Index(name = "ix_visa_checkee_crawl_data_save_to_visa_case_id", columnList = "save_to_visa_case_id")
}) })
public class VisaCheckeeCrawlData extends BaseEntity<Long> { public class VisaCheckeeCrawlData extends BaseEntity<Long> {
@Column(name = "month", columnDefinition = "varchar(50) COMMENT 'month'") @Column(name = "month", columnDefinition = "varchar(50) COMMENT 'month'")

View File

@ -1,10 +1,23 @@
package com.northtecom.visatrack.api.data.repository; package com.northtecom.visatrack.api.data.repository;
import com.northtecom.visatrack.api.data.entity.Blog; import com.northtecom.visatrack.api.data.entity.Blog;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
/** /**
* *
*/ */
public interface BlogRepository extends PagingAndSortingRepository<Blog, Long> { public interface BlogRepository extends PagingAndSortingRepository<Blog, Long>,
JpaSpecificationExecutor<Blog> {
@Query(value = "select b.category,COUNT(*) as category_count from usvisatrack.blog b group by b.category ",
nativeQuery = true)
List<Object[]> reportAllCategory();
@Query(value = "select DATE_FORMAT(b.publish_time ,'%Y') as month_key,COUNT(*) as year_count from usvisatrack" +
".blog b group by month_key",
nativeQuery = true)
List<Object[]> reportAllYear();
} }

View File

@ -0,0 +1,23 @@
package com.northtecom.visatrack.api.data.repository;
import com.northtecom.visatrack.api.data.entity.MyFavouredVisaCase;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.util.List;
import java.util.Optional;
/**
* Created with IntelliJ IDEA.
*
* @Author: XieYang
* @Date: 2022/10/23/17:27
* @Description:
*/
public interface MyFavouredVisaCaseRepository extends PagingAndSortingRepository<MyFavouredVisaCase, Long> {
@Query("select m from MyFavouredVisaCase m where m.userId = ?1 and m.visaCaseId = ?2")
Optional<MyFavouredVisaCase> findByUserIdAndVisaCaseId(Long userId, Long visaCaseId);
@Query("select m from MyFavouredVisaCase m where m.userId = ?1 order by m.favouredDate desc")
List<MyFavouredVisaCase> findAllByUserId(Long userId);
}

View File

@ -53,7 +53,7 @@ public interface VisaCaseRepository extends PagingAndSortingRepository<VisaCase,
@Query(value = "select * \n" + @Query(value = "select * \n" +
"from usvisatrack.visa_case \n" + "from usvisatrack.visa_case \n" +
"where date_visa_interview >=:startDate and date_visa_interview < :endDate \n" + "where date_visa_interview >=:startDate and date_visa_interview < :endDate \n" +
"order by date_visa_interview", nativeQuery = true) "order by date_visa_interview desc", nativeQuery = true)
List<VisaCase> queryByCheckDateRange(@Param("startDate") LocalDate startDate, List<VisaCase> queryByCheckDateRange(@Param("startDate") LocalDate startDate,
@Param("endDate") LocalDate endDate); @Param("endDate") LocalDate endDate);
@ -75,4 +75,9 @@ public interface VisaCaseRepository extends PagingAndSortingRepository<VisaCase,
@Param("endDate") LocalDate endDate); @Param("endDate") LocalDate endDate);
@Query("select visaCase from VisaCase visaCase where visaCase.saveUserId in (select m.userId from " +
"MyFavouredVisaCase m where m.userId = :userId)")
List<VisaCase> queryFavouredVisaCaseByUserId(@Param("userId") Long userId);
} }

View File

@ -1,5 +1,7 @@
package com.northtecom.visatrack.api.data.spec; package com.northtecom.visatrack.api.data.spec;
import com.northtecom.visatrack.api.data.entity.Blog;
import lombok.Data;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -15,21 +17,25 @@ import javax.persistence.criteria.Root;
* @Date: 2022/10/14/17:55 * @Date: 2022/10/14/17:55
* @Description: * @Description:
*/ */
public class BlogSpecification implements Specification { @Data
private DateRange publishDateRange; public class BlogSpecification implements Specification<Blog> {
private Integer year;
private String search; private String search;
private String category; private String category;
@Override @Override
public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) { public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
if (publishDateRange != null) {
if (year != null) {
DateRange publishDateRange = DateRange.ofYear(year);
if (publishDateRange.getStart() != null) { if (publishDateRange.getStart() != null) {
query.where(criteriaBuilder.greaterThanOrEqualTo(root.get("publish_time"), query.where(criteriaBuilder.greaterThanOrEqualTo(root.get("publishDatetime"),
publishDateRange.getStart())); publishDateRange.getStart().atTime(0, 0, 0)));
} }
if (publishDateRange.getEnd() != null) { if (publishDateRange.getEnd() != null) {
query.where(criteriaBuilder.lessThanOrEqualTo(root.get("publish_time"), query.where(criteriaBuilder.lessThan(root.get("publishDatetime"),
publishDateRange.getEnd())); publishDateRange.getEnd().atTime(0, 0, 0)));
} }
} }

View File

@ -46,6 +46,13 @@ public class DateRange {
return dateRange; return dateRange;
} }
public static DateRange ofYear(Integer year) {
DateRange dateRange = new DateRange();
dateRange.setStart(LocalDate.of(year, 1, 1));
dateRange.setEnd(dateRange.getStart().plusYears(1));
return dateRange;
}
public static DateRange ofLastMonth(Integer lastMonth) { public static DateRange ofLastMonth(Integer lastMonth) {
DateRange dateRange = new DateRange(); DateRange dateRange = new DateRange();
LocalDate nowDate = LocalDate.now(); LocalDate nowDate = LocalDate.now();

View File

@ -0,0 +1,90 @@
package com.northtecom.visatrack.api.service.impl;
import com.northtecom.visatrack.api.controller.vo.BlogCategoryReport;
import com.northtecom.visatrack.api.controller.vo.BlogYearReport;
import com.northtecom.visatrack.api.data.entity.Blog;
import com.northtecom.visatrack.api.data.repository.BlogRepository;
import com.northtecom.visatrack.api.data.spec.BlogSpecification;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Listing Service.
* This Service process listing related.
*
* @author YuCheng Hu
*/
@Service
@Slf4j
public class BlogService {
private final BlogRepository blogRepository;
@Autowired
public BlogService(BlogRepository blogRepository) {
this.blogRepository = blogRepository;
}
public Page<Blog> queryAllPageBlog(Pageable pageable, String category, String year, String search) {
BlogSpecification blogSpecification = new BlogSpecification();
if (StringUtils.hasText(category)) {
blogSpecification.setCategory(category);
}
if (StringUtils.hasText(year)) {
blogSpecification.setYear(Integer.valueOf(year));
}
if (StringUtils.hasText(search)) {
blogSpecification.setSearch(search);
}
return blogRepository.findAll(blogSpecification, pageable);
}
public List<BlogCategoryReport> reportCategory() {
List<Object[]> blogCategoryReportData = blogRepository.reportAllCategory();
List<BlogCategoryReport> blogCategoryReportList = new ArrayList<>();
for (Object[] data : blogCategoryReportData) {
BlogCategoryReport blogCategoryReport = new BlogCategoryReport();
blogCategoryReport.setCategory((String) data[0]);
blogCategoryReport.setTotal(Integer.valueOf(data[1].toString()));
blogCategoryReportList.add(blogCategoryReport);
}
return blogCategoryReportList;
}
public List<BlogYearReport> reportYear() {
List<Object[]> blogYearReportData = blogRepository.reportAllYear();
List<BlogYearReport> blogYearReportList = new ArrayList<>();
for (Object[] data : blogYearReportData) {
BlogYearReport blogYearReport = new BlogYearReport();
blogYearReport.setYear((String) data[0]);
blogYearReport.setTotal(Integer.valueOf(data[1].toString()));
blogYearReportList.add(blogYearReport);
}
return blogYearReportList;
}
public Blog getBlogById(Long blogId) {
return blogRepository.findById(blogId).orElse(null);
}
@Transactional
public void updateBlogVisitCount(Blog blog) {
blog.setVisitCount(blog.getVisitCount() + 1);
blogRepository.save(blog);
}
}

View File

@ -10,6 +10,7 @@ import com.northtecom.visatrack.api.data.repository.VisaCaseRepository;
import com.northtecom.visatrack.api.data.spec.DateRange; import com.northtecom.visatrack.api.data.spec.DateRange;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
@ -80,7 +81,7 @@ public class CaseVisaReportService {
} }
public List<CaseVisaReport> QueryAllReportData() { public List<CaseVisaReport> QueryAllReportData() {
return (List<CaseVisaReport>) this.caseVisaReportRepository.findAll(); return (List<CaseVisaReport>) this.caseVisaReportRepository.findAll(Sort.by(Sort.Direction.DESC, "month"));
} }
public CaseVisaReport QueryByMonth(String monthKey) { public CaseVisaReport QueryByMonth(String monthKey) {

View File

@ -1,38 +0,0 @@
package com.northtecom.visatrack.api.service.impl;
import com.northtecom.visatrack.api.data.entity.Blog;
import com.northtecom.visatrack.api.data.repository.BlogRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
/**
* Listing Service.
* This Service process listing related.
*
* @author YuCheng Hu
*/
@Service
@Slf4j
public class ContentService {
private final BlogRepository blogRepository;
@Autowired
public ContentService(BlogRepository blogRepository) {
this.blogRepository = blogRepository;
}
public Page<Blog> getNewBlog(Pageable pageable) {
return blogRepository.findAll(pageable);
}
public Blog getBlogById(Long blogId) {
return blogRepository.findById(blogId).orElse(null);
}
}

View File

@ -0,0 +1,73 @@
package com.northtecom.visatrack.api.service.impl;
import com.northtecom.visatrack.api.data.entity.MyFavouredVisaCase;
import com.northtecom.visatrack.api.data.entity.VisaCase;
import com.northtecom.visatrack.api.data.repository.MyFavouredVisaCaseRepository;
import com.northtecom.visatrack.api.data.repository.VisaCaseRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* Created with IntelliJ IDEA.
*
* @Author: XieYang
* @Date: 2022/10/23/17:40
* @Description:
*/
@Service
@Slf4j
public class MyFavouredVisaCaseService {
private final MyFavouredVisaCaseRepository myFavouredVisaCaseRepository;
private final VisaCaseRepository visaCaseRepository;
public MyFavouredVisaCaseService(MyFavouredVisaCaseRepository myFavouredVisaCaseRepository,
VisaCaseRepository visaCaseRepository) {
this.myFavouredVisaCaseRepository = myFavouredVisaCaseRepository;
this.visaCaseRepository = visaCaseRepository;
}
public void favouredVisaCase(Long userId, Long visaCaseId) {
log.info("User: {} favoured visa case: {}", userId, visaCaseId);
MyFavouredVisaCase myFavouredVisaCase = myFavouredVisaCaseRepository.findByUserIdAndVisaCaseId(userId,
visaCaseId).stream().findFirst().orElse(null);
if (myFavouredVisaCase == null) {
myFavouredVisaCase = new MyFavouredVisaCase();
myFavouredVisaCase.setUserId(userId);
myFavouredVisaCase.setVisaCaseId(visaCaseId);
myFavouredVisaCaseRepository.save(myFavouredVisaCase);
}
}
public void unFavouredVisaCase(Long userId, Long visaCaseId) {
log.info("User: {} un-favoured visa case: {}", userId, visaCaseId);
MyFavouredVisaCase myFavouredVisaCase = myFavouredVisaCaseRepository.findByUserIdAndVisaCaseId(userId,
visaCaseId).stream().findFirst().orElse(null);
if (myFavouredVisaCase != null) {
myFavouredVisaCaseRepository.delete(myFavouredVisaCase);
}
}
public List<MyFavouredVisaCase> queryFavouredVisaCasesData(Long userId) {
log.info("Query user: {} favoured visa cases", userId);
return myFavouredVisaCaseRepository.findAllByUserId(userId).stream().collect(Collectors.toList());
}
public List<VisaCase> queryFavouredVisaCases(Long userId) {
log.info("Query user: {} favoured visa cases", userId);
return visaCaseRepository.queryFavouredVisaCaseByUserId(userId);
}
}

View File

@ -10,8 +10,10 @@ import com.northtecom.visatrack.api.controller.vo.RegisterUserRequest;
import com.northtecom.visatrack.api.controller.vo.VisaTrackUserDetail; import com.northtecom.visatrack.api.controller.vo.VisaTrackUserDetail;
import com.northtecom.visatrack.api.data.entity.User; import com.northtecom.visatrack.api.data.entity.User;
import com.northtecom.visatrack.api.data.entity.UserChangePassword; import com.northtecom.visatrack.api.data.entity.UserChangePassword;
import com.northtecom.visatrack.api.data.entity.VisaCase;
import com.northtecom.visatrack.api.data.repository.UserChangePasswordRepository; import com.northtecom.visatrack.api.data.repository.UserChangePasswordRepository;
import com.northtecom.visatrack.api.data.repository.UserRepository; import com.northtecom.visatrack.api.data.repository.UserRepository;
import com.northtecom.visatrack.api.data.repository.VisaCaseRepository;
import com.northtecom.visatrack.api.service.enums.UserStatus; import com.northtecom.visatrack.api.service.enums.UserStatus;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -28,7 +30,9 @@ import org.springframework.util.StringUtils;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
/** /**
* Listing Service. * Listing Service.
@ -47,7 +51,8 @@ public class UserService implements UserDetailsService {
private UserRepository userRepository; private UserRepository userRepository;
@Autowired @Autowired
private UserChangePasswordRepository userChangePasswordRepository; private UserChangePasswordRepository userChangePasswordRepository;
@Autowired
private VisaCaseRepository visaCaseRepository;
@Autowired @Autowired
private EmailService emailService; private EmailService emailService;
@ -237,4 +242,8 @@ public class UserService implements UserDetailsService {
emailService.sendChangePasswordSuccessEmailToUser(dbUser); emailService.sendChangePasswordSuccessEmailToUser(dbUser);
} }
public List<String> getFavoriteVisaCaseIdList(Long userId) {
return visaCaseRepository.queryFavouredVisaCaseByUserId(userId).stream().map(VisaCase::getId).collect(Collectors.toList()).stream().map(String::valueOf).collect(Collectors.toList());
}
} }

View File

@ -387,4 +387,12 @@ public class VisaCaseService {
} }
return months; return months;
} }
@PreAuthorize("authentication.getPrincipal().toString()!=\"anonymousUser\"")
public List<VisaCase> queryMyFavouredVisaCase() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
VisaTrackUserDetail userDetail = (VisaTrackUserDetail) authentication.getPrincipal();
return visaCaseRepository.queryFavouredVisaCaseByUserId(userDetail.getId());
}
} }

View File

@ -0,0 +1,2 @@
server:
port: 8282

View File

@ -0,0 +1,6 @@
server:
ssl:
key-store: classpath:keystore.p12
key-store-password: 123456
key-store-type: PKCS12
key-alias: tomcat

View File

@ -19,12 +19,10 @@ crawl:
server: server:
port: ${app.web.host} port: ${app.web.host}
ssl:
key-store: classpath:keystore.p12
key-store-password: 123456
key-store-type: PKCS12
key-alias: tomcat
spring: spring:
profiles:
active: prod
application: application:
name: usvisatrack name: usvisatrack
title: Us Visa Track API title: Us Visa Track API

View File

@ -1,14 +1,25 @@
package com.northtecom.visatrack.api; package com.northtecom.visatrack.api;
import com.github.javafaker.Faker;
import com.northtecom.visatrack.api.data.entity.Blog;
import com.northtecom.visatrack.api.data.entity.Dictionary; import com.northtecom.visatrack.api.data.entity.Dictionary;
import com.northtecom.visatrack.api.data.repository.BlogRepository;
import com.northtecom.visatrack.api.data.repository.DictionaryRepository; import com.northtecom.visatrack.api.data.repository.DictionaryRepository;
import com.northtecom.visatrack.api.service.impl.VisaCaseService; import com.northtecom.visatrack.api.service.impl.VisaCaseService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@SpringBootTest @SpringBootTest
@Slf4j
class VisaTrackApiApplicationTests { class VisaTrackApiApplicationTests {
@Autowired @Autowired
@ -17,6 +28,10 @@ class VisaTrackApiApplicationTests {
@Autowired @Autowired
private VisaCaseService visaCaseService; private VisaCaseService visaCaseService;
@Autowired
private BlogRepository blogRepository;
@Test @Test
void contextLoads() { void contextLoads() {
} }
@ -32,24 +47,85 @@ class VisaTrackApiApplicationTests {
@Test @Test
@Disabled @Disabled
void dataInit() { void dataInit() {
CreateDictionary("DEGREE", "BS,MS,Ph.D,Others"); createDictionary("DEGREE", "BS,MS,Ph.D,Others");
CreateDictionary("US_CONSULATE", "BeiJing,ChengDu,Chennai,Europe,GuangZhou,HongKong,Kolkata,MexicoCity," + createDictionary("US_CONSULATE", "BeiJing,ChengDu,Chennai,Europe,GuangZhou,HongKong,Kolkata,MexicoCity," +
"Montreal," + "Montreal," +
"Mumbai,NewDelhi,Ottawa,Quebec,ShangHai,ShenYang,Tijuana,Toronto,Vancouver,Others"); "Mumbai,NewDelhi,Ottawa,Quebec,ShangHai,ShenYang,Tijuana,Toronto,Vancouver,Others");
CreateDictionary("VISA_TYPE", "F1,F2,H1,H4,J1,J2,B1,B2,L1,L2,O1,O2"); createDictionary("VISA_TYPE", "F1,F2,H1,H4,J1,J2,B1,B2,L1,L2,O1,O2");
CreateDictionary("VISA_STATUS", "Pending,Clear,Reject"); createDictionary("VISA_STATUS", "Pending,Clear,Reject");
CreateDictionary("VISA_ENTRY", "New,Renewal"); createDictionary("VISA_ENTRY", "New,Renewal");
} }
private void CreateDictionary(String category, String keys) { @Test
@Disabled
void generateTestBlogs() {
Faker faker = new Faker(new Locale("zh-CN"));
List<String> categoryList = Arrays.asList("Design", "Development", "Business", "Project", "Travel", "Travel",
"Lifestyle", "Photography");
List<Integer> years = Arrays.asList(2022, 2021, 2020, 2019, 2018);
for (int i = 0; i < categoryList.size(); i++) {
String category = categoryList.get(i);
for (int j = 0; j < years.size(); j++) {
Integer year = years.get(j);
Integer blogCount = faker.number().numberBetween(1, 10);
for (int k = 0; k < blogCount; k++) {
newBlog(
faker.name().fullName(),
category,
faker.lorem().sentence(12),
faker.lorem().paragraph(100),
faker.internet().image(),
faker.lorem().paragraph(6),
LocalDate.of(year, faker.number().numberBetween(1, 12), faker.number().numberBetween(1,
28)),
new ArrayList<>(),
faker.random().nextInt(0, 100));
}
}
}
}
private void newBlog(
String authorName,
String category,
String title,
String content,
String cover,
String summary,
LocalDate publish_time,
List<String> tags,
Integer visit_count) {
Blog blog = new Blog();
blog.setAuthorName(authorName);
blog.setCategory(category);
blog.setBlogTitle(title);
blog.setBlogContent(content);
blog.setBlogCover(cover);
blog.setBlogSummary(summary);
blog.setPublishDatetime(publish_time.atTime(0, 0, 0));
blog.setTags(tags);
blog.setVisitCount(visit_count);
log.info("insert blog:{}", blog);
blogRepository.save(blog);
}
private void createDictionary(String category, String keys) {
String[] dictionaryItems = keys.split(","); String[] dictionaryItems = keys.split(",");
for (int i = 0; i < dictionaryItems.length; i++) { for (int i = 0; i < dictionaryItems.length; i++) {
CreateDictionaryItem(category, dictionaryItems[i], dictionaryItems[i], "", i); createDictionaryItem(category, dictionaryItems[i], dictionaryItems[i], "", i);
} }
} }
private void CreateDictionaryItem(String category, String key, String value, String remark, int sortIndex) { private void createDictionaryItem(String category, String key, String value, String remark, int sortIndex) {
Dictionary dictionary = new Dictionary(); Dictionary dictionary = new Dictionary();
dictionary.setCategory(category); dictionary.setCategory(category);
dictionary.setKey(key); dictionary.setKey(key);