diff --git a/servers/boe-server-all/src/main/java/com/xboe/BoeServerAllApplication.java b/servers/boe-server-all/src/main/java/com/xboe/BoeServerAllApplication.java index 5dfeacda..d390a4c8 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/BoeServerAllApplication.java +++ b/servers/boe-server-all/src/main/java/com/xboe/BoeServerAllApplication.java @@ -12,12 +12,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.system.ApplicationPid; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; @Configuration @SpringBootApplication @EnableCaching @EnableAsync @EnableRetry +@EnableScheduling public class BoeServerAllApplication { public static void main(String[] args) { diff --git a/servers/boe-server-all/src/main/java/com/xboe/api/ThirdApi.java b/servers/boe-server-all/src/main/java/com/xboe/api/ThirdApi.java index 831e2299..f5167e03 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/api/ThirdApi.java +++ b/servers/boe-server-all/src/main/java/com/xboe/api/ThirdApi.java @@ -16,6 +16,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -231,5 +234,38 @@ public class ThirdApi { } + /** + * 获取案例浏览记录 + */ + public UserDynamicResult getAllUserdynamicListOfCaseRead(UserdynamicParam userdynamicParam, String token) { + String s = buildFormData(userdynamicParam); + String resp = Optional.ofNullable(HttpRequest + .post(userdynamicListUrl) + .header("Content-Type", "application/x-www-form-urlencoded") + .body(s) + .header("XBOE-Access-Token", token) + .execute().body()).orElseThrow(() -> new RuntimeException("token校验失败")); + DynamicBean dynamicBean = JSONUtil.toBean(resp, DynamicBean.class); + UserDynamicResult userdynamicResult = dynamicBean.getResult(); + return userdynamicResult; + } + + private String buildFormData(UserdynamicParam param) { + StringBuilder builder = new StringBuilder(); + try { + builder.append("pageIndex=").append(URLEncoder.encode(param.getPageIndex().toString(), "UTF-8")); + + builder.append("&pageSize=").append(URLEncoder.encode(param.getPageSize().toString(), "UTF-8")); + builder.append("&contentType=").append(URLEncoder.encode(param.getContentType().toString(), "UTF-8")); + builder.append("&aid=").append(URLEncoder.encode(param.getAid().toString(), "UTF-8")); + builder.append("&eventKey=").append(URLEncoder.encode("ReadCase", "UTF-8")); + if (param.getHidden() != null) { + builder.append("&hidden=").append(URLEncoder.encode(param.getHidden(), "UTF-8")); + } + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + return builder.toString(); + } } diff --git a/servers/boe-server-all/src/main/java/com/xboe/constants/CacheName.java b/servers/boe-server-all/src/main/java/com/xboe/constants/CacheName.java index 3d765d51..07810238 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/constants/CacheName.java +++ b/servers/boe-server-all/src/main/java/com/xboe/constants/CacheName.java @@ -135,4 +135,24 @@ public interface CacheName { String KEY_DICT="dict"; String STUDY_KEY = "StudyKey:"; + + /** + * 季度观看量排行key + * */ + String CASE_RANK_VIEWS_QUARTER="case:rank:views:quarter"; + + /** + * 总观看排行key + * */ + String CASE_RANK_VIEWS_ALL="case:rank:views:all"; + + /** + * 季度点赞排行key + * */ + String CASE_RANK_PRAISE_QUARTER ="case:rank:praise:quarter"; + + /** + * 总点赞排行key + * */ + String CASE_RANK_PRAISE_ALL="case:rank:praise:all"; } diff --git a/servers/boe-server-all/src/main/java/com/xboe/enums/CasesRankEnum.java b/servers/boe-server-all/src/main/java/com/xboe/enums/CasesRankEnum.java new file mode 100644 index 00000000..ce570db2 --- /dev/null +++ b/servers/boe-server-all/src/main/java/com/xboe/enums/CasesRankEnum.java @@ -0,0 +1,26 @@ +package com.xboe.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import static com.xboe.constants.CacheName.*; + +/** + * 案例排行榜类型 + */ +@AllArgsConstructor +@Getter +public enum CasesRankEnum { + + QUARTER_VIEWS(1,"季度观看量排行",CASE_RANK_VIEWS_QUARTER), + ALL_VIEWS(2,"总观看排行",CASE_RANK_VIEWS_ALL), + QUARTER_PRAISES(3,"季度点赞排行",CASE_RANK_PRAISE_QUARTER), + ALL_PRAISES(4,"总点赞排行",CASE_RANK_PRAISE_ALL), + ; + + private Integer type; + private String name; + private String cacheKey; + + +} diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseScheduledTasks.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseScheduledTasks.java new file mode 100644 index 00000000..243ae1eb --- /dev/null +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CaseScheduledTasks.java @@ -0,0 +1,29 @@ +package com.xboe.module.boecase.api; + +import com.xboe.module.boecase.service.ICasesService; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +@Component +public class CaseScheduledTasks { + + @Resource + private ICasesService casesService; + + @Scheduled(cron = "0 0 1 1 * ?") // 每月的第一天的1:00执行 + public void refreshViewsRankOfMajor() { + casesService.refreshViewsRankOfMajor(); + } + + /** + * 季初执行,cron表达式设置为每个季度的第一个月的第一天的特定时间。每个季度的第一个月是1月、4月、7月和10月: + */ + @Scheduled(cron = "0 0 2 1 1,4,7,10 ?") + public void refreshLastQuarterStatistics() { + casesService.refreshLastQuarterStatistics(); + } + + +} diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CasesApi.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CasesApi.java index 60bf649b..1fdce29b 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CasesApi.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/api/CasesApi.java @@ -11,18 +11,14 @@ import com.xboe.module.boecase.dao.CasesMajorTypeDao; import com.xboe.module.boecase.dto.*; import com.xboe.module.boecase.entity.CasesMajorType; import com.xboe.module.boecase.service.ICasesRecommendPushRecordService; -import com.xboe.module.boecase.vo.CaseExportVo; +import com.xboe.module.boecase.vo.*; import com.xboe.module.dict.entity.DictItem; import com.xboe.module.excel.ExportsExcelSenderUtil; import com.xboe.system.user.dao.UserDao; import com.xboe.system.user.entity.User; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.LocalDateTimeUtil; @@ -39,6 +35,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.validation.annotation.Validated; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.time.LocalDateTime; @@ -127,25 +124,12 @@ public class CasesApi extends ApiBaseController { @PostMapping("/queryListV2") public JsonResponse> queryCaseBreV2(@Validated @RequestBody CasePageVo req) { String type = req.getType(); - PageList subViews1; - PageList subViews2; - PageList views = null; req.setUserId(getCurrent().getAccountId()); - if (StringUtils.isNotEmpty(type)) { - if ("recommend".equals(type)) { - views = casesService.queryRecommendPageCasesV2(req); - } else { - views = casesService.queryPageCasesV2(req); - } + PageList views = null; + if (type.equals("recommend")) { + views = casesService.queryRecommendPageCasesV2(req); } else { - PageDto pageDto = new PageDto(); - pageDto.setPageIndex(req.getPageIndex()); - pageDto.setPageSize(req.getPageSize()); - req.setPageSize(1000000); - req.setPageIndex(1); - subViews1 = casesService.queryRecommendPageCasesV2(req); - subViews2 = casesService.queryPageCasesV2(req); - views = merge(subViews1, subViews2, pageDto); + views = casesService.queryPageCasesV2(req); } if (views != null) { @@ -175,24 +159,6 @@ public class CasesApi extends ApiBaseController { return success(views); } - public static PageList merge(PageList pageList1, PageList pageList2, PageDto pageDto) { - List mergedCaseList = new ArrayList<>(); - mergedCaseList.addAll(pageList1.getList()); - mergedCaseList.addAll(pageList2.getList()); - List pageCaseList = mergedCaseList.stream() - .skip((long) (pageDto.getPageIndex() - 1) * pageDto.getPageSize()) - .limit(pageDto.getPageSize()) - .collect(Collectors.toList()); - int totalCount = pageList1.getCount() + pageList2.getCount(); - int pageSize = pageDto.getPageSize(); - - PageList mergePageList = new PageList<>(); - mergePageList.setList(pageCaseList); - mergePageList.setCount(totalCount); - mergePageList.setPageSize(pageSize); - return mergePageList; - } - @PostMapping("/caseYears") public JsonResponse> caseYears() { List result = casesService.getCaseYears(); @@ -646,7 +612,8 @@ public class CasesApi extends ApiBaseController { if (ids.isEmpty()) { return badRequest("参数异常"); } - List cases = casesService.ids(ids); + String accountId = getCurrent().getAccountId(); + List cases = casesService.ids(ids,accountId); return success(cases); } @@ -654,7 +621,7 @@ public class CasesApi extends ApiBaseController { * 设置/取消优秀案例 */ @PostMapping("/excellent") - public JsonResponse excellent(String id, Boolean excellent) { + public JsonResponse excellent(String id, Boolean excellent,String excellentReason) { if (StringUtil.isBlank(id)) { return badRequest("参数异常"); } @@ -662,12 +629,145 @@ public class CasesApi extends ApiBaseController { excellent = false;//默认设置取消 } try { - casesService.excellent(id, excellent); + casesService.excellent(id, excellent,excellentReason); return success(true); } catch (Exception e) { return error("设置或者取消失败", e.getMessage()); } } + /** + * 不同专业分类下排行榜刷新 + * 注意!!!定时统计任务是在本月月初执行的,而上榜时间是在上个月最后一天23:59:59 + */ + @PostMapping("/refreshViewsRankOfMajor") + public JsonResponse refreshViewsRankOfMajor() { + casesService.refreshViewsRankOfMajor(); + return success(true); + } + + @PostMapping("/refreshLastQuarterStatistics") + public JsonResponse refreshLastQuarterStatistics() { + casesService.refreshLastQuarterStatistics(); + return success(true); + } + + + /** + * 热度榜(当前季度、总榜) 按观看量排行 + * @param pageSize + * @param rankType 1:当前季度,2:总榜 + * @return + */ + @SuppressWarnings("unchecked") + @GetMapping("/queryPopularity") + public JsonResponse> queryPopularity(@RequestParam(required = false) Integer pageSize,@RequestParam Integer rankType) { + List caseRankingVoList =casesService.queryRank(pageSize,rankType); + return success(caseRankingVoList); + } + + + /** + * 好评榜 (当前季度、总榜) 按点赞量排行 + * @param pageSize + * @param rankType + * @return + */ + @SuppressWarnings("unchecked") + @GetMapping("/queryHighOpinion") + public JsonResponse> queryHighOpinion(@RequestParam(required = false) Integer pageSize,@RequestParam Integer rankType) { + List caseRankingVoList =casesService.queryRank(pageSize,rankType); + return success(caseRankingVoList); + } + + /** + * 不同专业月热度榜 按观看量排行 + */ + @SuppressWarnings("unchecked") + @GetMapping("/queryPopularityOfMajor") + public JsonResponse> queryPopularityOfMajor(@RequestParam(required = false) Integer pageSize, + @RequestParam String majorId, + @RequestParam LocalDateTime rankMonth) { + String accountId = getCurrent().getAccountId(); + List caseRankingVoList =casesService.queryPopularityOfMajor(pageSize,majorId,rankMonth,accountId); + return success(caseRankingVoList); + } + + + /** + * 所有上榜的的(专业ID-时间), 用于下拉框.优化可将majorName一并查询,返回为List> todo by anyone + */ + @GetMapping("/queryAllTimePopularityOfMajor") + public JsonResponse>> queryAllTimePopularityOfMajor() { + Map> time = casesService.queryAllTimePopularityOfMajor(); + return success(time); + } + + + /** + * 查询推荐案例榜单 + * @return + */ + @SuppressWarnings("unchecked") + @GetMapping("/queryRecommendRank") + public JsonResponse> queryRecommendRank(@RequestParam(required = false,defaultValue = "3") Integer pageSize) { + List list = casesService.queryRecommendRank(pageSize); + return success(list); + } + + /** + * 案例上榜 + */ + @SuppressWarnings("unchecked") + @PostMapping("/riseIntoRank") + public JsonResponse riseIntoRank(@RequestParam Long caseId) { + casesService.riseIntoRank(caseId,getCurrent()); + return success(true); + } + + /** + * 案例下榜 + */ + @SuppressWarnings("unchecked") + @PostMapping("/cancelRiseIntoRank") + public JsonResponse cancelRiseIntoRank(@RequestParam Long caseId) { + casesService.cancelRiseIntoRank(caseId); + return success(true); + } + + /** + * 推荐案例调整排名 + */ + @SuppressWarnings("unchecked") + @PostMapping("/adjustRank") + public JsonResponse adjustRank(@RequestParam List caseIds) { + casesService.adjustRank(caseIds); + return success(true); + } + + /** + * 查询收藏 + * @param pageIndex + * @param pageSize + * @return + */ + @SuppressWarnings("unchecked") + @GetMapping("/queryFavoriteCaseOfIndex") + public JsonResponse> queryFavoriteCaseOfIndex(@RequestParam(required = false,defaultValue = "1") Integer pageIndex, + @RequestParam(required = false,defaultValue = "5") Integer pageSize) { + String accountId = this.getCurrent().getAccountId(); + PageList casesList = casesService.queryFavoriteCaseOfIndex(pageIndex,pageSize,accountId); + return success(casesList); + } + + @GetMapping("/browsingHistory") + public JsonResponse> browsingHistory(@RequestParam(required = false,defaultValue = "1") Integer pageIndex, + @RequestParam(required = false,defaultValue = "5") Integer pageSize, + HttpServletRequest request) { + String accountId = this.getCurrent().getAccountId(); + PageList casesList = casesService.browsingHistory(pageIndex,pageSize,accountId,request); + return success(casesList); + } + } diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesDao.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesDao.java index 1ffa20db..b4294a9f 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesDao.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesDao.java @@ -1,18 +1,24 @@ package com.xboe.module.boecase.dao; -import java.util.List; - -import org.springframework.stereotype.Repository; - import com.xboe.common.OrderCondition; import com.xboe.common.PageList; import com.xboe.core.orm.BaseDao; +import com.xboe.core.orm.FieldFilters; import com.xboe.core.orm.IFieldFilter; import com.xboe.module.boecase.entity.Cases; -import com.xboe.core.orm.FieldFilters; -import com.xboe.module.boecase.dto.CaseVo; +import com.xboe.module.boecase.vo.CaseRankingVo; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import static com.xboe.enums.CasesRankEnum.*; @Repository +@Slf4j public class CasesDao extends BaseDao { /** @@ -35,4 +41,106 @@ public class CasesDao extends BaseDao { public Cases getByTitle(String title) { return this.getGenericDao().findOne(Cases.class, FieldFilters.eq("title", title)); } + + public HashMap findExcellentCount(List authorIdList) { + String sql = + "SELECT author_id,COUNT(1) AS excellentCount\n" + + "FROM boe_cases \n" + + "WHERE excellent = 1 AND author_id IN (?1) AND deleted=0 \n" + + "GROUP BY author_id"; + List list = this.sqlFindList(sql, authorIdList); + + HashMap map = new HashMap<>(); + + list.forEach(objects -> { + String authorId = objects[0].toString(); + int excellentCount = Integer.parseInt(objects[1].toString()); + map.put(authorId, excellentCount); + }); + + return map; + } + + private List handleCaseRank(List listFields) { + List list = new ArrayList<>(); + for (Object[] o : listFields) { + CaseRankingVo dto = new CaseRankingVo(); + dto.setCaseId(String.valueOf(o[0])); + dto.setCaseTitle((String) o[1]); + list.add(dto); + } + return list; + } + + public List findPopularityOfAll(Integer pageSize) { + + String sql = + "SELECT id,title\n" + + "FROM boe_cases \n" + + "WHERE deleted=0\n" + + "ORDER BY views DESC,sys_create_time DESC\n" + + "LIMIT ?1"; + + List listFields = this.sqlFindList(sql, pageSize); + List caseRankingVoList = handleCaseRank(listFields); + return caseRankingVoList; + } + + public List findPopularityOfQuarter(Integer pageSize) { + String sql = + "SELECT id,title\n" + + "FROM boe_cases \n" + + "WHERE deleted=0\n" + + "ORDER BY (views-last_quarter_views) DESC,sys_create_time DESC \n" + + "LIMIT ?1"; + + List listFields = this.sqlFindList(sql, pageSize); + + List caseRankingVoList = handleCaseRank(listFields); + return caseRankingVoList; + } + + public List findHighOpinionOfAll(Integer pageSize) { + String sql = + "SELECT id,title\n" + + "FROM boe_cases \n" + + "WHERE deleted=0\n" + + "ORDER BY praises DESC,sys_create_time DESC \n" + + "LIMIT ?1"; + List listFields = this.sqlFindList(sql, pageSize); + List caseRankingVoList = handleCaseRank(listFields); + return caseRankingVoList; + } + + + public List findHighOpinionOfQuarter(Integer pageSize) { + String sql = + "SELECT id,title\n" + + "FROM boe_cases \n" + + "WHERE deleted=0\n" + + "ORDER BY (praises-last_quarter_praises) DESC,sys_create_time DESC \n" + + "LIMIT ?1"; + + List listFields = this.sqlFindList(sql, pageSize); + List caseRankingVoList = handleCaseRank(listFields); + return caseRankingVoList; + } + + public List findRank(Integer pageSize, Integer rankType) { + List popularityOfQuarter = Collections.emptyList(); + if (rankType == QUARTER_VIEWS.getType()){ + popularityOfQuarter = findPopularityOfQuarter(pageSize); + } + if (rankType == ALL_VIEWS.getType()){ + popularityOfQuarter = findPopularityOfAll(pageSize); + } + if (rankType == QUARTER_PRAISES.getType()){ + popularityOfQuarter = findHighOpinionOfQuarter(pageSize); + } + if (rankType == ALL_PRAISES.getType()){ + popularityOfQuarter = findHighOpinionOfAll(pageSize); + } + return popularityOfQuarter; + } + } diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesRankDao.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesRankDao.java new file mode 100644 index 00000000..2ad38cb2 --- /dev/null +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesRankDao.java @@ -0,0 +1,87 @@ +package com.xboe.module.boecase.dao; + +import com.xboe.core.orm.BaseDao; +import com.xboe.module.boecase.entity.CasesRank; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Repository; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +@Repository +@Slf4j +public class CasesRankDao extends BaseDao { + + public List findViewsRankRecordByCaseId(String caseId) { + String sql = + "SELECT bdmt.name,bcvr.rise_rank_time,bcvr.rank,bcvr.major_id \n" + + "FROM\n" + + " boe_cases_rank bcvr\n" + + "JOIN boe_dict_major_type bdmt \n" + + " ON bdmt.code = bcvr.major_id \n" + + "WHERE bcvr.case_id = ?1 AND bcvr.deleted=0 AND bdmt.deleted=0\n" + + "ORDER BY bcvr.sys_update_time DESC \n" + + "LIMIT 2;"; + + List list = this.sqlFindList(sql, caseId); + + List resultList = new ArrayList<>(); + for (Object[] o : list) { + CasesRank casesRank = new CasesRank(); + casesRank.setMajorName(o[0].toString()); + casesRank.setRiseRankTime(((Timestamp) o[1]).toLocalDateTime()); + casesRank.setRank(Integer.valueOf(o[2].toString())); + casesRank.setMajorId(o[3].toString()); + resultList.add(casesRank); + } + return resultList; + } + + public HashMap findViewTopCount(List authorIdList) { + String sql= + "SELECT author_id,COUNT(1) as viewTopCount\n" + + "FROM boe_cases bc JOIN boe_cases_rank bcvr ON bcvr.case_id = bc.id\n" + + "WHERE bc.author_id IN (?1) \n" + + " AND bcvr.deleted = 0 \n" + + " AND bc.deleted = 0\n" + + "GROUP BY bc.author_id;"; + List list = this.sqlFindList(sql, authorIdList); + + HashMap map = new HashMap<>(); + + list.forEach(objects -> { + String authorId = objects[0].toString(); + Integer viewTopCount = Integer.parseInt(objects[1].toString()); + map.put(authorId, viewTopCount); + }); + + return map; + } + + + public List> findPopularityOfMajor(Integer pageSize, LocalDateTime startTime, LocalDateTime endTime, String majorId) { + + String sql = + "SELECT bcr.case_id,bcr.rank\n" + + "FROM boe_cases_rank bcr\n" + + "JOIN boe_cases bc on bcr.case_id = bc.id\n" + + "WHERE bcr.deleted=0 AND bc.deleted=0 AND bcr.rise_rank_time BETWEEN ?1 and ?2 AND major_id=?3\n" + + "ORDER BY rank\n" + + "LIMIT ?4"; + + List listFields = this.sqlFindList(sql, startTime, endTime,majorId,pageSize); + + List> collect = listFields.stream().map(item -> { + HashMap map = new HashMap<>(); + map.put("caseId", item[0].toString()); + map.put("rank", item[1].toString()); + return map; + }).collect(Collectors.toList()); + + return collect; + } +} diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesRecordDao.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesRecordDao.java index 65ce714a..7d0ae946 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesRecordDao.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/dao/CasesRecordDao.java @@ -21,50 +21,79 @@ import java.util.List; */ @Repository public interface CasesRecordDao extends JpaRepository, JpaSpecificationExecutor { - @Query(nativeQuery = true, value = "select c.* from ( select b.*" + - " from boe_cases_recommend_push_record a left JOIN boe_cases b on a.case_id = b.id" + - " where b.deleted=0 and a.push_status = 3 and a.deleted=0 and a.push_user_id= :#{#condition.userId}" + - " and if(IFNULL(:#{#condition.keyWord},'')!='',b.title like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.author_name like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.keyword1 like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.keyword2 like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.keyword3 like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.keyword4 like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.keyword5 like CONCAT('%',:#{#condition.keyWord},'%'),1=1)" + - " and if(:#{#condition.yearsEmpty},1=1, YEAR(b.sys_create_time) in (:#{#condition.years}))" + - " and if(:#{#condition.caseIdsEmpty}, 1=1, b.id in (:#{#condition.caseIds}))" + - " and ("+ - " if(:#{#condition.allOrgEmpty}, 1=1, 1=2)" + - " or if(:#{#condition.org1Empty}, 1=2, b.org_domain_parent in (:#{#condition.org1}))" + - " or if(:#{#condition.org2Empty}, 1=2, b.org_domain_parent2 in (:#{#condition.org2}))" + - " or if(:#{#condition.org3Empty}, 1=2, b.org_domain_parent3 in (:#{#condition.org3}))" + - ")" + - " and if(:#{#condition.isSysType1Empty} , 1=1, b.sys_type1 = :#{#condition.sysType1} )"+ - " and if(:#{#condition.isSysType2Empty} , 1=1, b.sys_type2 = :#{#condition.sysType2} )"+ - " and if(:#{#condition.isSysType3Empty} , 1=1, b.sys_type3 = :#{#condition.sysType3} )"+ - " order by a.sys_create_time DESC, a.read_flag ASC) as c group by c.id", - countQuery = "select count(*) FROM (select c.* from ( select b.*" + - " from boe_cases_recommend_push_record a left JOIN boe_cases b on a.case_id = b.id " + - " where b.deleted=0 and a.push_status = 3 and a.deleted=0 and a.push_user_id= :#{#condition.userId}" + - " and if(IFNULL(:#{#condition.keyWord},'')!='',b.title like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.author_name like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.keyword1 like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.keyword2 like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.keyword3 like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.keyword4 like CONCAT('%',:#{#condition.keyWord},'%')" + - " or b.keyword5 like CONCAT('%',:#{#condition.keyWord},'%'),1=1)" + - " and if(:#{#condition.yearsEmpty},1=1, YEAR(b.sys_create_time) in (:#{#condition.years}))" + - " and if(:#{#condition.caseIdsEmpty}, 1=1, b.id in (:#{#condition.caseIds}))" + - " and ("+ - " if(:#{#condition.allOrgEmpty}, 1=1, 1=2)" + - " or if(:#{#condition.org1Empty}, 1=1, b.org_domain_parent in (:#{#condition.org1}))" + - " or if(:#{#condition.org2Empty}, 1=1, b.org_domain_parent2 in (:#{#condition.org2}))" + - " or if(:#{#condition.org3Empty}, 1=1, b.org_domain_parent3 in (:#{#condition.org3}))" + - ")" + - " and if(:#{#condition.isSysType1Empty} , 1=1, b.sys_type1 = :#{#condition.sysType1} )"+ - " and if(:#{#condition.isSysType2Empty} , 1=1, b.sys_type2 = :#{#condition.sysType2} )"+ - " and if(:#{#condition.isSysType3Empty} , 1=1, b.sys_type3 = :#{#condition.sysType3} )"+ - " order by a.sys_create_time DESC, a.read_flag ASC ) as c group by c.id) as d") + @Query(nativeQuery = true, value = + " SELECT c.* FROM ( " + + " SELECT b.*,a.sys_create_time as recommendPushTime" + + " FROM boe_cases_recommend_push_record a " + + " LEFT JOIN boe_cases b ON a.case_id = b.id " + + " WHERE b.deleted = 0 " + + " AND a.push_status = 3 " + + " AND a.deleted = 0 " + + " AND a.push_user_id = :#{#condition.userId} " + + " AND IF(IFNULL(:#{#condition.keyWord}, '') != '', " + + " b.title LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.author_name LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.keyword1 LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.keyword2 LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.keyword3 LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.keyword4 LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.keyword5 LIKE CONCAT('%', :#{#condition.keyWord}, '%'), " + + " 1 = 1) " + + " AND IF(:#{#condition.yearsEmpty}, 1 = 1, YEAR(b.sys_create_time) IN (:#{#condition.years})) " + + " AND IF(:#{#condition.caseIdsEmpty}, 1 = 1, b.id IN (:#{#condition.caseIds})) " + + " AND ( " + + " IF(:#{#condition.allOrgEmpty}, 1 = 1, 1 = 2) " + + " OR IF(:#{#condition.org1Empty}, 1 = 2, b.org_domain_parent IN (:#{#condition.org1})) " + + " OR IF(:#{#condition.org2Empty}, 1 = 2, b.org_domain_parent2 IN (:#{#condition.org2})) " + + " OR IF(:#{#condition.org3Empty}, 1 = 2, b.org_domain_parent3 IN (:#{#condition.org3})) " + + " ) " + + " AND IF(:#{#condition.isSysType1Empty}, 1 = 1, b.sys_type1 = :#{#condition.sysType1}) " + + " AND IF(:#{#condition.isSysType2Empty}, 1 = 1, b.sys_type2 = :#{#condition.sysType2}) " + + " AND IF(:#{#condition.isSysType3Empty}, 1 = 1, b.sys_type3 = :#{#condition.sysType3}) " + + " ) AS c GROUP BY c.id " + + " ORDER BY " + + " IF(:#{#condition.orderField}='views' and :#{#condition.orderAsc}=true,c.views, null) asc," + + " IF(:#{#condition.orderField}='views' and :#{#condition.orderAsc}=false,c.views, null) desc," + + " IF(:#{#condition.orderField}='sysCreateTime' and :#{#condition.orderAsc}=true ,c.sys_create_time,null) asc," + + " IF(:#{#condition.orderField}='sysCreateTime' and :#{#condition.orderAsc}=false , c.sys_create_time,null) desc," + + " IF(:#{#condition.orderField}='recommendPushTime', c.recommendPushTime,null) desc", + countQuery = + " SELECT count(*) FROM ( " + + " SELECT b.*,a.sys_create_time as recommendPushTime" + + " FROM boe_cases_recommend_push_record a " + + " LEFT JOIN boe_cases b ON a.case_id = b.id " + + " WHERE b.deleted = 0 " + + " AND a.push_status = 3 " + + " AND a.deleted = 0 " + + " AND a.push_user_id = :#{#condition.userId} " + + " AND IF(IFNULL(:#{#condition.keyWord}, '') != '', " + + " b.title LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.author_name LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.keyword1 LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.keyword2 LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.keyword3 LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.keyword4 LIKE CONCAT('%', :#{#condition.keyWord}, '%') " + + " OR b.keyword5 LIKE CONCAT('%', :#{#condition.keyWord}, '%'), " + + " 1 = 1) " + + " AND IF(:#{#condition.yearsEmpty}, 1 = 1, YEAR(b.sys_create_time) IN (:#{#condition.years})) " + + " AND IF(:#{#condition.caseIdsEmpty}, 1 = 1, b.id IN (:#{#condition.caseIds})) " + + " AND ( " + + " IF(:#{#condition.allOrgEmpty}, 1 = 1, 1 = 2) " + + " OR IF(:#{#condition.org1Empty}, 1 = 2, b.org_domain_parent IN (:#{#condition.org1})) " + + " OR IF(:#{#condition.org2Empty}, 1 = 2, b.org_domain_parent2 IN (:#{#condition.org2})) " + + " OR IF(:#{#condition.org3Empty}, 1 = 2, b.org_domain_parent3 IN (:#{#condition.org3})) " + + " ) " + + " AND IF(:#{#condition.isSysType1Empty}, 1 = 1, b.sys_type1 = :#{#condition.sysType1}) " + + " AND IF(:#{#condition.isSysType2Empty}, 1 = 1, b.sys_type2 = :#{#condition.sysType2}) " + + " AND IF(:#{#condition.isSysType3Empty}, 1 = 1, b.sys_type3 = :#{#condition.sysType3}) " + + " ) AS c GROUP BY c.id " + + " ORDER BY " + + " IF(:#{#condition.orderField}='views' and :#{#condition.orderAsc}=true,c.views, null) asc," + + " IF(:#{#condition.orderField}='views' and :#{#condition.orderAsc}=false,c.views, null) desc," + + " IF(:#{#condition.orderField}='sysCreateTime' and :#{#condition.orderAsc}=true ,c.sys_create_time,null) asc," + + " IF(:#{#condition.orderField}='sysCreateTime' and :#{#condition.orderAsc}=false , c.sys_create_time,null) desc," + + " IF(:#{#condition.orderField}='recommendPushTime', c.recommendPushTime,null) desc" + ) Page queryList(Pageable pageable, @Param("condition") CasePageVo casePage); diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/Cases.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/Cases.java index 7e933ba8..aa8fd353 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/Cases.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/Cases.java @@ -3,6 +3,7 @@ package com.xboe.module.boecase.entity; import com.fasterxml.jackson.annotation.JsonFormat; import com.xboe.core.SysConstant; import com.xboe.core.orm.BaseEntity; +import com.xboe.module.boecase.vo.CaseViewRankingItemVo; import lombok.Data; import lombok.EqualsAndHashCode; @@ -248,16 +249,7 @@ public class Cases extends BaseEntity { @Column(name = "case_value") private String caseValue; - // 种类字段1 - // 暂不上线 -// @Column(name = "sys_type1") -// private String sysType1; - //种类字段2 -// @Column(name = "sys_type2") -// private String sysType2; - //种类字段3 -// @Column(name = "sys_type3") -// private String sysType3; + /** * 最佳案例标识 @@ -272,6 +264,48 @@ public class Cases extends BaseEntity { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime excellentTime; + /** + * 最佳时间 + * */ + @Column(name = "excellent_reason") + private String excellentReason; + + /** + * 上月浏览量 + */ + @Column(name = "last_month_views") + private Integer lastMonthViews; + + /** + * 上季度浏览量 + */ + @Column(name = "last_quarter_views") + private Integer lastQuarterViews; + + /** + * 上季度点赞量 + */ + @Column(name = "last_quarter_praises") + private Integer lastQuarterPraises; + + /** + * 推荐榜排序 + * */ + @Column(name = "recommend_rank") + private Integer recommendRank; + + /** + * 推送用户名称 + */ + @Column(name = "recommend_rank_push_user_name") + private String recommendRankPushUserName; + + /** + * 推送时间 + */ + @Column(name = "recommend_rank_push_time") + private LocalDateTime recommendRankPushTime; + /** * type 种类 * 区分 案例/推荐案例 @@ -279,11 +313,6 @@ public class Cases extends BaseEntity { @Transient private String type; - /** - * id - */ - - @Transient private List majorIds; @@ -296,6 +325,15 @@ public class Cases extends BaseEntity { @Transient private String refId; + @Transient + private String excellentTag; + + @Transient + private List viewRankTags; + + @Transient + private List authorTags; + public String getRefId() { return refId; } @@ -380,7 +418,7 @@ public class Cases extends BaseEntity { this.title=title; } public Cases(String id,String title,String summary,String coverUrl,String authorId,String authorName,LocalDateTime sysCreateTime,Integer breCommend,Integer views,Integer comments,Integer praises,Integer shares,Integer favorites,Boolean deleted - ,String sysCreateBy,String sysCreateAid){ + ,String sysCreateBy,String sysCreateAid){ this.title=title; super.setId(id); this.authorId=authorId; @@ -398,7 +436,6 @@ public class Cases extends BaseEntity { this.favorites=favorites; super.setDeleted(deleted); } - public Cases(String title) { this.title = title; } @@ -415,4 +452,29 @@ public class Cases extends BaseEntity { this.authorName = authorName; this.confidentialityLevel = confidentialityLevel; } + + public Cases(String id,String title,String summary,String coverUrl,String authorId,String authorName,LocalDateTime sysCreateTime,Integer breCommend,Integer views,Integer comments,Integer praises,Integer shares,Integer favorites,Boolean deleted + ,String sysCreateBy,String sysCreateAid,String keyword1,String keyword2,String keyword3,String keyword4,String keyword5){ + this.title=title; + super.setId(id); + this.authorId=authorId; + this.authorName=authorName; + super.setSysCreateTime(sysCreateTime); + super.setSysCreateAid(sysCreateAid); + super.setSysCreateBy(sysCreateBy); + this.summary=summary; + this.coverUrl=coverUrl; + this.breCommend=breCommend; + this.views=views; + this.comments=comments; + this.praises=praises; + this.shares=shares; + this.favorites=favorites; + this.keyword1=keyword1; + this.keyword2=keyword2; + this.keyword3=keyword3; + this.keyword4=keyword4; + this.keyword5=keyword5; + super.setDeleted(deleted); + } } diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/CasesRank.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/CasesRank.java new file mode 100644 index 00000000..0d3a3cfc --- /dev/null +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/CasesRank.java @@ -0,0 +1,61 @@ +package com.xboe.module.boecase.entity; + +import com.xboe.core.SysConstant; +import com.xboe.core.orm.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.time.LocalDateTime; + +/** +* 案例推荐表 +* @TableName boe_cases_rank +*/ +@Data +@NoArgsConstructor +@Entity +@EqualsAndHashCode(callSuper = false) +@Table(name = SysConstant.TABLE_PRE+"cases_rank") +public class CasesRank extends BaseEntity { + + /** + * 案例ID + */ + @Column(name = "case_id") + private Long caseId; + + /** + * 专业ID + */ + @Column(name = "major_id") + private String majorId; + + /** + * 排名 + */ + @Column(name = "rank") + private Integer rank; + + /** + * 浏览量每月增量 + */ + @Column(name = "monthly_increment") + private Integer monthlyIncrement; + + + @Column(name = "rise_rank_time") + private LocalDateTime riseRankTime; + + @Transient + private String majorName; + + public CasesRank(String majorId, LocalDateTime riseRankTime) { + this.majorId = majorId; + this.riseRankTime = riseRankTime; + } +} diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/CasesRecommend.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/CasesRecommend.java index 69ac0a5a..25dbcfdd 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/CasesRecommend.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/entity/CasesRecommend.java @@ -54,8 +54,15 @@ public class CasesRecommend extends BaseEntity { public CasesRecommend() { } + public CasesRecommend(String id, String recommendOrgName) { this.setId(id); this.recommendOrgName = recommendOrgName; } + + public CasesRecommend(String id, String recommendOrgName,LocalDateTime recommendTime) { + this.setId(id); + this.recommendOrgName = recommendOrgName; + this.recommendTime = recommendTime; + } } diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/ICasesService.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/ICasesService.java index 151af48b..b114932e 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/ICasesService.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/ICasesService.java @@ -1,14 +1,22 @@ package com.xboe.module.boecase.service; -import java.util.List; - import com.xboe.common.PageList; import com.xboe.core.CurrentUser; import com.xboe.module.boecase.dto.*; import com.xboe.module.boecase.entity.Cases; +import com.xboe.module.boecase.vo.CasesBrowsingHistoryVo; +import com.xboe.module.boecase.vo.CaseRankingVo; +import com.xboe.module.boecase.vo.CasesQueryRecommendRankVo; +import com.xboe.module.boecase.vo.FavoriteCaseOfIndexVo; import com.xboe.module.dict.entity.DictItem; import com.xboe.school.vo.CasesVo; +import javax.servlet.http.HttpServletRequest; +import javax.transaction.Transactional; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + public interface ICasesService{ /** * 案例分页搜索,是否被推荐 @@ -91,7 +99,7 @@ public interface ICasesService{ /** * 用于二次查询 * */ - List ids(List ids); + List ids(List ids, String accountId); /** *二期 首页的推荐案例 @@ -101,7 +109,7 @@ public interface ICasesService{ /** * 设置或者取消优秀案例 * */ - void excellent(String id,Boolean excellent); + void excellent(String id, Boolean excellent, String excellentReason); PageList queryRecommendPageCasesV2(CasePageVo req); @@ -110,5 +118,27 @@ public interface ICasesService{ List getCaseYears(); + @Transactional + void refreshViewsRankOfMajor(); + + void refreshLastQuarterStatistics(); + + List queryRecommendRank(Integer pageSize); + + void riseIntoRank(Long caseId, CurrentUser currentUser); + + void cancelRiseIntoRank(Long caseId); + + void adjustRank(List caseIdList); + + List queryRank(Integer pageSize, Integer rankType); + + List queryPopularityOfMajor(Integer pageSize, String majorId, LocalDateTime month, String accountId); + + PageList queryFavoriteCaseOfIndex(Integer pageIndex, Integer pageSize, String accountId); + + PageList browsingHistory(Integer pageIndex, Integer pageSize, String accountId, HttpServletRequest request); + + Map> queryAllTimePopularityOfMajor(); } diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CasesServiceImpl.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CasesServiceImpl.java index c546e399..c723fe8f 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CasesServiceImpl.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CasesServiceImpl.java @@ -2,8 +2,14 @@ package com.xboe.module.boecase.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.xboe.api.ThirdApi; +import com.xboe.api.vo.UserDynamic; +import com.xboe.api.vo.UserDynamicResult; +import com.xboe.api.vo.UserdynamicParam; import com.xboe.common.OrderCondition; import com.xboe.common.OrderDirection; import com.xboe.common.PageList; @@ -11,29 +17,40 @@ import com.xboe.common.utils.IDGenerator; import com.xboe.common.utils.StringUtil; import com.xboe.core.CurrentUser; import com.xboe.core.orm.*; +import com.xboe.enums.CasesRankEnum; import com.xboe.module.boecase.dao.*; import com.xboe.module.boecase.dto.*; -import com.xboe.module.boecase.entity.Cases; -import com.xboe.module.boecase.entity.CasesMajorType; -import com.xboe.module.boecase.entity.CasesRecommend; -import com.xboe.module.boecase.entity.CasesRecommendPushRecord; +import com.xboe.module.boecase.entity.*; import com.xboe.module.boecase.service.ICasesService; +import com.xboe.module.boecase.vo.*; import com.xboe.module.dict.dao.SysDictionaryDao; import com.xboe.module.dict.entity.DictItem; +import com.xboe.module.interaction.entity.Favorites; import com.xboe.orm.CustomFieldInFilter; import com.xboe.school.vo.CasesVo; +import com.xboe.standard.enums.BoedxResourceType; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; -import javax.transaction.Transactional; +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Array; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAdjusters; import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import java.util.stream.IntStream; + @Slf4j @Service @@ -61,6 +78,15 @@ public class CasesServiceImpl implements ICasesService { @Autowired private CasesRecommendDao casesRecommendDao; + @Resource + private CasesRankDao casesRankDao; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + @Resource + private ThirdApi thirdApi; + /** * 案例分页查询,用于门户的查询 */ @@ -178,12 +204,6 @@ public class CasesServiceImpl implements ICasesService { @Override public PageList queryPageCasesV2(CasePageVo caseVo) { - String type = caseVo.getType(); - if (!StrUtil.equals(type,"excellent")) { - caseVo.setOrderField(""); - caseVo.setOrderAsc(null); - } - String keyword = caseVo.getKeyWord(); QueryBuilder query = QueryBuilder.from(Cases.class); PageList page = null; @@ -296,18 +316,16 @@ public class CasesServiceImpl implements ICasesService { filters.add(FieldFilters.eq("excellent", caseVo.getExcellent())); } OrderCondition order = null; - if (StringUtils.isNotBlank(caseVo.getOrderField())) { - if (caseVo.getOrderAsc() == null || caseVo.getOrderAsc()) { + if (StringUtils.isNotBlank(caseVo.getOrderField()) && caseVo.getOrderAsc() != null && ("sysCreateTime".equals(caseVo.getOrderField()) || "views".equals(caseVo.getOrderField()))) { + if (caseVo.getOrderAsc()) { order = OrderCondition.asc(caseVo.getOrderField()); } else { order = OrderCondition.desc(caseVo.getOrderField()); } - } - if (StrUtil.equals(type,"new")) { + } else { order = OrderCondition.desc("sysCreateTime"); - } else if (StrUtil.equals(type,"hot")) { - order = OrderCondition.desc("views"); } + if(Objects.nonNull(order)) { query.addOrder(order); } @@ -315,53 +333,18 @@ public class CasesServiceImpl implements ICasesService { query.setPageIndex(caseVo.getPageIndex()); query.setPageSize(caseVo.getPageSize()); page = casesDao.findPage(query.builder()); - List list = page.getList(); - list.forEach(it->{ + List casesList = page.getList(); + casesList.forEach(it->{ it.setBreCommend(0); }); - if (CollUtil.isNotEmpty(list) && StrUtil.isNotBlank(caseVo.getUserId())) { - List caseIds = list.stream().map(Cases::getId).collect(Collectors.toList()); - QueryBuilder recommendCasesQuery = QueryBuilder.from(CasesRecommendPushRecord.class); - recommendCasesQuery.addField("new CasesRecommendPushRecord(id,recommendId,caseId)"); - List subFilters = new ArrayList<>(); - subFilters.add(FieldFilters.eq("pushUserId", caseVo.getUserId())); - subFilters.add(FieldFilters.in("caseId", caseIds)); - subFilters.add(FieldFilters.eq("pushStatus", 3)); - subFilters.add(FieldFilters.eq("deleted", Boolean.FALSE)); - - QueryBuilder queryBuilder = recommendCasesQuery.addFilters(subFilters) - .addOrder("sysCreateTime", OrderDirection.DESC) - .addGroupBy("caseId"); - List pushRecords = casesRecommendPushRecordDao.findList(queryBuilder.builder()); - if (CollUtil.isNotEmpty(pushRecords)) { - List rIds = pushRecords.stream().map(CasesRecommendPushRecord::getRecommendId).distinct().collect(Collectors.toList()); - QueryBuilder builder = QueryBuilder.from(CasesRecommend.class); - builder.addField("new CasesRecommend(id,recommendOrgName)"); - List recommendFilters = new ArrayList<>(); - recommendFilters.add(FieldFilters.eq("deleted", Boolean.FALSE)); - recommendFilters.add(FieldFilters.in("id", rIds)); - builder.addFilters(recommendFilters); - List recommands = casesRecommendDao.findList(builder.builder()); - if (CollUtil.isNotEmpty(recommands)) { - Map collect = recommands.stream().collect(Collectors.toMap(k -> k.getId(), v -> v.getRecommendOrgName())); - list.forEach(it -> { - CasesRecommendPushRecord one = CollUtil.findOne(pushRecords, (a) -> StrUtil.equals(a.getCaseId(), it.getId())); - if (Objects.nonNull(one)) { - String recommendOrgName = collect.get(one.getRecommendId()); - it.setBreCommend(1); - it.setRecommendOrgName(recommendOrgName); - } else { - it.setBreCommend(0); - } - }); - } - } - - } + casesList = caseListCommonHandle(casesList, caseVo.getUserId()); + page.setList(casesList); return page; } + + @Override public PageList queryRecommendPageCasesV2(CasePageVo caseVo) { @@ -408,37 +391,68 @@ public class CasesServiceImpl implements ICasesService { caseVo.setOrg2(level2); caseVo.setOrg3(level3); + Set validOrderFields = new HashSet<>(); + validOrderFields.add("sysCreateTime"); + validOrderFields.add("views"); + validOrderFields.add("recommendPushTime"); + if (StringUtils.isBlank(caseVo.getOrderField()) || caseVo.getOrderAsc() == null || !validOrderFields.contains(caseVo.getOrderField())) { + caseVo.setOrderField("recommendPushTime"); + caseVo.setOrderAsc(false); + } + Page cases = casesRecordDao.queryList(pageRequest,caseVo); PageList pageList = new PageList<>(); pageList.setCount((int) cases.getTotalElements()); pageList.setPageSize(cases.getSize()); List content = cases.getContent(); - List caseIds = content.stream().map(Cases::getId).collect(Collectors.toList()); - String userId = caseVo.getUserId(); - if (CollUtil.isNotEmpty(caseIds)) { - QueryBuilder recommendCasesQuery = QueryBuilder.from(CasesRecommendPushRecord.class); - recommendCasesQuery.addField("new CasesRecommendPushRecord(id,recommendId,caseId)"); - List subFilters = new ArrayList<>(); - subFilters.add(FieldFilters.eq("pushUserId", userId)); - subFilters.add(FieldFilters.in("caseId", caseIds)); - subFilters.add(FieldFilters.eq("pushStatus", 3)); - subFilters.add(FieldFilters.eq("deleted", Boolean.FALSE)); - QueryBuilder queryBuilder = recommendCasesQuery.addFilters(subFilters) + caseListCommonHandle(content, caseVo.getUserId()); + + pageList.setList(content); + return pageList; + } + + private List caseListCommonHandle(List casesList, String accountId) { + if (CollUtil.isEmpty(casesList)) { + return casesList; + } + //1.推荐案例数据处理 + recommendCasesDataHandle(casesList, accountId); + //2.标签处理,添加作者标签和新的案例标签 + addAuthorTagAndCaseNewTag(casesList); + + return casesList; + } + + private void recommendCasesDataHandle(List casesList, String accountId) { + if (StrUtil.isNotBlank(accountId)) { + List caseIdList = casesList.stream().map(Cases::getId).collect(Collectors.toList()); + QueryBuilder queryBuilder = QueryBuilder.from(CasesRecommendPushRecord.class) + .addField("new CasesRecommendPushRecord(id,recommendId,caseId)") + .addFilters(Arrays.asList( + FieldFilters.eq("pushUserId", accountId), + FieldFilters.in("caseId", caseIdList), + FieldFilters.eq("pushStatus", 3), + FieldFilters.eq("deleted", Boolean.FALSE) + )) .addOrder("sysCreateTime", OrderDirection.DESC) .addGroupBy("caseId"); + List pushRecords = casesRecommendPushRecordDao.findList(queryBuilder.builder()); + if (CollUtil.isNotEmpty(pushRecords)) { List rIds = pushRecords.stream().map(CasesRecommendPushRecord::getRecommendId).distinct().collect(Collectors.toList()); - QueryBuilder builder = QueryBuilder.from(CasesRecommend.class); - List recommendFilters = new ArrayList<>(); - recommendFilters.add(FieldFilters.eq("deleted", Boolean.FALSE)); - recommendFilters.add(FieldFilters.in("id", rIds)); - builder.addFilters(recommendFilters); + QueryBuilder builder = QueryBuilder.from(CasesRecommend.class) + .addField("new CasesRecommend(id,recommendOrgName,recommendTime)") + .addFilters(Arrays.asList( + FieldFilters.eq("deleted", Boolean.FALSE), + FieldFilters.in("id", rIds) + )); + List recommands = casesRecommendDao.findList(builder.builder()); if (CollUtil.isNotEmpty(recommands)) { - Map collect = recommands.stream().collect(Collectors.toMap(k -> k.getId(), item->item)); - content.forEach(it -> { + Map collect = recommands.stream().collect(Collectors.toMap(k -> k.getId(), item -> item)); + casesList.forEach(it -> { CasesRecommendPushRecord one = CollUtil.findOne(pushRecords, (a) -> StrUtil.equals(a.getCaseId(), it.getId())); if (Objects.nonNull(one)) { CasesRecommend recommend = collect.get(one.getRecommendId()); @@ -446,13 +460,76 @@ public class CasesServiceImpl implements ICasesService { it.setRefId(one.getId()); it.setRecommendOrgName(recommend.getRecommendOrgName()); it.setSysCreateTime(recommend.getRecommendTime()); + } else { + it.setBreCommend(0); } }); } } } - pageList.setList(content); - return pageList; + } + + /** + * 添加案例标签、作者标签(最佳案例N篇、上榜浏览量TOP榜单N次)、案例标签(xx分类浏览量TOP、最佳案例) + */ + private void addAuthorTagAndCaseNewTag(List caseList) { + if (CollUtil.isEmpty(caseList)) { + return; + } + + List authorIdList = caseList.stream().map(Cases::getAuthorId).distinct().collect(Collectors.toList()); + HashMap excellentCountMap = casesDao.findExcellentCount(authorIdList); + HashMap viewTopCountMap = casesRankDao.findViewTopCount(authorIdList); + + + caseList.forEach(e -> { + // 获取最新的两个浏览量上榜记录 + List viewsRankRecords = casesRankDao.findViewsRankRecordByCaseId(e.getId()); + if (CollUtil.isNotEmpty(viewsRankRecords)) { + // 拼接生成浏览量排行榜的标签 + List viewRankTags = viewsRankRecords.stream().map(casesRank -> { + String pattern = casesRank.getRiseRankTime().getMonthValue() < 10 ? "yy年M月" : "yy年MM月"; + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); + String time = casesRank.getRiseRankTime().format(formatter); + + // 2023年6月 经营管理类 浏览量 TOP1 + String viewRankTag = time + casesRank.getMajorName() + "类浏览量TOP" + (casesRank.getRank() + 1); + + CaseViewRankingItemVo caseViewRankingItemVo = new CaseViewRankingItemVo(); + caseViewRankingItemVo.setMajorId(String.valueOf(casesRank.getMajorId())); + caseViewRankingItemVo.setMajorName(casesRank.getMajorName()); + caseViewRankingItemVo.setTagName(viewRankTag); + caseViewRankingItemVo.setRiseRankTime(casesRank.getRiseRankTime()); + + return caseViewRankingItemVo; + }).collect(Collectors.toList()); + e.setViewRankTags(viewRankTags); + + } + + // 拼接生成年度最佳标签 + if (e.getExcellent()!=null && e.getExcellent()) { + if (e.getDraftingTime()!=null){ + e.setExcellentTag(e.getDraftingTime().format(DateTimeFormatter.ofPattern("yy年"))+"度最佳"); + } else { + e.setExcellentTag(e.getSysCreateTime().format(DateTimeFormatter.ofPattern("yy年"))+"度最佳"); + } + } + + List authorTags = new ArrayList<>(); + + if (excellentCountMap.get(e.getAuthorId())!=null){ + String authorTagOfExcellent = excellentCountMap.get(e.getAuthorId()) + "篇最佳案例"; + authorTags.add(authorTagOfExcellent); + } + + if (viewTopCountMap.get(e.getAuthorId())!=null){ + String authorTagOfView = "上榜浏览量TOP榜单" + viewTopCountMap.get(e.getAuthorId()) + "次"; + authorTags.add(authorTagOfView); + } + + e.setAuthorTags(authorTags); + }); } public static void main(String[] args) { @@ -945,11 +1022,12 @@ public class CasesServiceImpl implements ICasesService { } @Override - public List ids(List ids) { + public List ids(List ids, String accountId) { QueryBuilder builder = QueryBuilder.from(Cases.class); builder.addFilter(FieldFilters.in("id", ids)); - builder.addFields("new Cases(id,title,summary,coverUrl,authorId,authorName,sysCreateTime,breCommend,views,comments,praises,shares,favorites,deleted,sysCreateBy,sysCreateAid)"); + builder.addFields("new Cases(id,title,summary,coverUrl,authorId,authorName,sysCreateTime,breCommend,views,comments,praises,shares,favorites,deleted,sysCreateBy,sysCreateAid,keyword1,keyword2,keyword3,keyword4,keyword5)"); List cases = casesDao.findList(builder.builder()); + cases = caseListCommonHandle(cases, accountId); return cases; } @@ -1078,15 +1156,362 @@ public class CasesServiceImpl implements ICasesService { } @Override - public void excellent(String id, Boolean excellent) { + public void excellent(String id, Boolean excellent, String excellentReason) { //取消时,把时间清空 if (excellent) { - casesDao.updateMultiFieldById(id, UpdateBuilder.create("excellent", excellent), UpdateBuilder.create("excellentTime", LocalDateTime.now())); + casesDao.updateMultiFieldById(id, UpdateBuilder.create("excellent", excellent), UpdateBuilder.create("excellentTime", LocalDateTime.now()), UpdateBuilder.create("excellentReason", excellentReason)); } else { - casesDao.updateMultiFieldById(id, UpdateBuilder.create("excellent", excellent), UpdateBuilder.create("excellentTime", null)); + casesDao.updateMultiFieldById(id, UpdateBuilder.create("excellent", excellent), UpdateBuilder.create("excellentTime", null), UpdateBuilder.create("excellentReason", null)); } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void refreshViewsRankOfMajor(){ + log.info("开始执行每月案例浏览量相关定时任务"); + // 获取上个月的第一天的00:00 +// LocalDateTime firstDayOfLastMonth = LocalDateTime.now().minusMonths(1).with(TemporalAdjusters.firstDayOfMonth()).toLocalDate().atStartOfDay(); + // 获取上个月的最后一天的23:59:59,将其设置为上榜时间。注意,定时统计任务是在本月月初执行的,而上榜时间是在上个月最后一天23:59:59 + LocalDateTime lastDayOfLastMonth = LocalDateTime.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).toLocalDate().atTime(23, 59, 59); // 设置为当天的几乎结束时刻 + + int count = casesRankDao.sqlCount("SELECT count(1) FROM boe_cases_rank WHERE deleted=0 AND rise_rank_time = ?1" , lastDayOfLastMonth); + if (count > 0){ + log.info("已生成上个月排行榜数据,本次不执行"); + throw new RuntimeException("已生成上个月排行榜数据,请将上月排行榜数据删除"); + } + + //获取案例当月排名 +// String sql = +// "SELECT bc.id,bcmt.major_id,bc.views - COALESCE(bc.last_month_views, 0) AS increment\n" + +// "FROM boe_cases bc\n" + +// "JOIN boe_cases_major_type bcmt ON bcmt.case_id = bc.id and bc.deleted=0 and file_path is not null and file_path!='' and bc.views - COALESCE(bc.last_month_views, 0)!=0"; + + String sql = + "SELECT bc.id,bcmt.major_id,bc.views AS increment\n" + + "FROM boe_cases bc\n" + + "JOIN boe_cases_major_type bcmt ON bcmt.case_id = bc.id and bc.deleted=0 and file_path is not null and file_path!='' and bc.views !=0 and bc.views is not null"; + + List caseListOfObject = casesDao.sqlFindList(sql); + + // 转为casesRank + List casesRankList = caseListOfObject.stream() + .map(o -> { + CasesRank casesRank = new CasesRank(); + casesRank.setCaseId(Long.valueOf(Array.get(o, 0).toString())); + casesRank.setMajorId(Array.get(o, 1).toString()); + casesRank.setMonthlyIncrement(Integer.parseInt(Array.get(o, 2).toString())); + casesRank.setRiseRankTime(lastDayOfLastMonth); + return casesRank; + }).collect(Collectors.toList()); + // 根据专业分类进行分组 + Map> casesRankMap = casesRankList.stream().collect(Collectors.groupingBy(CasesRank::getMajorId)); + + // 生成当前月不同分类的最新的浏览量排名 + ArrayList lastMonthRank = new ArrayList<>(); + casesRankMap.forEach((majorId, caseList) -> { + List sortedCaseList = caseList.stream() + .sorted(Comparator.comparingInt(CasesRank::getMonthlyIncrement).reversed()).limit(10) + .collect(Collectors.toList()); + + IntStream.range(0, sortedCaseList.size()) + .forEach(i -> sortedCaseList.get(i).setRank(i)); + lastMonthRank.addAll(sortedCaseList); + }); + + + casesRankDao.saveList(lastMonthRank); + // 重置上月观看量:last_month_views + int i = casesDao.sqlUpdate("update boe_cases set last_month_views=views where deleted=0"); + log.info("每月案例浏览量相关定时任务执行完成,boe_cases更新数据量为条数为"+i); + log.info("每月案例浏览量相关定时任务执行完成,boe_cases_rank添加数据量为条数为"+lastMonthRank.size()); } + @Override + public void refreshLastQuarterStatistics() { + log.info("开始执行每季案例相关定时任务"); + int i = casesDao.sqlUpdate("update boe_cases set last_quarter_views=views,last_quarter_praise=praise where deleted=0"); + log.info("每季案例相关定时任务执行完成,boe_cases更新数据量为条数为"+i); + } + + @Override + public List queryRank(Integer pageSize, Integer rankType) { + if (pageSize == null) { + pageSize = 3; + } + String cacheKey = ""; + // 获取缓存key + for (CasesRankEnum enumValue : CasesRankEnum.values()) { + if (rankType == enumValue.getType()) { + // 格式如:case:rank:praise:all3 + cacheKey = enumValue.getCacheKey()+pageSize; + } + } + + List caseListOfJson = stringRedisTemplate.opsForList().range(cacheKey, 0, -1); + + if (CollectionUtil.isNotEmpty(caseListOfJson)) { + // 缓存中存在数据 + List casesList = caseListOfJson.stream().map(item -> JSONUtil.toBean(item, CaseRankingVo.class)).collect(Collectors.toList()); + return casesList; + } + + List casesList = casesDao.findRank(pageSize,rankType); + + if (CollectionUtil.isNotEmpty(casesList)) { + // 缓存不存在数据,数据库中不存在数据,重建缓存 + List serializedCases = casesList.stream().map(item -> JSONUtil.toJsonStr(item)).collect(Collectors.toList()); + stringRedisTemplate.opsForList().rightPushAll(cacheKey, serializedCases); + stringRedisTemplate.expire(cacheKey, 600, TimeUnit.SECONDS); + return casesList; + } + return Collections.emptyList(); + + } + + + @Override + public List queryPopularityOfMajor(Integer pageSize, String majorId, LocalDateTime month, String accountId) { + if (pageSize == null) { + pageSize = 10; + } + + LocalDateTime startTime = month.withDayOfMonth(1); + LocalDateTime endTime = month.plusMonths(1).withDayOfMonth(1).withMinute(0); + + List> popularityOfMajor = casesRankDao.findPopularityOfMajor(pageSize, startTime, endTime, majorId); + List caseIdList = popularityOfMajor.stream().map(map -> map.get("caseId").toString()).collect(Collectors.toList()); + + Map collect = popularityOfMajor.stream().collect(Collectors.toMap(map -> map.get("caseId").toString(), map -> Integer.valueOf(map.get("rank").toString()))); + + QueryBuilder query = QueryBuilder.from(Cases.class); + query.addFilter(FieldFilters.in("id",caseIdList)); + query.addFilter(FieldFilters.eq("deleted",false)); + + List casesList = casesDao.findList(query.builder()); + casesList = caseListCommonHandle(casesList, accountId); + + Collections.sort(casesList, new Comparator() { + @Override + public int compare(Cases c1, Cases c2) { + Integer order1 = collect.get(c1.getId()); + Integer order2 = collect.get(c2.getId()); + return Integer.compare(order1, order2); + } + }); + return casesList; + } + + + + @Override + public List queryRecommendRank(Integer pageSize) { + QueryBuilder queryBuilder = QueryBuilder.from(Cases.class); + queryBuilder.setPageSize(pageSize); + queryBuilder.addFilter(FieldFilters.eq("deleted",false)); + queryBuilder.addFilter(FieldFilters.isNotNull("recommend_rank")); + queryBuilder.addOrder(OrderCondition.asc("recommend_rank")); + + List recommendRank = casesDao.findList(queryBuilder.builder()); + + List collect = recommendRank.stream().map(e -> { + CasesQueryRecommendRankVo casesQueryRecommendRankVo = new CasesQueryRecommendRankVo(); + casesQueryRecommendRankVo.setCaseId(e.getId()); + casesQueryRecommendRankVo.setCaseTitle(e.getTitle()); + casesQueryRecommendRankVo.setCaseAuthor(e.getAuthorName()); + casesQueryRecommendRankVo.setRecommendRankPushUserName(e.getRecommendRankPushUserName()); + casesQueryRecommendRankVo.setRecommendRankPusTime(e.getRecommendRankPushTime()); + return casesQueryRecommendRankVo; + }).collect(Collectors.toList()); + return collect; + } + + @Override + public void riseIntoRank(Long caseId, CurrentUser currentUser) { + Cases caseOfNewRise = casesDao.findOne(FieldFilters.eq("id", String.valueOf(caseId)),FieldFilters.isNull("recommend_rank"),FieldFilters.eq("deleted",false)); + if (caseOfNewRise == null) { + log.error("案例不存在或已经在榜,不可上榜", caseId); + return; + } + + int count = casesDao.sqlCount("select count(1) from boe_cases where deleted=0 and recommend_rank is not null order by recommend_rank asc limit 10"); + + if (count == 10){ + log.error("已满10条,无法添加"); + throw new RuntimeException("已满10条,无法添加"); + } + + caseOfNewRise.setRecommendRank(count); + caseOfNewRise.setRecommendRankPushUserName(currentUser.getLoginName()); + caseOfNewRise.setRecommendRankPushTime(LocalDateTime.now()); + + casesDao.update(caseOfNewRise); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void cancelRiseIntoRank(Long caseId) { + Cases caseOfCancelRise = casesDao.findOne(FieldFilters.eq("id", String.valueOf(caseId)),FieldFilters.isNotNull("recommend_rank"),FieldFilters.eq("deleted",false)); + if (caseOfCancelRise == null) { + log.error("案例不存在或已经在榜,不可下榜", caseId); + return; + } + QueryBuilder queryBuilder = QueryBuilder.from(Cases.class); + queryBuilder.setPageSize(10); + queryBuilder.addFilter(FieldFilters.eq("deleted",false)); + queryBuilder.addOrder(OrderCondition.asc("recommend_rank")); + queryBuilder.addFilter(FieldFilters.gt("recommend_rank",caseOfCancelRise.getRecommendRank())); + List recommendRank = casesDao.findList(queryBuilder.builder()); + + if (CollectionUtils.isEmpty(recommendRank)){ + // 更新排序 + for (int i = 0; i < recommendRank.size(); i++){ + Integer currentSort = recommendRank.get(i).getRecommendRank(); + recommendRank.get(i).setRecommendRank(currentSort - 1); + casesDao.update(recommendRank.get(i)); + } + } + + // 取消排序 + caseOfCancelRise.setRecommendRank(null); + caseOfCancelRise.setRecommendRankPushTime(null); + caseOfCancelRise.setRecommendRankPushUserName(null); + casesDao.update(caseOfCancelRise); + } + + @Override + public void adjustRank(List caseIdList) { + QueryBuilder queryBuilder = QueryBuilder.from(Cases.class); + queryBuilder.setPageSize(10); + queryBuilder.addFilter(FieldFilters.eq("deleted",false)); + queryBuilder.addFilter(FieldFilters.isNotNull("recommend_rank")); + queryBuilder.addOrder(OrderCondition.asc("recommend_rank")); + List recommendRank = casesDao.findList(queryBuilder.builder()); + + // 遍历排序后的案例列表,并根据 caseIdList 设置或重置 recommendRank + recommendRank.forEach(caseItem -> { + int index = caseIdList.indexOf(Long.valueOf(caseItem.getId())); + // 如果 ID 存在于 caseIdList 中,则设置推荐等级为该 ID 的索引位置,否则设置为 null + if (index != -1) { + caseItem.setRecommendRank(index); + } else { + caseItem.setRecommendRank(null); + caseItem.setRecommendRankPushTime(null); + caseItem.setRecommendRankPushUserName(null); + } + }); + + // 保存对案例排序的更改 + recommendRank.forEach(casesDao::update); + } + + @Override + public PageList queryFavoriteCaseOfIndex(Integer pageIndex, Integer pageSize, String accountId) { + String from = Favorites.class.getSimpleName()+" f,"+ Cases.class.getSimpleName()+" c"; + QueryBuilder builder = QueryBuilder.from(from); + builder.addFields("f.id","f.sysCreateTime","c"); + + builder.addFilter(FieldFilters.eqField("f.objId","c.id")); + builder.addFilter(FieldFilters.eq("f.objType", BoedxResourceType.Case.value())); + builder.addFilter(FieldFilters.eq("f.sysCreateAid",accountId)); + builder.addFilter(FieldFilters.eq("c.deleted", false)); + builder.addOrder(OrderCondition.desc("f.sysCreateTime")); + + builder.setPageIndex(pageIndex); + builder.setPageSize(pageSize); + + PageList pageFields=null; + try { + pageFields = casesDao.findPageFields(builder.builder()); + } catch (Exception e) { + log.error("收藏案例查询错误",e); + } + + List list = pageFields.getList(); + + // 提取出 Cases 对象,添加标签 + List casesList = list.stream().map(o -> { + Cases cases = (Cases) o[2]; + FavoriteCaseOfIndexVo favoriteCaseOfIndexVo = new FavoriteCaseOfIndexVo(); + BeanUtils.copyProperties(cases, favoriteCaseOfIndexVo); + favoriteCaseOfIndexVo.setFavoriteId(o[0].toString()); + favoriteCaseOfIndexVo.setFavoriteTime(LocalDateTime.parse(o[1].toString())); + return favoriteCaseOfIndexVo; + }).collect(Collectors.toList()); + + casesList = caseListCommonHandle(casesList, accountId); + + List collect = casesList.stream().map(cases -> (FavoriteCaseOfIndexVo) cases).collect(Collectors.toList()); + + PageList favoriteCaseOfIndexVoPageList = new PageList<>(); + favoriteCaseOfIndexVoPageList.setList(collect); + favoriteCaseOfIndexVoPageList.setPageSize(pageSize); + favoriteCaseOfIndexVoPageList.setCount(pageFields.getCount()); + + return favoriteCaseOfIndexVoPageList; + + } + + @Override + public PageList browsingHistory(Integer pageIndex, Integer pageSize, String accountId, HttpServletRequest request) { + UserdynamicParam userdynamicParam = new UserdynamicParam(); + userdynamicParam.setPageIndex(pageIndex); + userdynamicParam.setPageSize(pageSize); + userdynamicParam.setContentType(3); + userdynamicParam.setAid(Long.valueOf(accountId)); + userdynamicParam.setHidden(""); + + String token = request.getHeader("Xboe-Access-Token"); + if (StringUtils.isEmpty(token)) { + token = request.getHeader("token"); + } + // 获取案例浏览记录 + UserDynamicResult userDynamicResult = thirdApi.getAllUserdynamicListOfCaseRead(userdynamicParam, token); + + List allUserdynamicList = userDynamicResult.getList(); + List collect = allUserdynamicList.stream().map(UserDynamic::getContentId).distinct().collect(Collectors.toList()); + // 查询案例信息 + List caseList = this.ids(collect, accountId); + Map map = caseList.stream().collect(Collectors.toMap(Cases::getId, cases -> cases)); + + // 组合案例信息与浏览记录 + List batchHistoryVoList = allUserdynamicList.stream().map(userDynamic -> { + CasesBrowsingHistoryVo browsingHistoryVo = new CasesBrowsingHistoryVo(); + browsingHistoryVo.setBrowsingHistoryId(userDynamic.getId()); + browsingHistoryVo.setContentInfo(userDynamic.getContentInfo()); + browsingHistoryVo.setEventTime(userDynamic.getEventTime()); + browsingHistoryVo.setContentId(userDynamic.getContentId()); + if (map.containsKey(userDynamic.getContentId())){ + // 重名属性,如ID,copy会出现覆盖。 + BeanUtils.copyProperties(map.get(userDynamic.getContentId()),browsingHistoryVo); + } + return browsingHistoryVo; + }).collect(Collectors.toList()); + + PageList pageList = new PageList<>(); + pageList.setList(batchHistoryVoList); + pageList.setCount(userDynamicResult.getCount()); + pageList.setPageSize(userDynamicResult.getPageSize()); + + return pageList; + } + + @Override + public Map> queryAllTimePopularityOfMajor() { + QueryBuilder builder = QueryBuilder.from(CasesRank.class); + builder.addField("new CasesRank(majorId,riseRankTime)"); + builder.addFilter(FieldFilters.eq("deleted",false)); + builder.addGroupBy("majorId"); + builder.addGroupBy("riseRankTime"); + List list = casesRankDao.findList(builder.builder()); + // 定义日期时间的格式 + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yy-MM"); + + Map> collect = list.stream().collect(Collectors.groupingBy + (CasesRank::getMajorId, Collectors.mapping(casesRank -> casesRank.getRiseRankTime().format(formatter), Collectors.toList()))); + + return collect; + } + } diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CaseRankingVo.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CaseRankingVo.java new file mode 100644 index 00000000..d906144b --- /dev/null +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CaseRankingVo.java @@ -0,0 +1,17 @@ +package com.xboe.module.boecase.vo; + +import lombok.Data; + +@Data +public class CaseRankingVo { + /** + * 案例id + */ + private String caseId; + + /** + * 案例标题 + */ + private String caseTitle; + +} diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CaseViewRankingItemVo.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CaseViewRankingItemVo.java new file mode 100644 index 00000000..88191080 --- /dev/null +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CaseViewRankingItemVo.java @@ -0,0 +1,29 @@ +package com.xboe.module.boecase.vo; + +import lombok.Data; +import java.time.LocalDateTime; + +@Data +public class CaseViewRankingItemVo { + + /** + * 分类id + */ + private String majorId; + + /** + * 分类名称 + */ + private String majorName; + + /** + * 上榜时间,目前默认为一月中的最后一天的23:59:59 + */ + private LocalDateTime riseRankTime; + + /** + * 标签名称 + */ + private String tagName; + +} diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CasesBrowsingHistoryVo.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CasesBrowsingHistoryVo.java new file mode 100644 index 00000000..93775a0f --- /dev/null +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CasesBrowsingHistoryVo.java @@ -0,0 +1,31 @@ +package com.xboe.module.boecase.vo; + +import com.xboe.module.boecase.entity.Cases; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class CasesBrowsingHistoryVo extends Cases{ + + /** + * 浏览记录id + * */ + private String browsingHistoryId; + + /** + * 案例标题 + * */ + private String contentInfo; + + /** + * 事件时间,查看案例时,有定时接口触发,名为send,eventTime为该时间 + * */ + private LocalDateTime eventTime; + + /** + * 案例ID + * */ + private String contentId; + +} diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CasesQueryRecommendRankVo.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CasesQueryRecommendRankVo.java new file mode 100644 index 00000000..5e6d5a27 --- /dev/null +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/CasesQueryRecommendRankVo.java @@ -0,0 +1,37 @@ +package com.xboe.module.boecase.vo; + +import lombok.Data; + +import java.time.LocalDateTime; + + +@Data +public class CasesQueryRecommendRankVo { + + /** + * 案例id + */ + private String caseId; + + /** + * 案例标题 + */ + private String caseTitle; + + /** + * 案例作者 + */ + private String caseAuthor; + + /** + * 推送用户名称 + */ + private String recommendRankPushUserName; + + /** + * 推送时间 + */ + private LocalDateTime recommendRankPusTime; + + +} diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/FavoriteCaseOfIndexVo.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/FavoriteCaseOfIndexVo.java new file mode 100644 index 00000000..bb59e316 --- /dev/null +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/vo/FavoriteCaseOfIndexVo.java @@ -0,0 +1,23 @@ +package com.xboe.module.boecase.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.xboe.module.boecase.entity.Cases; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class FavoriteCaseOfIndexVo extends Cases{ + + /** + * 收藏id + */ + private String favoriteId; + + /** + * 收藏时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime favoriteTime; + +} diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/interaction/dto/FavoriteCaseDto.java b/servers/boe-server-all/src/main/java/com/xboe/module/interaction/dto/FavoriteCaseDto.java index af70ed9e..8487ada9 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/interaction/dto/FavoriteCaseDto.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/interaction/dto/FavoriteCaseDto.java @@ -12,6 +12,7 @@ public class FavoriteCaseDto { private String id; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime time; /**