资讯精选列表页增加行业分页和概念标签搜索

This commit is contained in:
sunflower2014 2025-06-17 08:01:25 +08:00
parent 09b47574d6
commit 8ec45e21fe
10 changed files with 197 additions and 28 deletions

View File

@ -1,5 +1,7 @@
package com.jinrui.reference.admin.controller;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
@ -16,7 +18,8 @@ import com.jinrui.reference.admin.service.AdminJwtService;
import com.jinrui.reference.core.model.dto.news.SaveIndustryDTO;
import com.jinrui.reference.core.model.vo.PageObject;
import com.jinrui.reference.core.model.vo.ResultObject;
import com.jinrui.reference.core.model.vo.tag.IndustryVO;
import com.jinrui.reference.core.model.vo.industry.IndustryHierarchyVO;
import com.jinrui.reference.core.model.vo.industry.IndustryVO;
import com.jinrui.reference.core.service.IndustryService;
/**
@ -99,6 +102,22 @@ public class IndustryController {
return industryService.update(saveIndustryDTO.getId(), saveIndustryDTO.getPrimaryName(), saveIndustryDTO.getSecondaryName());
}
@GetMapping("/hierarchy")
public ResultObject<List<IndustryHierarchyVO>> getHierarchy(@RequestHeader("auth-token") String token) {
AdminUser adminUser = AdminJwtService.parseToken(token);
if (adminUser == null) {
log.warn("解析token {}拿不到AdminUser对象!", token);
return ResultObject.failed("登陆Token有误请联系系统管理员!");
}
if (!adminUser.isActive()) {
log.warn("当前用户已被封禁! id = {}", adminUser.getId());
return ResultObject.failed("当前用户已被封禁!请联系系统管理员!");
}
return industryService.getHierarchy();
}
/**
* 行业分类搜索接口
*

View File

@ -193,6 +193,8 @@ public class NewsController {
@GetMapping
public PageObject<NewsVO> queryNews(@RequestHeader("auth-token") String token,
@RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "tag", required = false) String tag,
@RequestParam(value = "industry", required = false) String industry,
@RequestParam(value = "minScore", required = false) Double minScore,
@RequestParam(value = "maxScore", required = false) Double maxScore,
@RequestParam(value = "column", required = false) String columnList,
@ -220,13 +222,13 @@ public class NewsController {
}
log.info("path: /news, method: GET, request user id: {}, keyword: {}, column: {}, status: {}, " +
"page: {}, size: {}, last: {}, current: {}, orderBy: {}",
adminUser.getId(), keyword, columnList, status, page, size, last, current, orderBy);
"page: {}, size: {}, last: {}, current: {}, orderBy: {}, tag: {}, industry: {}",
adminUser.getId(), keyword, columnList, status, page, size, last, current, orderBy, tag, industry);
} catch (Exception e) {
log.error("解析登陆Token出错!", e);
return PageObject.failedPage(500, "服务端错误,请联系系统管理员!");
}
return newsService.queryNews(keyword, columnList, status, page, size, last, current, orderBy, minScore, maxScore);
return newsService.queryNews(keyword, columnList, status, page, size, last, current, orderBy, minScore, maxScore, tag, industry);
}
@GetMapping("/score")

View File

@ -19,21 +19,22 @@ spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://10.127.2.207:3306/reference?autoReconnect=true&useUnicode=true&useSSL=false&allowMultiQueries=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: financial_prod
password: mmTFncqmDal5HLRGY0BV
# url: jdbc:mysql://121.37.185.246:3306/reference?autoReconnect=true&useUnicode=true&useSSL=false&allowMultiQueries=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
# username: root
# password: Xgf_8000
# url: jdbc:mysql://192.168.0.142:3306/reference?autoReconnect=true&useUnicode=true&useSSL=false&allowMultiQueries=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
# username: financial_prod
# password: mmTFncqmDal5HLRGY0BV
url: jdbc:mysql://121.37.185.246:3306/reference?autoReconnect=true&useUnicode=true&useSSL=false&allowMultiQueries=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: Xgf_8000
redis:
host: 10.127.2.209
# host: 192.168.0.172
# port: 6379
# password: Xgf_redis
host: 123.60.153.169
port: 6379
password: dMrt4kmwiW6LDJXy
#host: 123.60.153.169
#port: 6379
#password: Xgf_redis
password: Xgf_redis
elasticsearch:
scheme: http
# 111.13.176.3
host: 10.127.2.194
port: 9200
enable: true
@ -42,4 +43,4 @@ elasticsearch:
mybatis:
type-handlers-package:com.jinrui.reference.core.typehandler
api:
key: WBysu6N1z26AbA12l
key: WBysu6N1z26AbA12l

View File

@ -0,0 +1 @@
alter table tag add level tinyint after name;

View File

@ -100,6 +100,18 @@ public interface NewsMapper {
"<if test=\"column != null and !column.isEmpty()\">" +
"inner join news_column_rel on news.id = news_column_rel.news_id " +
"</if>" +
"<if test=\"tags != null and !tags.isEmpty()\">" +
" inner join news_tag_rel on news.id = news_tag_rel.news_id and tag_id in " +
"<foreach collection=\"tags\" item=\"id\" open=\"(\" close=\")\" separator=\",\">\n" +
"#{id}\n" +
"</foreach>" +
"</if>" +
"<if test=\"industries != null and !industries.isEmpty()\">" +
" inner join news_industry_rel on news.id = news_industry_rel.news_id and industry_id in " +
"<foreach collection=\"industries\" item=\"id\" open=\"(\" close=\")\" separator=\",\">\n" +
"#{id}\n" +
"</foreach>" +
"</if>" +
" left join news_tags on news.newsinfo_id = news_tags.newsinfo_id " +
"<where>" +
"<if test=\"keyword != null and !keyword.isEmpty()\">" +
@ -134,13 +146,27 @@ public interface NewsMapper {
@Param("last") Integer last,
@Param("orderBy") String orderBy,
@Param("limit") int limit,
@Param("offset") int offset);
@Param("offset") int offset,
@Param("tags") List<Long> tags,
@Param("industries") List<Long> industries);
@Select("<script>" +
"select count(*) from (select distinct news.* from news " +
"<if test=\"column != null and !column.isEmpty() \">" +
"inner join news_column_rel on news.id = news_column_rel.news_id " +
"</if>" +
"<if test=\"tags != null and !tags.isEmpty()\">" +
" inner join news_tag_rel on news.id = news_tag_rel.news_id and tag_id in " +
"<foreach collection=\"tags\" item=\"id\" open=\"(\" close=\")\" separator=\",\">\n" +
"#{id}\n" +
"</foreach>" +
"</if>" +
"<if test=\"industries != null and !industries.isEmpty()\">" +
" inner join news_industry_rel on news.id = news_industry_rel.news_id and industry_id in " +
"<foreach collection=\"industries\" item=\"id\" open=\"(\" close=\")\" separator=\",\">\n" +
"#{id}\n" +
"</foreach>" +
"</if>" +
"<if test=\"minScore != null or maxScore != null \">" +
"left join news_tags on news.newsinfo_id = news_tags.newsinfo_id " +
"</if>" +
@ -166,7 +192,9 @@ public interface NewsMapper {
@Param("minScore") Double minScore,
@Param("maxScore") Double maxScore,
@Param("column") String columnParam,
@Param("status") Integer status);
@Param("status") Integer status,
@Param("tags") List<Long> tags,
@Param("industries") List<Long> industries);
@Select("select id, title, summary, picture, content, status, " +
"create_time as createTime, " +

View File

@ -0,0 +1,60 @@
package com.jinrui.reference.core.model.vo.industry;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.jinrui.reference.core.model.entity.Industry;
import com.jinrui.reference.core.model.entity.Tag;
/**
* 行业分类
*/
@SuppressWarnings("unused")
public class IndustryHierarchyVO {
/**
* 行业分类ID
*/
private Long id;
/**
* 行业名称
*/
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<IndustryHierarchyVO> getChildren() {
return children;
}
public void setChildren(List<IndustryHierarchyVO> children) {
this.children = children;
}
/**
* 二级行业
*/
private List<IndustryHierarchyVO> children;
public IndustryHierarchyVO(Industry industry) {
this.id = industry.getId();
this.name = industry.getDisplayName();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}

View File

@ -1,4 +1,4 @@
package com.jinrui.reference.core.model.vo.tag;
package com.jinrui.reference.core.model.vo.industry;
import java.util.ArrayList;
import java.util.Date;
@ -41,9 +41,8 @@ public class IndustryVO {
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private Date updateTime;
public IndustryVO(Industry industry) {
public IndustryVO(Industry industry) {
this.id = industry.getId();
this.parentId = industry.getParentId();
this.primaryName = industry.getPrimaryName();
@ -99,5 +98,4 @@ public class IndustryVO {
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}

View File

@ -16,7 +16,8 @@ import com.jinrui.reference.core.mapper.IndustryMapper;
import com.jinrui.reference.core.model.entity.Industry;
import com.jinrui.reference.core.model.vo.PageObject;
import com.jinrui.reference.core.model.vo.ResultObject;
import com.jinrui.reference.core.model.vo.tag.IndustryVO;
import com.jinrui.reference.core.model.vo.industry.IndustryHierarchyVO;
import com.jinrui.reference.core.model.vo.industry.IndustryVO;
@Service
public class IndustryService {
@ -151,5 +152,21 @@ public class IndustryService {
}
return resultPage;
}
public ResultObject<List<IndustryHierarchyVO>> getHierarchy() {
List<IndustryHierarchyVO> resultList = new ArrayList<>();
try {
List<Industry> industrys = industryMapper.queryIndustry(0L, null, "id", "asc");
resultList = industrys.stream().map(IndustryHierarchyVO::new).collect(Collectors.toList());
for (IndustryHierarchyVO industryHierarchyVO: resultList) {
List<Industry> childIndustrys = industryMapper.queryIndustry(industryHierarchyVO.getId(), null, "id", "asc");
industryHierarchyVO.setChildren(childIndustrys.stream().map(IndustryHierarchyVO::new).collect(Collectors.toList()));
}
} catch (Exception e) {
log.error("搜索行业分类出错!", e);
return ResultObject.failed("服务端错误,请联系系统管理员!");
}
return ResultObject.success(resultList);
}
}

View File

@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@ -22,8 +23,9 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.jinrui.reference.core.mapper.ColumnMapper;
import com.jinrui.reference.core.mapper.IndustryMapper;
import com.jinrui.reference.core.mapper.NewsMapper;
@ -767,7 +769,8 @@ public class NewsService {
}
public PageObject<NewsVO> queryNews(String keyword, String columnParam, Integer status, int page, int size,
Integer last, Integer current, String orderBy, Double minScore, Double maxScore) {
Integer last, Integer current, String orderBy, Double minScore, Double maxScore,
String tag, String industry) {
String orderByClause = null;
if (StringUtils.hasText(orderBy)) {
String orderByStr = orderBy;
@ -803,10 +806,23 @@ public class NewsService {
}
}
}
List<Long> tags = this.getMatchTags(tag);
List<Long> industries = null;
if (!ObjectUtils.isEmpty(industry)) {
try {
String industryStr = URLDecoder.decode(industry, "UTF-8");
ObjectMapper objectMapper = new ObjectMapper();
industries = objectMapper.readValue(industryStr, new TypeReference<List<Long>>() {});
} catch (UnsupportedEncodingException|JsonProcessingException e) {
log.error("资讯精选列表页面的行业分类参数异常!", e);
return PageObject.failedPage(500, "服务器错误,请联系系统管理员!");
}
}
List<News> newsList;
try {
newsList = newsMapper.queryNews(keyword, minScore, maxScore, columnParam, status, last, orderByClause, size, offset);
newsList = newsMapper.queryNews(keyword, minScore, maxScore, columnParam, status, last, orderByClause, size, offset, tags, industries);
} catch (Exception e) {
log.error("搜索新闻异常!", e);
return PageObject.failedPage(500, "服务器错误,请联系系统管理员!");
@ -815,7 +831,7 @@ public class NewsService {
PageObject<NewsVO> pageObject = new PageObject<>();
if (page == 1) {
try {
int total = newsMapper.queryTotal(keyword,minScore, maxScore, columnParam, status);
int total = newsMapper.queryTotal(keyword,minScore, maxScore, columnParam, status, tags, industries);
pageObject.setTotal(total);
} catch (Exception e) {
log.error("获取新闻总数异常!", e);
@ -894,4 +910,31 @@ public class NewsService {
NewsScoreVO newsScoreVO = new NewsScoreVO(newsTags);
return ResultObject.success(newsScoreVO);
}
private List<Long> getMatchTags(String tagParam) {
if (ObjectUtils.isEmpty(tagParam)) {
return Collections.emptyList();
}
String[] tags = StringUtils.trimWhitespace(tagParam).split("\\s+");
List<Tag> levelOneTags = tagMapper.queryTag(6L, null, null, "create_time", null);
List<Long> result = new ArrayList<>();
for (Tag tag: levelOneTags) {
long levelOneMatchs = Stream.of(tags).filter(x -> tag.getName().contains(x)).count();
if (levelOneMatchs > 0) {
result.add(tag.getId());
}
List<Tag> childTags = tagMapper.queryTag(tag.getId(), null, null, "create_time", null);
if (levelOneMatchs > 0) {
result.addAll(childTags.stream().map(Tag::getId).collect(Collectors.toList()));
} else {
List<Long> matchedTags = childTags.stream().filter(e -> {
long count = Stream.of(tags).filter(x -> e.getName().contains(x)).count();
return count > 0;
}).map(e -> e.getId()).collect(Collectors.toList());
result.addAll(matchedTags);
}
}
return result;
}
}