资讯精选增加操作日志记录、送审、发布等功能
This commit is contained in:
parent
d291e3be72
commit
4f59c48c1c
|
|
@ -35,11 +35,6 @@
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>redis.clients</groupId>
|
|
||||||
<artifactId>jedis</artifactId>
|
|
||||||
<version>${jedis.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.elasticsearch.client</groupId>
|
<groupId>org.elasticsearch.client</groupId>
|
||||||
<artifactId>elasticsearch-rest-client</artifactId>
|
<artifactId>elasticsearch-rest-client</artifactId>
|
||||||
|
|
@ -50,6 +45,23 @@
|
||||||
<artifactId>jakarta.json-api</artifactId>
|
<artifactId>jakarta.json-api</artifactId>
|
||||||
<version>${jakartajson.version}</version>
|
<version>${jakartajson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>2.19.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.pdfbox</groupId>
|
||||||
|
<artifactId>pdfbox</artifactId>
|
||||||
|
<version>3.0.5</version> <!-- 或使用最新版本 -->
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.itextpdf</groupId>
|
||||||
|
<artifactId>itext7-core</artifactId>
|
||||||
|
<version>9.2.0</version> <!-- 或使用最新版本 -->
|
||||||
|
<type>pom</type>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
/PDFTextSearcher.java
|
||||||
|
/PDFTextSearcherItext.java
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
package com.jinrui.reference.admin;
|
package com.jinrui.reference.admin;
|
||||||
|
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
import redis.clients.jedis.JedisPool;
|
|
||||||
import redis.clients.jedis.JedisPoolConfig;
|
|
||||||
|
|
||||||
@SpringBootApplication(scanBasePackages = {
|
@SpringBootApplication(scanBasePackages = {
|
||||||
"com.jinrui.reference.admin",
|
"com.jinrui.reference.admin",
|
||||||
|
|
@ -17,21 +13,11 @@ import redis.clients.jedis.JedisPoolConfig;
|
||||||
@MapperScan({
|
@MapperScan({
|
||||||
"com.jinrui.reference.admin.mapper",
|
"com.jinrui.reference.admin.mapper",
|
||||||
"com.jinrui.reference.core.mapper"})
|
"com.jinrui.reference.core.mapper"})
|
||||||
|
@EnableScheduling
|
||||||
|
@EnableAspectJAutoProxy
|
||||||
public class AdminApplication {
|
public class AdminApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(AdminApplication.class, args);
|
SpringApplication.run(AdminApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public JedisPool jedisPool(@Value("${redis.host}") String host,
|
|
||||||
@Value("${redis.port}") int port,
|
|
||||||
@Value("${redis.timeout:1000}") int timeout,
|
|
||||||
@Value("${redis.password:}") String password) {
|
|
||||||
if (StringUtils.hasText(password)) {
|
|
||||||
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
|
|
||||||
return new JedisPool(jedisPoolConfig, host, port, timeout, password);
|
|
||||||
}
|
|
||||||
return new JedisPool(host, port);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.jinrui.reference.admin;
|
||||||
|
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
public class ApiClient {
|
||||||
|
public final static String ak = "6a91a5070b044eb0b798f9420ccae15d";
|
||||||
|
public final static String sk = "clkky/Ad6d4DXDZ0UzemOKUKroLwSmc5vlIb2Sjh6YM=";
|
||||||
|
public final static String baseUrl = "http://127.0.0.1:13579";
|
||||||
|
|
||||||
|
public ApiClient() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String path = "/admin/api/news";
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
params.put("num", String.valueOf(20));
|
||||||
|
String result = callApi(path, params);
|
||||||
|
System.out.println("+++++++++++++++++++++++++++++++++++++: " + result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String callApi(String path, Map<String, String> params) throws Exception {
|
||||||
|
String timestamp = String.valueOf(System.currentTimeMillis());
|
||||||
|
String nonce = UUID.randomUUID().toString();
|
||||||
|
String sortedParams = sortParams(params);
|
||||||
|
String url = baseUrl + path + "?" + sortedParams;
|
||||||
|
|
||||||
|
// 1. 计算签名
|
||||||
|
String data = "GET" + path + sortedParams + timestamp + nonce;
|
||||||
|
String signature = calculateSignature(data, sk);
|
||||||
|
|
||||||
|
// 2. 设置请求头
|
||||||
|
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
conn.setRequestMethod("GET");
|
||||||
|
conn.setRequestProperty("X-Api-Key", ak);
|
||||||
|
conn.setRequestProperty("X-Timestamp", timestamp);
|
||||||
|
conn.setRequestProperty("X-Nonce", nonce);
|
||||||
|
conn.setRequestProperty("X-Signature", signature);
|
||||||
|
|
||||||
|
// 3. 发送请求
|
||||||
|
return IOUtils.toString(conn.getInputStream(), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String calculateSignature(String data, String sk) throws Exception {
|
||||||
|
Mac sha256 = Mac.getInstance("HmacSHA256");
|
||||||
|
sha256.init(new SecretKeySpec(sk.getBytes(), "HmacSHA256"));
|
||||||
|
byte[] signBytes = sha256.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return Hex.encodeHexString(signBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sortParams(Map<String, String> params) {
|
||||||
|
return params.entrySet().stream()
|
||||||
|
.sorted(Map.Entry.comparingByKey())
|
||||||
|
.map(e -> e.getKey() + "=" + e.getValue())
|
||||||
|
.collect(Collectors.joining("&"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.jinrui.reference.admin.annotation;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Documented
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Target({ METHOD, ANNOTATION_TYPE })
|
||||||
|
public @interface OperationInfo {
|
||||||
|
String type() default "";
|
||||||
|
|
||||||
|
String behavior();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.jinrui.reference.admin.aspect;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.AfterThrowing;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.jinrui.reference.admin.annotation.OperationInfo;
|
||||||
|
import com.jinrui.reference.admin.model.dto.news.PublishNewsDTO;
|
||||||
|
import com.jinrui.reference.admin.service.UserOperationLogService;
|
||||||
|
import com.jinrui.reference.core.model.vo.ResultObject;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Aspect
|
||||||
|
public class UserOperationLogAspect {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(UserOperationLogAspect.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserOperationLogService userOperationLogService;
|
||||||
|
|
||||||
|
@Pointcut("@annotation(com.jinrui.reference.admin.annotation.OperationInfo)")
|
||||||
|
public void userOperation() {}
|
||||||
|
|
||||||
|
@AfterThrowing(pointcut = "userOperation()", throwing = "e")
|
||||||
|
public void handleThrowing(JoinPoint point, Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("userOperation()")
|
||||||
|
public Object handleSuccess(ProceedingJoinPoint point) throws Throwable {
|
||||||
|
Object result = point.proceed();
|
||||||
|
OperationInfo operationInfo = getOperationInfo(point);
|
||||||
|
String behavior = operationInfo.behavior();
|
||||||
|
String type = operationInfo.type();
|
||||||
|
Object[] args = point.getArgs();
|
||||||
|
|
||||||
|
if (result instanceof ResultObject) {
|
||||||
|
int code = ((ResultObject)result).getCode();
|
||||||
|
if (code != 200) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("news".equals(type)) {
|
||||||
|
userOperationLogService.logUserOperation(type, behavior, (String)args[0], ((PublishNewsDTO)args[1]).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OperationInfo getOperationInfo(JoinPoint point) {
|
||||||
|
MethodSignature ms = (MethodSignature)point.getSignature();
|
||||||
|
Method method = ms.getMethod();
|
||||||
|
return method.<OperationInfo>getAnnotation(OperationInfo.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
package com.jinrui.reference.admin.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestHeader;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.jinrui.reference.admin.model.entity.AdminUser;
|
||||||
|
import com.jinrui.reference.admin.service.AdminJwtService;
|
||||||
|
import com.jinrui.reference.core.model.vo.ResultObject;
|
||||||
|
import com.jinrui.reference.core.model.vo.news.NewsApiVO;
|
||||||
|
import com.jinrui.reference.core.service.ApiKeyService;
|
||||||
|
import com.jinrui.reference.core.service.NewsService;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api")
|
||||||
|
public class ApiController {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ApiController.class);
|
||||||
|
|
||||||
|
private final NewsService newsService;
|
||||||
|
private final ApiKeyService apiKeyService;
|
||||||
|
|
||||||
|
public ApiController(NewsService newsService, ApiKeyService apiKeyService) {
|
||||||
|
this.newsService = newsService;
|
||||||
|
this.apiKeyService = apiKeyService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/news")
|
||||||
|
public ResultObject<List<NewsApiVO>> getNews(@RequestParam(name = "num", required = true, defaultValue = "10") Integer num, @RequestParam(name = "last", required = false) Long last) {
|
||||||
|
return newsService.requestNewsByApi(num, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/news")
|
||||||
|
public ResultObject<List<NewsApiVO>> queryNews(@RequestParam(name = "num", required = true, defaultValue = "10") Integer num, @RequestParam(name = "last", required = false) Long last) {
|
||||||
|
return newsService.requestNewsByApi(num, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/key")
|
||||||
|
public ResultObject<Map<String, Object>> generateApiKey(@RequestHeader("auth-token") String token,
|
||||||
|
@RequestParam(name = "clientName", required = true) String clientName) {
|
||||||
|
if (!StringUtils.hasText(token)) {
|
||||||
|
return ResultObject.failed("登陆Token为空!");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
AdminUser adminUser = AdminJwtService.parseToken(token);
|
||||||
|
if (adminUser == null) {
|
||||||
|
log.warn("解析token {}拿不到AdminUser对象!", token);
|
||||||
|
return ResultObject.failed("登陆Token有误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Long adminUserId = adminUser.getId();
|
||||||
|
if (!adminUser.isActive()) {
|
||||||
|
log.warn("当前用户已被封禁! id = {}", adminUserId);
|
||||||
|
return ResultObject.failed("当前用户已被封禁!请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("path: /api/key, method: POST, request user id: {}, clientName: {}", adminUserId, clientName);
|
||||||
|
return apiKeyService.generateApiKey(clientName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析登陆Token出错!", e);
|
||||||
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/key")
|
||||||
|
public ResultObject<Map<String, Object>> getApiKey(@RequestHeader("auth-token") String token,
|
||||||
|
@RequestParam(name = "clientName", required = true) String clientName) {
|
||||||
|
return generateApiKey(token, clientName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,16 @@
|
||||||
package com.jinrui.reference.admin.controller;
|
package com.jinrui.reference.admin.controller;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestHeader;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.aliyuncs.auth.sts.AssumeRoleRequest;
|
import com.aliyuncs.auth.sts.AssumeRoleRequest;
|
||||||
import com.aliyuncs.auth.sts.AssumeRoleResponse;
|
import com.aliyuncs.auth.sts.AssumeRoleResponse;
|
||||||
import com.aliyuncs.http.MethodType;
|
import com.aliyuncs.http.MethodType;
|
||||||
|
|
@ -7,19 +18,12 @@ import com.aliyuncs.profile.DefaultProfile;
|
||||||
import com.aliyuncs.profile.IClientProfile;
|
import com.aliyuncs.profile.IClientProfile;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.jinrui.reference.admin.model.dto.newsinfo.PublishNewsInfoDTO;
|
|
||||||
import com.jinrui.reference.admin.model.dto.oss.CloseableAcsClient;
|
import com.jinrui.reference.admin.model.dto.oss.CloseableAcsClient;
|
||||||
import com.jinrui.reference.admin.model.entity.AdminUser;
|
import com.jinrui.reference.admin.model.entity.AdminUser;
|
||||||
import com.jinrui.reference.admin.model.vo.oss.OssVO;
|
import com.jinrui.reference.admin.model.vo.oss.OssVO;
|
||||||
import com.jinrui.reference.admin.service.AdminJwtService;
|
import com.jinrui.reference.admin.service.AdminJwtService;
|
||||||
import com.jinrui.reference.core.model.vo.ResultObject;
|
import com.jinrui.reference.core.model.vo.ResultObject;
|
||||||
import com.jinrui.reference.core.service.NewsInfoService;
|
import com.jinrui.reference.core.service.NewsInfoService;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/common")
|
@RequestMapping("/common")
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.jinrui.reference.admin.controller;
|
package com.jinrui.reference.admin.controller;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -8,6 +9,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestHeader;
|
import org.springframework.web.bind.annotation.RequestHeader;
|
||||||
|
|
@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.jinrui.reference.admin.annotation.OperationInfo;
|
||||||
import com.jinrui.reference.admin.model.dto.news.PublishNewsDTO;
|
import com.jinrui.reference.admin.model.dto.news.PublishNewsDTO;
|
||||||
import com.jinrui.reference.admin.model.entity.AdminUser;
|
import com.jinrui.reference.admin.model.entity.AdminUser;
|
||||||
import com.jinrui.reference.admin.service.AdminJwtService;
|
import com.jinrui.reference.admin.service.AdminJwtService;
|
||||||
|
|
@ -23,10 +26,15 @@ import com.jinrui.reference.core.model.dto.news.SaveNewsDTO;
|
||||||
import com.jinrui.reference.core.model.vo.PageObject;
|
import com.jinrui.reference.core.model.vo.PageObject;
|
||||||
import com.jinrui.reference.core.model.vo.ResultObject;
|
import com.jinrui.reference.core.model.vo.ResultObject;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsDetailVO;
|
import com.jinrui.reference.core.model.vo.news.NewsDetailVO;
|
||||||
|
import com.jinrui.reference.core.model.vo.news.NewsLogVO;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsScoreVO;
|
import com.jinrui.reference.core.model.vo.news.NewsScoreVO;
|
||||||
|
import com.jinrui.reference.core.model.vo.news.NewsTranslatorVO;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsVO;
|
import com.jinrui.reference.core.model.vo.news.NewsVO;
|
||||||
import com.jinrui.reference.core.service.NewsService;
|
import com.jinrui.reference.core.service.NewsService;
|
||||||
|
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/news")
|
@RequestMapping("/news")
|
||||||
public class NewsController {
|
public class NewsController {
|
||||||
|
|
@ -35,15 +43,96 @@ public class NewsController {
|
||||||
|
|
||||||
private final NewsService newsService;
|
private final NewsService newsService;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
|
private final JedisPool jedisPool;
|
||||||
|
|
||||||
|
|
||||||
public NewsController(NewsService newsService,
|
public NewsController(NewsService newsService,
|
||||||
ObjectMapper objectMapper) {
|
ObjectMapper objectMapper,
|
||||||
|
JedisPool jedisPool) {
|
||||||
this.newsService = newsService;
|
this.newsService = newsService;
|
||||||
this.objectMapper = objectMapper;;
|
this.objectMapper = objectMapper;
|
||||||
|
this.jedisPool = jedisPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/submit")
|
||||||
|
@OperationInfo(behavior = "送审", type = "news")
|
||||||
|
public ResultObject<Void> submit(@RequestHeader("auth-token") String token,
|
||||||
|
@RequestBody PublishNewsDTO publishNewsDTO) {
|
||||||
|
if (!StringUtils.hasText(token)) {
|
||||||
|
return ResultObject.failed("登陆Token为空!");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
AdminUser adminUser = AdminJwtService.parseToken(token);
|
||||||
|
if (adminUser == null) {
|
||||||
|
log.warn("解析token {}拿不到AdminUser对象!", token);
|
||||||
|
return ResultObject.failed("登陆Token有误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Long adminUserId = adminUser.getId();
|
||||||
|
if (!adminUser.isActive()) {
|
||||||
|
log.warn("当前用户已被封禁! id = {}", adminUserId);
|
||||||
|
return ResultObject.failed("当前用户已被封禁!请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Long id = publishNewsDTO.getId();
|
||||||
|
if (id == null) {
|
||||||
|
return ResultObject.failed("要送审的新闻ID不可为空!");
|
||||||
|
}
|
||||||
|
boolean isSuccessed = setEditingFlag(id);
|
||||||
|
if (!isSuccessed) {
|
||||||
|
return ResultObject.failed("该资讯正在审核中,请勿重复操作!");
|
||||||
|
}
|
||||||
|
log.info("path: /news/publish, method: POST, request user id: {}, news id: {}", adminUserId, id);
|
||||||
|
return newsService.submit(id, adminUserId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析登陆Token出错!", e);
|
||||||
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
|
} finally {
|
||||||
|
unsetEditingFlag(publishNewsDTO.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/revoke")
|
||||||
|
public ResultObject<Void> revoke(@RequestHeader("auth-token") String token,
|
||||||
|
@RequestBody PublishNewsDTO publishNewsDTO) {
|
||||||
|
if (!StringUtils.hasText(token)) {
|
||||||
|
return ResultObject.failed("登陆Token为空!");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
AdminUser adminUser = AdminJwtService.parseToken(token);
|
||||||
|
if (adminUser == null) {
|
||||||
|
log.warn("解析token {}拿不到AdminUser对象!", token);
|
||||||
|
return ResultObject.failed("登陆Token有误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Long adminUserId = adminUser.getId();
|
||||||
|
if (!adminUser.isActive()) {
|
||||||
|
log.warn("当前用户已被封禁! id = {}", adminUserId);
|
||||||
|
return ResultObject.failed("当前用户已被封禁!请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Long id = publishNewsDTO.getId();
|
||||||
|
if (id == null) {
|
||||||
|
return ResultObject.failed("要送审的新闻ID不可为空!");
|
||||||
|
}
|
||||||
|
boolean isSuccessed = setEditingFlag(id);
|
||||||
|
if (!isSuccessed) {
|
||||||
|
return ResultObject.failed("该资讯正在审核中,请勿重复操作!");
|
||||||
|
}
|
||||||
|
log.info("path: /news/publish, method: POST, request user id: {}, news id: {}", adminUserId, id);
|
||||||
|
return newsService.revoke(id, adminUserId, adminUser.isReviewer());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析登陆Token出错!", e);
|
||||||
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
|
} finally {
|
||||||
|
unsetEditingFlag(publishNewsDTO.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/publish")
|
@PostMapping("/publish")
|
||||||
|
@OperationInfo(behavior = "发布", type = "news")
|
||||||
public ResultObject<Void> publish(@RequestHeader("auth-token") String token,
|
public ResultObject<Void> publish(@RequestHeader("auth-token") String token,
|
||||||
@RequestBody PublishNewsDTO publishNewsDTO) {
|
@RequestBody PublishNewsDTO publishNewsDTO) {
|
||||||
if (!StringUtils.hasText(token)) {
|
if (!StringUtils.hasText(token)) {
|
||||||
|
|
@ -67,7 +156,10 @@ public class NewsController {
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
return ResultObject.failed("要发布/下架的新闻ID不可为空!");
|
return ResultObject.failed("要发布/下架的新闻ID不可为空!");
|
||||||
}
|
}
|
||||||
|
if (!adminUser.isReviewer()) {
|
||||||
|
return ResultObject.failed("当前操作非法,没有审核员权限!");
|
||||||
|
}
|
||||||
|
|
||||||
log.info("path: /news/publish, method: POST, request user id: {}, news id: {}", adminUserId, id);
|
log.info("path: /news/publish, method: POST, request user id: {}, news id: {}", adminUserId, id);
|
||||||
return newsService.publish(id, adminUserId);
|
return newsService.publish(id, adminUserId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -111,6 +203,39 @@ public class NewsController {
|
||||||
return ResultObject.failed("登陆Token为空!");
|
return ResultObject.failed("登陆Token为空!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
AdminUser adminUser = AdminJwtService.parseToken(token);
|
||||||
|
if (adminUser == null) {
|
||||||
|
log.warn("解析token {}拿不到AdminUser对象!", token);
|
||||||
|
return ResultObject.failed("登陆Token有误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Long adminUserId = adminUser.getId();
|
||||||
|
if (!adminUser.isActive()) {
|
||||||
|
log.warn("当前用户已被封禁! id = {}", adminUserId);
|
||||||
|
return ResultObject.failed("当前用户已被封禁!请联系系统管理员!");
|
||||||
|
}
|
||||||
|
boolean isSuccessed = setEditingFlag(id);
|
||||||
|
if (!isSuccessed) {
|
||||||
|
return ResultObject.failed("该资讯正在审核中,请勿重复操作!");
|
||||||
|
}
|
||||||
|
log.info("path: /news, method: DELETE, request user id: {}, news id: {}", adminUserId, id);
|
||||||
|
return newsService.deleteNews(id, adminUserId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析登陆Token出错!", e);
|
||||||
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
|
} finally {
|
||||||
|
unsetEditingFlag(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/{id}/recover")
|
||||||
|
public ResultObject<Void> recoverNews(@RequestHeader("auth-token") String token,
|
||||||
|
@PathVariable( name = "id", required = true) Long id) {
|
||||||
|
if (!StringUtils.hasText(token)) {
|
||||||
|
return ResultObject.failed("登陆Token为空!");
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AdminUser adminUser = AdminJwtService.parseToken(token);
|
AdminUser adminUser = AdminJwtService.parseToken(token);
|
||||||
if (adminUser == null) {
|
if (adminUser == null) {
|
||||||
|
|
@ -125,7 +250,7 @@ public class NewsController {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("path: /news, method: DELETE, request user id: {}, news id: {}", adminUserId, id);
|
log.info("path: /news, method: DELETE, request user id: {}, news id: {}", adminUserId, id);
|
||||||
return newsService.deleteNews(id);
|
return newsService.recoverNews(id, adminUserId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("解析登陆Token出错!", e);
|
log.error("解析登陆Token出错!", e);
|
||||||
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
|
|
@ -151,14 +276,18 @@ public class NewsController {
|
||||||
log.warn("当前用户已被封禁! id = {}", adminUserId);
|
log.warn("当前用户已被封禁! id = {}", adminUserId);
|
||||||
return ResultObject.failed("当前用户已被封禁!请联系系统管理员!");
|
return ResultObject.failed("当前用户已被封禁!请联系系统管理员!");
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("path: /news/create/publish, method: POST, request user id: {}, param: {}",
|
log.info("path: /news/create/publish, method: POST, request user id: {}, param: {}",
|
||||||
adminUserId, objectMapper.writeValueAsString(saveNewsDTO));
|
adminUserId, objectMapper.writeValueAsString(saveNewsDTO));
|
||||||
|
boolean isSuccessed = setEditingFlag(saveNewsDTO.getId());
|
||||||
return newsService.createPublish(adminUserId, saveNewsDTO);
|
if (!isSuccessed) {
|
||||||
|
return ResultObject.failed("该资讯正在审核中,请勿重复操作!");
|
||||||
|
}
|
||||||
|
return newsService.createPublish(adminUserId, saveNewsDTO, adminUser.isReviewer());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("解析登陆Token出错!", e);
|
log.error("解析登陆Token出错!", e);
|
||||||
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
|
} finally {
|
||||||
|
unsetEditingFlag(saveNewsDTO.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -183,14 +312,12 @@ public class NewsController {
|
||||||
|
|
||||||
log.info("path: /news/save, method: POST, request user id: {}, param: {}",
|
log.info("path: /news/save, method: POST, request user id: {}, param: {}",
|
||||||
adminUser.getId(), objectMapper.writeValueAsString(saveNewsDTO));
|
adminUser.getId(), objectMapper.writeValueAsString(saveNewsDTO));
|
||||||
|
|
||||||
|
return newsService.saveDraft(saveNewsDTO, adminUser.isReviewer());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("解析登陆Token出错!", e);
|
log.error("解析登陆Token出错!", e);
|
||||||
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 这个接口是保存,那status应该是1,未发布
|
|
||||||
saveNewsDTO.setStatus(1);
|
|
||||||
return newsService.saveDraft(saveNewsDTO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
|
|
@ -206,10 +333,12 @@ public class NewsController {
|
||||||
@RequestParam(value = "size", required = false, defaultValue = "10") int size,
|
@RequestParam(value = "size", required = false, defaultValue = "10") int size,
|
||||||
@RequestParam(value = "last", required = false) Integer last,
|
@RequestParam(value = "last", required = false) Integer last,
|
||||||
@RequestParam(value = "current", required = false) Integer current,
|
@RequestParam(value = "current", required = false) Integer current,
|
||||||
@RequestParam(value = "orderBy", required = false, defaultValue = "id$asc") String orderBy,
|
@RequestParam(value = "orderBy", required = false) String orderBy,
|
||||||
@RequestParam(value = "mediaId", required = false) Long mediaId,
|
@RequestParam(value = "mediaId", required = false) Long mediaId,
|
||||||
@RequestParam(value = "dateline_from", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date datelineFrom,
|
@RequestParam(value = "dateline_from", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date datelineFrom,
|
||||||
@RequestParam(value = "dateline_to", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date datelineTo
|
@RequestParam(value = "dateline_to", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date datelineTo,
|
||||||
|
@RequestParam(value = "deleted", required = false) Integer deleted,
|
||||||
|
@RequestParam(value = "rating", required = false) Byte rating
|
||||||
) {
|
) {
|
||||||
if (!StringUtils.hasText(token)) {
|
if (!StringUtils.hasText(token)) {
|
||||||
return PageObject.failedPage("登陆Token为空!");
|
return PageObject.failedPage("登陆Token为空!");
|
||||||
|
|
@ -230,11 +359,11 @@ public class NewsController {
|
||||||
log.info("path: /news, method: GET, request user id: {}, keyword: {}, column: {}, status: {}, " +
|
log.info("path: /news, method: GET, request user id: {}, keyword: {}, column: {}, status: {}, " +
|
||||||
"page: {}, size: {}, last: {}, current: {}, orderBy: {}, tag: {}, industry: {}",
|
"page: {}, size: {}, last: {}, current: {}, orderBy: {}, tag: {}, industry: {}",
|
||||||
adminUser.getId(), keyword, columnList, status, page, size, last, current, orderBy, tag, industry);
|
adminUser.getId(), keyword, columnList, status, page, size, last, current, orderBy, tag, industry);
|
||||||
|
return newsService.queryNews(keyword, columnList, status, page, size, last, current, orderBy, minScore, maxScore, tag, industry, mediaId, datelineFrom, datelineTo, deleted, rating, adminUser.isReviewer());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("解析登陆Token出错!", e);
|
log.error("解析登陆Token出错!", e);
|
||||||
return PageObject.failedPage(500, "服务端错误,请联系系统管理员!");
|
return PageObject.failedPage(500, "服务端错误,请联系系统管理员!");
|
||||||
}
|
}
|
||||||
return newsService.queryNews(keyword, columnList, status, page, size, last, current, orderBy, minScore, maxScore, tag, industry, mediaId, datelineFrom, datelineTo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/score")
|
@GetMapping("/score")
|
||||||
|
|
@ -264,4 +393,97 @@ public class NewsController {
|
||||||
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}/translator")
|
||||||
|
public ResultObject<NewsTranslatorVO> getTranslator(@RequestHeader("auth-token") String token,
|
||||||
|
@PathVariable(name = "id", required = true) Long id) {
|
||||||
|
if (!StringUtils.hasText(token)) {
|
||||||
|
return ResultObject.failed("登陆Token为空!");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
AdminUser adminUser = AdminJwtService.parseToken(token);
|
||||||
|
if (adminUser == null) {
|
||||||
|
log.warn("解析token {}拿不到AdminUser对象!", token);
|
||||||
|
return ResultObject.failed("登陆Token有误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Long adminUserId = adminUser.getId();
|
||||||
|
if (!adminUser.isActive()) {
|
||||||
|
log.warn("当前用户已被封禁! id = {}", adminUserId);
|
||||||
|
return ResultObject.failed("当前用户已被封禁!请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("path: /news/detail, method: GET, request user id: {}, news id: {}", adminUserId, id);
|
||||||
|
return newsService.getTranslator(id);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析登陆Tokn出错!", e);
|
||||||
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/log")
|
||||||
|
public PageObject<NewsLogVO> getLog(@RequestHeader("auth-token") String token,
|
||||||
|
@RequestParam("id") Long id,
|
||||||
|
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
|
||||||
|
@RequestParam(value = "size", required = false, defaultValue = "10") int size,
|
||||||
|
@RequestParam(value = "current", required = false) Integer current) {
|
||||||
|
if (!StringUtils.hasText(token)) {
|
||||||
|
return PageObject.failedPage("登陆Token为空!");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
AdminUser adminUser = AdminJwtService.parseToken(token);
|
||||||
|
if (adminUser == null) {
|
||||||
|
log.warn("解析token {}拿不到AdminUser对象!", token);
|
||||||
|
return PageObject.failedPage("登陆Token有误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Long adminUserId = adminUser.getId();
|
||||||
|
if (!adminUser.isActive()) {
|
||||||
|
log.warn("当前用户已被封禁! id = {}", adminUserId);
|
||||||
|
return PageObject.failedPage("当前用户已被封禁!请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("path: /news/log, method: GET, request user id: {}, news id: {}, page: {}, size: {}, current: {}", adminUserId, id, page, size, current);
|
||||||
|
return newsService.getLog(id, page, size, current);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析登陆Tokn出错!", e);
|
||||||
|
return PageObject.failedPage(500, "服务端错误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param newsId
|
||||||
|
* @return true:表示不存在其他人在编辑; false表示已经有人在编辑或者操作
|
||||||
|
*/
|
||||||
|
private boolean setEditingFlag(Long newsId) {
|
||||||
|
if (newsId == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String newsIdStr = String.valueOf(newsId);
|
||||||
|
try(Jedis jedis = jedisPool.getResource()) {
|
||||||
|
Long result = jedis.setnx(newsIdStr, "");
|
||||||
|
if (result == null ||result == 0L) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
jedis.expire(newsIdStr, 10*60L);
|
||||||
|
return true;
|
||||||
|
} catch(Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unsetEditingFlag(Long newsId) {
|
||||||
|
if (newsId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String newsIdStr = String.valueOf(newsId);
|
||||||
|
try(Jedis jedis = jedisPool.getResource()) {
|
||||||
|
jedis.del(newsIdStr);
|
||||||
|
} catch(Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
package com.jinrui.reference.admin.controller;
|
package com.jinrui.reference.admin.controller;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
@ -18,6 +21,7 @@ import com.jinrui.reference.admin.model.entity.AdminUser;
|
||||||
import com.jinrui.reference.admin.service.AdminJwtService;
|
import com.jinrui.reference.admin.service.AdminJwtService;
|
||||||
import com.jinrui.reference.core.model.vo.PageObject;
|
import com.jinrui.reference.core.model.vo.PageObject;
|
||||||
import com.jinrui.reference.core.model.vo.ResultObject;
|
import com.jinrui.reference.core.model.vo.ResultObject;
|
||||||
|
import com.jinrui.reference.core.model.vo.news.NewsScoreVO;
|
||||||
import com.jinrui.reference.core.model.vo.newsinfo.NewsInfoDetailVO;
|
import com.jinrui.reference.core.model.vo.newsinfo.NewsInfoDetailVO;
|
||||||
import com.jinrui.reference.core.model.vo.newsinfo.NewsInfoVO;
|
import com.jinrui.reference.core.model.vo.newsinfo.NewsInfoVO;
|
||||||
import com.jinrui.reference.core.model.vo.newsinfo.SaveNewsInfoDTO;
|
import com.jinrui.reference.core.model.vo.newsinfo.SaveNewsInfoDTO;
|
||||||
|
|
@ -119,7 +123,7 @@ public class NewsInfoController {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("path: /newsinfo, method: DELETE, request user id: {}, news id: {}", adminUserId, id);
|
log.info("path: /newsinfo, method: DELETE, request user id: {}, news id: {}", adminUserId, id);
|
||||||
return newsInfoService.deleteNewsInfo(id);
|
return newsInfoService.deleteNewsInfo(id, adminUserId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("解析登陆Token出错!", e);
|
log.error("解析登陆Token出错!", e);
|
||||||
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
|
|
@ -168,7 +172,11 @@ public class NewsInfoController {
|
||||||
@RequestParam(value = "size", required = false, defaultValue = "10") int size,
|
@RequestParam(value = "size", required = false, defaultValue = "10") int size,
|
||||||
@RequestParam(value = "current", required = false) Integer current,
|
@RequestParam(value = "current", required = false) Integer current,
|
||||||
@RequestParam(value = "orderBy", required = false, defaultValue = "inputDate") String orderBy,
|
@RequestParam(value = "orderBy", required = false, defaultValue = "inputDate") String orderBy,
|
||||||
@RequestParam(value = "direction", required = false, defaultValue = "asc") String direction
|
@RequestParam(value = "direction", required = false, defaultValue = "desc") String direction,
|
||||||
|
@RequestParam(value = "minScore", required = false) Double minScore,
|
||||||
|
@RequestParam(value = "maxScore", required = false) Double maxScore,
|
||||||
|
@RequestParam(value = "inputDateFrom", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date inputDateFrom,
|
||||||
|
@RequestParam(value = "inputDateTo", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date inputDateTo
|
||||||
) {
|
) {
|
||||||
if (!StringUtils.hasText(token)) {
|
if (!StringUtils.hasText(token)) {
|
||||||
return PageObject.failedPage("登陆Token为空!");
|
return PageObject.failedPage("登陆Token为空!");
|
||||||
|
|
@ -193,8 +201,34 @@ public class NewsInfoController {
|
||||||
log.error("解析登陆Token出错!", e);
|
log.error("解析登陆Token出错!", e);
|
||||||
return PageObject.failedPage(500, "服务端错误,请联系系统管理员!");
|
return PageObject.failedPage(500, "服务端错误,请联系系统管理员!");
|
||||||
}
|
}
|
||||||
return newsInfoService.queryNewsInfo(title, content, stockcode, sourcename, page, size, last, current, orderBy, direction);
|
return newsInfoService.queryNewsInfo(title, content, stockcode, sourcename, page, size, last, current, orderBy, direction, minScore, maxScore, inputDateFrom, inputDateTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/score")
|
||||||
|
public ResultObject<NewsScoreVO> getScore(@RequestHeader("auth-token") String token,
|
||||||
|
@RequestParam("id") String id) {
|
||||||
|
if (!StringUtils.hasText(token)) {
|
||||||
|
return ResultObject.failed("登陆Token为空!");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
AdminUser adminUser = AdminJwtService.parseToken(token);
|
||||||
|
if (adminUser == null) {
|
||||||
|
log.warn("解析token {}拿不到AdminUser对象!", token);
|
||||||
|
return ResultObject.failed("登陆Token有误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
Long adminUserId = adminUser.getId();
|
||||||
|
if (!adminUser.isActive()) {
|
||||||
|
log.warn("当前用户已被封禁! id = {}", adminUserId);
|
||||||
|
return ResultObject.failed("当前用户已被封禁!请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("path: /news/score, method: GET, request user id: {}, news id: {}", adminUserId, id);
|
||||||
|
return newsInfoService.getScore(id);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析登陆Tokn出错!", e);
|
||||||
|
return ResultObject.failed(500, "服务端错误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.jinrui.reference.admin.job;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.jinrui.reference.core.mapper.NewsMapper;
|
||||||
|
import com.jinrui.reference.core.model.entity.News;
|
||||||
|
import com.jinrui.reference.core.service.NewsService;
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class NewsDeduplicationJob {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NewsService newsService;
|
||||||
|
@Autowired
|
||||||
|
private NewsMapper newsMapper;
|
||||||
|
|
||||||
|
|
||||||
|
// @Scheduled(fixedDelay=15, initialDelay=0, timeUnit = TimeUnit.MINUTES)
|
||||||
|
public void cleanDuplicatedData() {
|
||||||
|
List<String> clusterIds = newsMapper.getDuplicatedCluster();
|
||||||
|
for (String clusterId: clusterIds) {
|
||||||
|
List<News> duplicatedNews = newsMapper.getDuplicatedNews(clusterId);
|
||||||
|
List<News> toBeDeletedNews = duplicatedNews.stream().filter(e -> e.getDeleted() && e.getEditorId() == null).collect(Collectors.toList());
|
||||||
|
if (duplicatedNews.size() > toBeDeletedNews.size()) {
|
||||||
|
newsService.backupDuplicatedNews(toBeDeletedNews, clusterId);
|
||||||
|
newsService.deletDuplicatedNews(toBeDeletedNews);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,271 @@
|
||||||
|
package com.jinrui.reference.admin.job;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.jinrui.reference.core.mapper.NewsTagsMapper;
|
||||||
|
import com.jinrui.reference.core.model.entity.NewsInfo;
|
||||||
|
import com.jinrui.reference.core.model.entity.NewsTags;
|
||||||
|
|
||||||
|
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||||
|
import co.elastic.clients.elasticsearch._types.ElasticsearchException;
|
||||||
|
import co.elastic.clients.elasticsearch._types.InlineScript;
|
||||||
|
import co.elastic.clients.elasticsearch._types.Refresh;
|
||||||
|
import co.elastic.clients.elasticsearch._types.SortOptions;
|
||||||
|
import co.elastic.clients.elasticsearch._types.SortOrder;
|
||||||
|
import co.elastic.clients.elasticsearch._types.query_dsl.ExistsQuery;
|
||||||
|
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
|
||||||
|
import co.elastic.clients.elasticsearch._types.query_dsl.ScriptQuery;
|
||||||
|
import co.elastic.clients.elasticsearch._types.query_dsl.WildcardQuery;
|
||||||
|
import co.elastic.clients.elasticsearch.core.SearchRequest;
|
||||||
|
import co.elastic.clients.elasticsearch.core.SearchResponse;
|
||||||
|
import co.elastic.clients.elasticsearch.core.search.Hit;
|
||||||
|
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class NewsTagsIndustryLabelRepairJob {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(NewsTagsIndustryLabelRepairJob.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ElasticsearchClient elasticsearchClient;
|
||||||
|
@Autowired
|
||||||
|
private NewsTagsMapper newsTagsMapper;
|
||||||
|
|
||||||
|
// @Scheduled(fixedDelay=15, initialDelay=0, timeUnit = TimeUnit.MINUTES)
|
||||||
|
public void startToRepair() {
|
||||||
|
List<Query> filters = new ArrayList<>();
|
||||||
|
filters.add(ExistsQuery.of(e -> e.field("news_tags.industry_label"))._toQuery());
|
||||||
|
filters.add(WildcardQuery.of(e -> e.field("news_tags.industry_label").value("*"))._toQuery());
|
||||||
|
Query scriptQuery = ScriptQuery.of(e -> e.script(s -> s.inline(InlineScript.of(i -> i.lang("painless").source("doc['news_tags.industry_label.keyword'][0].indexOf('[') == 0")))))._toQuery();
|
||||||
|
filters.add(scriptQuery);
|
||||||
|
|
||||||
|
SortOptions sortOptions = SortOptions.of(e -> e.field(s -> s.field("create_time").order(SortOrder.Desc)));
|
||||||
|
|
||||||
|
Query resultQuery = new Query.Builder().bool(b -> b.filter(filters)).build();
|
||||||
|
|
||||||
|
int pageSize = 1000;
|
||||||
|
SearchRequest request = SearchRequest.of(s ->
|
||||||
|
s.index(NewsInfo.INDEX_NAME).from(0)
|
||||||
|
.size(pageSize) // 分页参数
|
||||||
|
.sort(sortOptions) // 排序字段
|
||||||
|
.query(resultQuery));
|
||||||
|
|
||||||
|
SearchResponse<JsonNode> searchResp;
|
||||||
|
try {
|
||||||
|
searchResp = elasticsearchClient.search(request, JsonNode.class);
|
||||||
|
HitsMetadata<JsonNode> hits = searchResp.hits();
|
||||||
|
if (!ObjectUtils.isEmpty(hits)) {
|
||||||
|
for (Hit<JsonNode> hit: hits.hits()) {
|
||||||
|
String id = hit.id();
|
||||||
|
NewsTags newsTags = newsTagsMapper.getNewsTagsByNewsId(id);
|
||||||
|
if (newsTags == null) {
|
||||||
|
JsonNode newsInfo = hit.source();
|
||||||
|
JsonNode newsTagsNode = newsInfo.get("news_tags");
|
||||||
|
newsTags = new NewsTags();
|
||||||
|
String summary = newsTagsNode.get("abstract").asText();
|
||||||
|
newsTags.setSummary(summary);
|
||||||
|
String title = newsTagsNode.get("title").asText();
|
||||||
|
newsTags.setTitle(title);
|
||||||
|
String rewriteContent = newsTagsNode.get("rewrite_content").asText();
|
||||||
|
newsTags.setRewriteContent(rewriteContent);
|
||||||
|
List<String> industryLabel = getIndustryLabel(newsTagsNode.get("industry_label").asText());
|
||||||
|
newsTags.setIndustryLabel(industryLabel);
|
||||||
|
List<Double> industryConfidence = doubleArrayNodeToList(newsTagsNode.get("industry_confidence"));
|
||||||
|
newsTags.setIndustryConfidence(industryConfidence);
|
||||||
|
List<Double> industryScore = doubleArrayNodeToList(newsTagsNode.get("industry_score"));
|
||||||
|
newsTags.setIndustryScore(industryScore);
|
||||||
|
List<String> conceptLabel = textArrayNodeToList(newsTagsNode.get("concept_label"));
|
||||||
|
newsTags.setConceptLabel(conceptLabel);
|
||||||
|
List<Double> conceptConfidence = doubleArrayNodeToList(newsTagsNode.get("concept_confidence"));
|
||||||
|
newsTags.setConceptConfidence(conceptConfidence);
|
||||||
|
List<Double> conceptScore = doubleArrayNodeToList(newsTagsNode.get("concept_score"));
|
||||||
|
newsTags.setConceptScore(conceptScore);
|
||||||
|
Integer publicOpinionScore = null;
|
||||||
|
if (newsTagsNode.hasNonNull("public_opinion_score")) {
|
||||||
|
publicOpinionScore = newsTagsNode.get("public_opinion_score").asInt();
|
||||||
|
}
|
||||||
|
newsTags.setPublicOpinionScore(publicOpinionScore);
|
||||||
|
Double chinaFactor = null;
|
||||||
|
if (newsTagsNode.hasNonNull("China_factor")) {
|
||||||
|
chinaFactor = newsTagsNode.get("China_factor").asDouble();
|
||||||
|
}
|
||||||
|
newsTags.setChinaFactor(chinaFactor);
|
||||||
|
String source = newsTagsNode.get("source").asText();
|
||||||
|
newsTags.setSource(source);
|
||||||
|
Integer sourceImpact = null;
|
||||||
|
if (newsTagsNode.hasNonNull("source_impact")) {
|
||||||
|
sourceImpact = newsTagsNode.get("source_impact").asInt();
|
||||||
|
}
|
||||||
|
newsTags.setSourceImpact(sourceImpact);
|
||||||
|
Double newsScore = null;
|
||||||
|
if (newsTagsNode.hasNonNull("news_score")) {
|
||||||
|
newsScore = newsTagsNode.get("news_score").asDouble();
|
||||||
|
}
|
||||||
|
newsTags.setNewsScore(newsScore);
|
||||||
|
Long newsId = null;
|
||||||
|
if (newsTagsNode.hasNonNull("news_id")) {
|
||||||
|
newsId = newsTagsNode.get("news_id").asLong();
|
||||||
|
}
|
||||||
|
newsTags.setNewsId(newsId);
|
||||||
|
Integer deleted = newsTagsNode.get("deleted").asInt();
|
||||||
|
newsTags.setDeleted(deleted);
|
||||||
|
Date createTime = getDateNodeValue(newsTagsNode.get("create_time").asText());
|
||||||
|
newsTags.setCreateTime(createTime);
|
||||||
|
Date updateTime = getDateNodeValue(newsTagsNode.get("update_time").asText());
|
||||||
|
newsTags.setUpdateTime(updateTime);
|
||||||
|
newsTagsMapper.save(newsTags);
|
||||||
|
|
||||||
|
NewsInfo newsInfo2 = new NewsInfo();
|
||||||
|
newsInfo2.setNewsTags(new NewsTags());
|
||||||
|
newsInfo2.getNewsTags().setIndustryLabel(industryLabel);
|
||||||
|
|
||||||
|
elasticsearchClient.update(e -> e.index(NewsInfo.INDEX_NAME).refresh(Refresh.True).id(id).doc(newsInfo2), NewsInfo.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ElasticsearchException|IOException e1) {
|
||||||
|
log.error("修复行业分类编码问题失败: ", e1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date getDateNodeValue(String dateStr) {
|
||||||
|
if (ObjectUtils.isEmpty(dateStr)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String pattern = "yyyy-MM-dd'T'HH:mm:ss";
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
|
||||||
|
try {
|
||||||
|
return sdf.parse(dateStr);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Double> doubleArrayNodeToList(JsonNode node) {
|
||||||
|
if (node.isArray()) {
|
||||||
|
int size = ((ArrayNode)node).size();
|
||||||
|
if (size == 0) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
List<Double> nodeValues = new ArrayList<>();
|
||||||
|
Iterator<JsonNode> iterator = ((ArrayNode)node).elements();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
nodeValues.add(iterator.next().asDouble());
|
||||||
|
}
|
||||||
|
return nodeValues;
|
||||||
|
}
|
||||||
|
double nodeValue = node.asDouble();
|
||||||
|
if (nodeValue > 0.0d) {
|
||||||
|
return Arrays.asList(nodeValue);
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> textArrayNodeToList(JsonNode node) {
|
||||||
|
if (node.isArray()) {
|
||||||
|
int size = ((ArrayNode)node).size();
|
||||||
|
if (size == 0) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
List<String> nodeValues = new ArrayList<>();
|
||||||
|
Iterator<JsonNode> iterator = ((ArrayNode)node).elements();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
nodeValues.add(iterator.next().asText());
|
||||||
|
}
|
||||||
|
return nodeValues;
|
||||||
|
}
|
||||||
|
String nodeValue = node.asText();
|
||||||
|
if (!ObjectUtils.isEmpty(nodeValue)) {
|
||||||
|
return Arrays.asList(nodeValue);
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getIndustryLabel(String unicodeIndustryLabel) {
|
||||||
|
if (ObjectUtils.isEmpty(unicodeIndustryLabel)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
unicodeIndustryLabel = unicodeIndustryLabel.replace("[", "").replace("]", "").replace("\"", "");
|
||||||
|
String industryLabel = unicodeDecode(unicodeIndustryLabel);
|
||||||
|
if (ObjectUtils.isEmpty(industryLabel)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return Stream.of(industryLabel.split(",")).map(e -> e.trim()).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String unicodeDecode(String unicodeIndustryLabel) {
|
||||||
|
if (!StringUtils.hasLength(unicodeIndustryLabel)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
|
||||||
|
Matcher matcher = pattern.matcher(unicodeIndustryLabel);
|
||||||
|
char ch;
|
||||||
|
while (matcher.find()) {
|
||||||
|
ch = (char) Integer.parseInt(matcher.group(2), 16);
|
||||||
|
unicodeIndustryLabel = unicodeIndustryLabel.replace(matcher.group(1), ch + "");
|
||||||
|
}
|
||||||
|
return unicodeIndustryLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// GET /news_info/_search
|
||||||
|
// {
|
||||||
|
// "size": 100,
|
||||||
|
// "query": {
|
||||||
|
// "bool": {
|
||||||
|
// "filter": [
|
||||||
|
// {
|
||||||
|
// "exists": {
|
||||||
|
// "field": "news_tags.industry_label"
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "script": {
|
||||||
|
// "script": {
|
||||||
|
// "lang": "painless",
|
||||||
|
// "source": "doc['news_tags.industry_label.keyword'][0].indexOf('[') == 0"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "wildcard": {
|
||||||
|
// "news_tags.industry_label": "*"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "sort": [
|
||||||
|
// {
|
||||||
|
// "create_time": {
|
||||||
|
// "order": "desc"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "track_total_hits": true
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@ public interface AdminUserMapper {
|
||||||
@Result(column = "phone", property = "phone"),
|
@Result(column = "phone", property = "phone"),
|
||||||
@Result(column = "name", property = "name"),
|
@Result(column = "name", property = "name"),
|
||||||
@Result(column = "active", property = "active"),
|
@Result(column = "active", property = "active"),
|
||||||
|
@Result(column = "user_type", property = "userType"),
|
||||||
@Result(column = "create_time", property = "createTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP),
|
@Result(column = "create_time", property = "createTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP),
|
||||||
@Result(column = "update_time", property = "updateTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP)
|
@Result(column = "update_time", property = "updateTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP)
|
||||||
})
|
})
|
||||||
|
|
@ -31,6 +32,7 @@ public interface AdminUserMapper {
|
||||||
@Result(column = "phone", property = "phone"),
|
@Result(column = "phone", property = "phone"),
|
||||||
@Result(column = "name", property = "name"),
|
@Result(column = "name", property = "name"),
|
||||||
@Result(column = "active", property = "active"),
|
@Result(column = "active", property = "active"),
|
||||||
|
@Result(column = "user_type", property = "userType"),
|
||||||
@Result(column = "create_time", property = "createTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP),
|
@Result(column = "create_time", property = "createTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP),
|
||||||
@Result(column = "update_time", property = "updateTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP)
|
@Result(column = "update_time", property = "updateTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 管理后台用户
|
* 管理后台用户
|
||||||
|
|
@ -32,6 +33,11 @@ public class AdminUser {
|
||||||
* true - 启动 | false - 禁用
|
* true - 启动 | false - 禁用
|
||||||
*/
|
*/
|
||||||
private boolean active;
|
private boolean active;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*/
|
||||||
|
private String userType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户创建时间
|
* 用户创建时间
|
||||||
|
|
@ -62,6 +68,10 @@ public class AdminUser {
|
||||||
this.name = value.asString();
|
this.name = value.asString();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "userType": {
|
||||||
|
this.userType = value.asString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "createTime": {
|
case "createTime": {
|
||||||
this.createTime = new Date(value.asLong());
|
this.createTime = new Date(value.asLong());
|
||||||
break;
|
break;
|
||||||
|
|
@ -122,4 +132,16 @@ public class AdminUser {
|
||||||
public void setUpdateTime(Date updateTime) {
|
public void setUpdateTime(Date updateTime) {
|
||||||
this.updateTime = updateTime;
|
this.updateTime = updateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setUserType(String userType) {
|
||||||
|
this.userType = userType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserType() {
|
||||||
|
return userType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReviewer() {
|
||||||
|
return Objects.equals(userType, "01");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,11 @@ public class LoginVO {
|
||||||
* 用户登陆Token
|
* 用户登陆Token
|
||||||
*/
|
*/
|
||||||
private String token;
|
private String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户类型
|
||||||
|
*/
|
||||||
|
private String userType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户创建时间
|
* 用户创建时间
|
||||||
|
|
@ -49,6 +54,7 @@ public class LoginVO {
|
||||||
this.phone = adminUser.getPhone();
|
this.phone = adminUser.getPhone();
|
||||||
this.name = adminUser.getName();
|
this.name = adminUser.getName();
|
||||||
this.token = AdminJwtService.generateToken(adminUser);
|
this.token = AdminJwtService.generateToken(adminUser);
|
||||||
|
this.userType = adminUser.getUserType();
|
||||||
this.createTime = adminUser.getCreateTime();
|
this.createTime = adminUser.getCreateTime();
|
||||||
this.updateTime = adminUser.getUpdateTime();
|
this.updateTime = adminUser.getUpdateTime();
|
||||||
}
|
}
|
||||||
|
|
@ -100,4 +106,12 @@ public class LoginVO {
|
||||||
public void setUpdateTime(Date updateTime) {
|
public void setUpdateTime(Date updateTime) {
|
||||||
this.updateTime = updateTime;
|
this.updateTime = updateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUserType() {
|
||||||
|
return userType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserType(String userType) {
|
||||||
|
this.userType = userType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,14 @@ public final class AdminJwtService {
|
||||||
Long id = adminUser.getId();
|
Long id = adminUser.getId();
|
||||||
String phone = adminUser.getPhone();
|
String phone = adminUser.getPhone();
|
||||||
String name = adminUser.getName();
|
String name = adminUser.getName();
|
||||||
|
String userType = adminUser.getUserType();
|
||||||
long createTime = adminUser.getCreateTime().getTime();
|
long createTime = adminUser.getCreateTime().getTime();
|
||||||
long updateTime = adminUser.getUpdateTime().getTime();
|
long updateTime = adminUser.getUpdateTime().getTime();
|
||||||
JWTCreator.Builder jwtBuilder = JWT.create();
|
JWTCreator.Builder jwtBuilder = JWT.create();
|
||||||
jwtBuilder.withClaim("id", id);
|
jwtBuilder.withClaim("id", id);
|
||||||
jwtBuilder.withClaim("phone", phone);
|
jwtBuilder.withClaim("phone", phone);
|
||||||
jwtBuilder.withClaim("name", name);
|
jwtBuilder.withClaim("name", name);
|
||||||
|
jwtBuilder.withClaim("userType", userType);
|
||||||
jwtBuilder.withClaim("createTime", createTime);
|
jwtBuilder.withClaim("createTime", createTime);
|
||||||
jwtBuilder.withClaim("updateTime", updateTime);
|
jwtBuilder.withClaim("updateTime", updateTime);
|
||||||
jwtBuilder.withClaim("timestamp", System.currentTimeMillis());
|
jwtBuilder.withClaim("timestamp", System.currentTimeMillis());
|
||||||
|
|
@ -47,6 +49,7 @@ public final class AdminJwtService {
|
||||||
.withClaimPresence("id")
|
.withClaimPresence("id")
|
||||||
.withClaimPresence("phone")
|
.withClaimPresence("phone")
|
||||||
.withClaimPresence("name")
|
.withClaimPresence("name")
|
||||||
|
.withClaimPresence("userType")
|
||||||
.withClaimPresence("createTime")
|
.withClaimPresence("createTime")
|
||||||
.withClaimPresence("updateTime")
|
.withClaimPresence("updateTime")
|
||||||
.withClaimPresence("timestamp")
|
.withClaimPresence("timestamp")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,15 @@
|
||||||
package com.jinrui.reference.admin.service;
|
package com.jinrui.reference.admin.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.jinrui.reference.admin.mapper.AdminUserMapper;
|
import com.jinrui.reference.admin.mapper.AdminUserMapper;
|
||||||
|
|
@ -9,19 +19,10 @@ import com.jinrui.reference.admin.model.vo.admin.user.AdminUserVO;
|
||||||
import com.jinrui.reference.admin.model.vo.login.LoginVO;
|
import com.jinrui.reference.admin.model.vo.login.LoginVO;
|
||||||
import com.jinrui.reference.core.model.vo.PageObject;
|
import com.jinrui.reference.core.model.vo.PageObject;
|
||||||
import com.jinrui.reference.core.model.vo.ResultObject;
|
import com.jinrui.reference.core.model.vo.ResultObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.JedisPool;
|
import redis.clients.jedis.JedisPool;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class AdminUserService {
|
public class AdminUserService {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.jinrui.reference.admin.service;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.jinrui.reference.admin.model.entity.AdminUser;
|
||||||
|
import com.jinrui.reference.core.mapper.UserOperationLogMapper;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UserOperationLogService {
|
||||||
|
|
||||||
|
private final UserOperationLogMapper userOperationLogMapper;
|
||||||
|
|
||||||
|
public UserOperationLogService(UserOperationLogMapper userOperationLogMapper) {
|
||||||
|
this.userOperationLogMapper = userOperationLogMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logUserOperation(String type, String behavior, String token, Long dataId) {
|
||||||
|
AdminUser adminUser = AdminJwtService.parseToken(token);
|
||||||
|
userOperationLogMapper.save(adminUser.getId(), adminUser.getName(), adminUser.getUserType(), dataId, type, behavior);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
/application-prod.yml
|
||||||
|
|
@ -1,13 +1,50 @@
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
root: DEBUG
|
root: DEBUG
|
||||||
|
server:
|
||||||
|
port: 13579
|
||||||
|
compression:
|
||||||
|
enabled: true
|
||||||
|
servlet:
|
||||||
|
context-path: /admin
|
||||||
|
oss:
|
||||||
|
ak: LTAI5t8z9QNdCG6b54mDgx8p
|
||||||
|
sk: F3M41hTgH8g99ZgVWyelj42825YbZM
|
||||||
|
roleArn: acs:ram::1647420045565932:role/ramoss
|
||||||
|
endPoint: oss-cn-hangzhou.aliyuncs.com
|
||||||
|
region: oss-cn-hangzhou
|
||||||
|
bucketName: lengfeng-test
|
||||||
|
baseUrl: https://lengfeng-test.oss-cn-hangzhou.aliyuncs.com
|
||||||
|
sts:
|
||||||
|
endPoint: sts.cn-hangzhou.aliyuncs.com
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
type: com.zaxxer.hikari.HikariDataSource
|
type: com.zaxxer.hikari.HikariDataSource
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://127.0.0.1:3306/reference?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&allowMultiQueries=true
|
# 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
|
username: root
|
||||||
password: Aa123456@
|
password: Xgf_8000
|
||||||
redis:
|
redis:
|
||||||
host: 127.0.0.1
|
# host: 192.168.0.172
|
||||||
|
# port: 6379
|
||||||
|
# password: Xgf_redis
|
||||||
|
host: 123.60.153.169
|
||||||
port: 6379
|
port: 6379
|
||||||
|
password: Xgf_redis
|
||||||
|
elasticsearch:
|
||||||
|
scheme: http
|
||||||
|
# 111.13.176.3 部署地址
|
||||||
|
# 10.127.2.194 本地测试地址
|
||||||
|
host: 111.13.176.3
|
||||||
|
port: 9200
|
||||||
|
enable: true
|
||||||
|
username: elastic
|
||||||
|
password: ZxE,3VM@Thk0
|
||||||
|
mybatis:
|
||||||
|
type-handlers-package:com.jinrui.reference.core.typehandler
|
||||||
|
api:
|
||||||
|
key: WBysu6N1z26AbA12l
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
root: DEBUG
|
||||||
server:
|
server:
|
||||||
port: 13579
|
port: 13579
|
||||||
compression:
|
compression:
|
||||||
|
|
@ -36,7 +39,7 @@ elasticsearch:
|
||||||
scheme: http
|
scheme: http
|
||||||
# 111.13.176.3 部署地址
|
# 111.13.176.3 部署地址
|
||||||
# 10.127.2.194 本地测试地址
|
# 10.127.2.194 本地测试地址
|
||||||
host: 10.127.2.194
|
host: 111.13.176.3
|
||||||
port: 9200
|
port: 9200
|
||||||
enable: true
|
enable: true
|
||||||
username: elastic
|
username: elastic
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
ALTER TABLE `reference`.`news`
|
||||||
|
ADD COLUMN `revision` TEXT NULL AFTER `rating`;
|
||||||
|
|
||||||
|
ALTER TABLE `reference`.`admin_user`
|
||||||
|
ADD COLUMN `user_type` CHAR(2) NULL DEFAULT '00' AFTER `active`;
|
||||||
|
|
@ -39,6 +39,10 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mysql</groupId>
|
<groupId>com.mysql</groupId>
|
||||||
<artifactId>mysql-connector-j</artifactId>
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
|
|
@ -86,6 +90,11 @@
|
||||||
<artifactId>jakarta.json-api</artifactId>
|
<artifactId>jakarta.json-api</artifactId>
|
||||||
<version>${jakartajson.version}</version>
|
<version>${jakartajson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>redis.clients</groupId>
|
||||||
|
<artifactId>jedis</artifactId>
|
||||||
|
<version>${jedis.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.jinrui.reference.core;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
import redis.clients.jedis.JedisPoolConfig;
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RedisConfig {
|
||||||
|
@Value("${redis.host}")
|
||||||
|
private String host;
|
||||||
|
|
||||||
|
@Value("${redis.port}")
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
@Value("${redis.timeout:1000}")
|
||||||
|
private int timeout;
|
||||||
|
|
||||||
|
@Value("${redis.password:}")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JedisPool jedisPool() {
|
||||||
|
if (StringUtils.hasText(password)) {
|
||||||
|
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
|
||||||
|
return new JedisPool(jedisPoolConfig, host, port, timeout, password);
|
||||||
|
}
|
||||||
|
return new JedisPool(host, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
package com.jinrui.reference.core;
|
package com.jinrui.reference.core;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import com.jinrui.reference.core.interceptor.ApiAuthInterceptor;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class WebConfig implements WebMvcConfigurer {
|
public class WebConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
|
@ -18,4 +24,15 @@ public class WebConfig implements WebMvcConfigurer {
|
||||||
.allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH")
|
.allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH")
|
||||||
.maxAge(3600);
|
.maxAge(3600);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ApiAuthInterceptor apiAuthInterceptor() {
|
||||||
|
return new ApiAuthInterceptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
registry.addInterceptor(apiAuthInterceptor())
|
||||||
|
.addPathPatterns("/api/**").excludePathPatterns("/api/key"); // 拦截API路径
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.jinrui.reference.core.api;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ApiKeyGenerator {
|
||||||
|
public static String generateAK() {
|
||||||
|
return UUID.randomUUID().toString().replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateSK() {
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
byte[] bytes = new byte[32]; // 256位密钥
|
||||||
|
random.nextBytes(bytes);
|
||||||
|
return Base64.getEncoder().encodeToString(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.jinrui.reference.core.api;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
|
||||||
|
public enum ApiReturnCode {
|
||||||
|
ILLEGAL_HEADER("10001", "缺失API相关的请求头参数!"),
|
||||||
|
REPLAY_ERROR("10002", "请求超时或重复请求!"),
|
||||||
|
KEY_ERROR("10003", "请求的KEY非法!"),
|
||||||
|
ARGUMENT_ERROR("10004", "参数签名错误!");
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String msg;
|
||||||
|
|
||||||
|
private ApiReturnCode(String code, String msg) {
|
||||||
|
this.code = code;
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
package com.jinrui.reference.core.interceptor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Hex;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.jinrui.reference.core.api.ApiReturnCode;
|
||||||
|
import com.jinrui.reference.core.service.ApiKeyService;
|
||||||
|
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
import redis.clients.jedis.params.SetParams;
|
||||||
|
|
||||||
|
public class ApiAuthInterceptor implements HandlerInterceptor {
|
||||||
|
public static final Logger LOGGER = LoggerFactory.getLogger(ApiAuthInterceptor.class);
|
||||||
|
public static final Long REQUEST_TIMEOUT = 300L;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApiKeyService apiKeyService; // 从数据库查询SK
|
||||||
|
@Autowired
|
||||||
|
private JedisPool jedisPool;
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws InvalidKeyException, NoSuchAlgorithmException {
|
||||||
|
String ak = request.getHeader("X-Api-Key");
|
||||||
|
String timestamp = request.getHeader("X-Timestamp");
|
||||||
|
String nonce = request.getHeader("X-Nonce");
|
||||||
|
String clientSign = request.getHeader("X-Signature");
|
||||||
|
|
||||||
|
// 1. 校验基础参数
|
||||||
|
if (!StringUtils.hasLength(ak) || !StringUtils.hasLength(timestamp)
|
||||||
|
|| !StringUtils.hasLength(nonce) || !StringUtils.hasLength(clientSign)) {
|
||||||
|
responseToFailed(response, ApiReturnCode.ILLEGAL_HEADER);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 防重放:时间戳有效期5分钟
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
if (Math.abs(currentTime - Long.parseLong(timestamp)) > REQUEST_TIMEOUT * 1000) {
|
||||||
|
responseToFailed(response, ApiReturnCode.REPLAY_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 3. 校验nonce唯一性(Redis实现)
|
||||||
|
try(Jedis jedis = jedisPool.getResource()) {
|
||||||
|
if (jedis.exists(nonce)) {
|
||||||
|
responseToFailed(response, ApiReturnCode.REPLAY_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
jedis.set(nonce, "", SetParams.setParams().ex(REQUEST_TIMEOUT));
|
||||||
|
} catch(Exception e) {
|
||||||
|
LOGGER.error("获取redis对象失败", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 获取SK并计算服务端签名
|
||||||
|
String sk = apiKeyService.getSecretKeyByAk(ak);
|
||||||
|
if (ObjectUtils.isEmpty(sk)) {
|
||||||
|
responseToFailed(response, ApiReturnCode.KEY_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String serverSign = calculateSignature(request, sk, timestamp, nonce);
|
||||||
|
|
||||||
|
// 5. 比对签名
|
||||||
|
if (!serverSign.equals(clientSign)) {
|
||||||
|
responseToFailed(response, ApiReturnCode.ARGUMENT_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String calculateSignature(HttpServletRequest request, String sk, String timestamp, String nonce) throws NoSuchAlgorithmException, InvalidKeyException {
|
||||||
|
// 拼接请求数据:方法+路径+排序后的参数
|
||||||
|
String method = request.getMethod();
|
||||||
|
String path = request.getRequestURI();
|
||||||
|
|
||||||
|
String params = getSortedParams(request);
|
||||||
|
String data = method + path + params + timestamp + nonce;
|
||||||
|
|
||||||
|
// HMAC-SHA256签名
|
||||||
|
Mac sha256 = Mac.getInstance("HmacSHA256");
|
||||||
|
sha256.init(new SecretKeySpec(sk.getBytes(), "HmacSHA256"));
|
||||||
|
byte[] signBytes = sha256.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return Hex.encodeHexString(signBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSortedParams(HttpServletRequest request) {
|
||||||
|
// 获取请求参数(目前只考虑query string类型的参数,暂不支持application/json格式参数
|
||||||
|
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||||
|
String sortedQueryString = parameterMap.entrySet().stream().filter(e -> !ObjectUtils.isEmpty(e.getValue())).sorted(Map.Entry.comparingByKey())
|
||||||
|
.map(e -> e.getKey() + "=" + String.join(",", e.getValue())).collect(Collectors.joining("&"));
|
||||||
|
return sortedQueryString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void responseToFailed(HttpServletResponse response, ApiReturnCode apiReturnCode) {
|
||||||
|
try {
|
||||||
|
response.setStatus(200);
|
||||||
|
response.setContentType("application/json");
|
||||||
|
response.setCharacterEncoding("utf-8");
|
||||||
|
response.getWriter().print(objectMapper.writeValueAsString(apiReturnCode));
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.jinrui.reference.core.mapper;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Insert;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
public interface ApiUserMapper {
|
||||||
|
@Select("select secret_key from api_user where access_key = #{ak} and disabled = 0")
|
||||||
|
String getClientSecretkey(@Param("ak") String ak);
|
||||||
|
|
||||||
|
@Select("select access_key, secret_key from api_user where client_name = #{clientName} and disabled = 0")
|
||||||
|
Map<String, Object> getClientKey(@Param("clientName") String clientName);
|
||||||
|
|
||||||
|
@Insert("insert into api_user(client_name, access_key, secret_key)" +
|
||||||
|
"values (#{clientName}, #{accessKey}, #{secretKey})")
|
||||||
|
void save(@Param("clientName") String clientName, @Param("accessKey") String accessKey, @Param("secretKey") String secretKey);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.jinrui.reference.core.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Insert;
|
||||||
|
|
||||||
|
import com.jinrui.reference.core.model.entity.NewsDeleted;
|
||||||
|
|
||||||
|
public interface NewsDeletedMapper {
|
||||||
|
@Insert("insert into news_deleted(news_id, newsinfo_id, cluster_id, deleted_time)" +
|
||||||
|
"values (#{newsId}, #{newsinfoId}, #{clusterId}, now())")
|
||||||
|
void save(NewsDeleted newsDeleted);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -7,16 +7,23 @@ import org.apache.ibatis.annotations.Delete;
|
||||||
import org.apache.ibatis.annotations.Insert;
|
import org.apache.ibatis.annotations.Insert;
|
||||||
import org.apache.ibatis.annotations.Options;
|
import org.apache.ibatis.annotations.Options;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Result;
|
||||||
|
import org.apache.ibatis.annotations.Results;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
import org.apache.ibatis.annotations.Update;
|
import org.apache.ibatis.annotations.Update;
|
||||||
|
|
||||||
import com.jinrui.reference.core.model.entity.News;
|
import com.jinrui.reference.core.model.entity.News;
|
||||||
import com.jinrui.reference.core.model.entity.NewsDraft;
|
import com.jinrui.reference.core.model.entity.NewsDraft;
|
||||||
|
import com.jinrui.reference.core.model.vo.news.NewsApiVO;
|
||||||
|
import com.jinrui.reference.core.typehandler.JsonArrayTypeHandler;
|
||||||
|
|
||||||
public interface NewsMapper {
|
public interface NewsMapper {
|
||||||
|
|
||||||
@Delete("delete from news where id = #{newsId}")
|
@Delete("update news set is_delete = 1, update_time = now(), editor_id = #{editorId} where id = #{newsId} and status = 1")
|
||||||
void deleteNews(@Param("newsId") Long newsId);
|
int deleteNews(@Param("newsId") Long newsId, @Param("editorId") Long editorId);
|
||||||
|
|
||||||
|
@Delete("update news set is_delete = 0, update_time = now(), editor_id = #{editorId} where id = #{newsId}")
|
||||||
|
void recoverNews(@Param("newsId") Long newsId, @Param("editorId") Long editorId);
|
||||||
|
|
||||||
@Delete("delete from news_draft where id = #{draftId}")
|
@Delete("delete from news_draft where id = #{draftId}")
|
||||||
void deleteDraft(@Param("draftId") Long draftId);
|
void deleteDraft(@Param("draftId") Long draftId);
|
||||||
|
|
@ -27,75 +34,60 @@ public interface NewsMapper {
|
||||||
"from news_draft where id = #{id}")
|
"from news_draft where id = #{id}")
|
||||||
NewsDraft getDraftDetail(@Param("id") Long id);
|
NewsDraft getDraftDetail(@Param("id") Long id);
|
||||||
|
|
||||||
@Select("select id, title, summary, picture, content, " +
|
@Select("select id, llm_title as title, summary, picture, llm_content as content, " +
|
||||||
"create_time as createTime, " +
|
"create_time as createTime, " +
|
||||||
"update_time as updateTime " +
|
"update_time as updateTime, " +
|
||||||
|
"is_delete as deleted, " +
|
||||||
|
"rating, " +
|
||||||
|
"revision, " +
|
||||||
|
"newsinfo_id as newsinfoId " +
|
||||||
"from news where id = #{id}")
|
"from news where id = #{id}")
|
||||||
News getNewsDetail(@Param("id") Long id);
|
News getNewsDetail(@Param("id") Long id);
|
||||||
|
|
||||||
@Update("update news set status = 1, update_time = now() where id = #{id}")
|
@Update("update news set status = #{newStatus}, update_time = now(), editor_id = #{editorId} where id = #{id} and status = #{oldStatus}")
|
||||||
void simpleUnpublish(@Param("id") long id);
|
int changeFrom(@Param("id") long id, @Param("oldStatus") int oldStatus, @Param("newStatus") int newStatus, @Param("editorId") long editorId);
|
||||||
|
|
||||||
@Update("update news set status = 2, update_time = now(), editor_id = #{editorId} where id = #{id}")
|
|
||||||
void simplePublish(@Param("id") long id, @Param("editorId") long editorId);
|
|
||||||
|
|
||||||
@Update("update news " +
|
@Update("update news " +
|
||||||
"set draft_id = #{draftId}," +
|
"set editor_id = #{news.editorId}," +
|
||||||
"editor_id = #{editorId}," +
|
"draft_id = #{news.draftId}, " +
|
||||||
"title = #{title}," +
|
"llm_title = #{news.title}," +
|
||||||
"summary = #{summary}," +
|
"summary = #{news.summary}," +
|
||||||
"picture = #{picture}," +
|
"picture = #{news.picture}," +
|
||||||
"content = #{content}," +
|
"llm_content = #{news.content}," +
|
||||||
"content_text = #{contentText}," +
|
"content_text = #{news.contentText}," +
|
||||||
"status = #{status}," +
|
"status = #{news.status}," +
|
||||||
"newsinfo_id = #{newsinfoId}," +
|
"newsinfo_id = #{news.newsinfoId}," +
|
||||||
"update_time = now() " +
|
"rating = #{news.rating}," +
|
||||||
"where id = #{id}")
|
"revision = #{news.revision}," +
|
||||||
void updateNews(News news);
|
|
||||||
|
|
||||||
@Update("update news " +
|
|
||||||
"set editor_id = #{editorId}," +
|
|
||||||
"draft_id = NULL, " +
|
|
||||||
"title = #{title}," +
|
|
||||||
"summary = #{summary}," +
|
|
||||||
"picture = #{picture}," +
|
|
||||||
"content = #{content}," +
|
|
||||||
"content_text = #{contentText}," +
|
|
||||||
"status = #{status}," +
|
|
||||||
"update_time = now()" +
|
"update_time = now()" +
|
||||||
"where id = #{id}")
|
"where id = #{news.id} and status = #{oldStatus}")
|
||||||
void publishNews(News news);
|
int updateNews(News news, Integer oldStatus);
|
||||||
|
|
||||||
@Select("select id, draft_id as draftId, status, newsinfo_id as newsinfoId from news where id = #{id}")
|
@Select("select id, draft_id as draftId, status, newsinfo_id as newsinfoId, is_delete as deleted, rating, revision from news where id = #{id}")
|
||||||
News getById(@Param("id") Long id);
|
News getById(@Param("id") Long id);
|
||||||
|
|
||||||
@Select("select last_insert_id()")
|
|
||||||
Long getLastInsertId();
|
|
||||||
|
|
||||||
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
|
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
|
||||||
@Insert("insert into news_draft(title, summary, picture, type, content, create_time, update_time)" +
|
@Insert("insert into news_draft(title, summary, picture, type, content, create_time, update_time)" +
|
||||||
"values (#{title}, #{summary}, #{picture}, #{type}, #{content}, now(), now())")
|
"values (#{title}, #{summary}, #{picture}, #{type}, #{content}, now(), now())")
|
||||||
void saveDraft(NewsDraft newsDraft);
|
void saveDraft(NewsDraft newsDraft);
|
||||||
|
|
||||||
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
|
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
|
||||||
@Insert("insert into news(draft_id, title, summary, picture, type, content, create_time, update_time, status, publish_time, content_text, newsinfo_id)" +
|
@Insert("insert into news(draft_id, title, summary, picture, type, content, create_time, update_time, status, publish_time, content_text, newsinfo_id, llm_title, llm_content, rating)" +
|
||||||
"values (#{draftId}, #{title}, #{summary}, #{picture}, #{type}, #{content}, now(), now(), #{status}, #{publishTime}, #{contentText}, #{newsinfoId})")
|
"values (#{draftId}, #{title}, #{summary}, #{picture}, #{type}, #{content}, now(), now(), #{status}, #{publishTime}, #{contentText}, #{newsinfoId}, #{llmTitle}, #{llmContent}, #{rating})")
|
||||||
void saveNews(News news);
|
void saveNews(News news);
|
||||||
|
|
||||||
|
|
||||||
@Select("SELECT MAX(id) AS max_id FROM news")
|
|
||||||
Long getNewsLastInsertId();
|
|
||||||
|
|
||||||
@Select("<script>" +
|
@Select("<script>" +
|
||||||
"select distinct " +
|
"select distinct " +
|
||||||
"news.id as id," +
|
"news.id as id," +
|
||||||
"news.draft_id as draftId," +
|
"news.draft_id as draftId," +
|
||||||
"news.title as title," +
|
"news.llm_title as title," +
|
||||||
"news.status as status," +
|
"news.status as status," +
|
||||||
"news.create_time as createTime," +
|
"news.create_time as createTime," +
|
||||||
"news.publish_time as publishTime," +
|
"news.publish_time as publishTime," +
|
||||||
"news.update_time as updateTime, " +
|
"news.update_time as updateTime, " +
|
||||||
"news.newsinfo_id as newsinfoId, " +
|
"news.newsinfo_id as newsinfoId, " +
|
||||||
|
"news.is_delete as deleted, " +
|
||||||
|
"news.rating as rating, " +
|
||||||
"news_tags.news_score as score " +
|
"news_tags.news_score as score " +
|
||||||
"from news " +
|
"from news " +
|
||||||
"<if test=\"column != null and !column.isEmpty()\">" +
|
"<if test=\"column != null and !column.isEmpty()\">" +
|
||||||
|
|
@ -121,7 +113,7 @@ public interface NewsMapper {
|
||||||
"<if test=\"keywords != null and !keywords.isEmpty()\">" +
|
"<if test=\"keywords != null and !keywords.isEmpty()\">" +
|
||||||
" and " +
|
" and " +
|
||||||
"<foreach collection=\"keywords\" item=\"keyword\" open=\"(\" close=\")\" separator=\"or\">\n" +
|
"<foreach collection=\"keywords\" item=\"keyword\" open=\"(\" close=\")\" separator=\"or\">\n" +
|
||||||
" (news.title like concat('%', #{keyword}, '%') or news.content like concat('%', #{keyword}, '%')) " +
|
" (news.llm_title like concat('%', #{keyword}, '%') or news.llm_content like concat('%', #{keyword}, '%')) " +
|
||||||
"</foreach>" +
|
"</foreach>" +
|
||||||
"</if>" +
|
"</if>" +
|
||||||
"<if test=\"datelineFrom != null\">" +
|
"<if test=\"datelineFrom != null\">" +
|
||||||
|
|
@ -142,9 +134,18 @@ public interface NewsMapper {
|
||||||
"<if test=\"status != null\">" +
|
"<if test=\"status != null\">" +
|
||||||
"and news.status = #{status} " +
|
"and news.status = #{status} " +
|
||||||
"</if>" +
|
"</if>" +
|
||||||
|
"<if test=\"deleted != null\">" +
|
||||||
|
"and news.is_delete = #{deleted} " +
|
||||||
|
"</if>" +
|
||||||
|
"<if test=\"rating != null\">" +
|
||||||
|
"and news.rating = #{rating} " +
|
||||||
|
"</if>" +
|
||||||
"<if test=\"last != null\">" +
|
"<if test=\"last != null\">" +
|
||||||
"and news.id > #{last}" +
|
"and news.id > #{last}" +
|
||||||
"</if>" +
|
"</if>" +
|
||||||
|
"<if test=\"isReviewer == true\">" +
|
||||||
|
"and news.status in (2, 3) " +
|
||||||
|
"</if>" +
|
||||||
"</where>" +
|
"</where>" +
|
||||||
"<if test=\"orderBy != null\">" +
|
"<if test=\"orderBy != null\">" +
|
||||||
"order by ${orderBy} " +
|
"order by ${orderBy} " +
|
||||||
|
|
@ -163,7 +164,10 @@ public interface NewsMapper {
|
||||||
@Param("tags") List<Long> tags,
|
@Param("tags") List<Long> tags,
|
||||||
@Param("industries") List<Long> industries,
|
@Param("industries") List<Long> industries,
|
||||||
@Param("datelineFrom") Date datelineFrom,
|
@Param("datelineFrom") Date datelineFrom,
|
||||||
@Param("datelineTo") Date datelineTo);
|
@Param("datelineTo") Date datelineTo,
|
||||||
|
@Param("deleted") Integer deleted,
|
||||||
|
@Param("rating") Byte rating,
|
||||||
|
@Param("isReviewer") boolean isReviewer);
|
||||||
|
|
||||||
@Select("<script>" +
|
@Select("<script>" +
|
||||||
"select count(*) from (select distinct news.* from news " +
|
"select count(*) from (select distinct news.* from news " +
|
||||||
|
|
@ -192,7 +196,7 @@ public interface NewsMapper {
|
||||||
"<if test=\"keywords != null and !keywords.isEmpty()\">" +
|
"<if test=\"keywords != null and !keywords.isEmpty()\">" +
|
||||||
" and " +
|
" and " +
|
||||||
"<foreach collection=\"keywords\" item=\"keyword\" open=\"(\" close=\")\" separator=\"or\">\n" +
|
"<foreach collection=\"keywords\" item=\"keyword\" open=\"(\" close=\")\" separator=\"or\">\n" +
|
||||||
" (news.title like concat('%', #{keyword}, '%') or news.content like concat('%', #{keyword}, '%')) " +
|
" (news.llm_title like concat('%', #{keyword}, '%') or news.llm_content like concat('%', #{keyword}, '%')) " +
|
||||||
"</foreach>" +
|
"</foreach>" +
|
||||||
"</if>" +
|
"</if>" +
|
||||||
"<if test=\"datelineFrom != null\">" +
|
"<if test=\"datelineFrom != null\">" +
|
||||||
|
|
@ -213,6 +217,15 @@ public interface NewsMapper {
|
||||||
"<if test=\"status != null\">" +
|
"<if test=\"status != null\">" +
|
||||||
"and news.status = #{status} " +
|
"and news.status = #{status} " +
|
||||||
"</if>" +
|
"</if>" +
|
||||||
|
"<if test=\"deleted != null\">" +
|
||||||
|
"and news.is_delete = #{deleted} " +
|
||||||
|
"</if>" +
|
||||||
|
"<if test=\"rating != null\">" +
|
||||||
|
"and news.rating = #{rating} " +
|
||||||
|
"</if>" +
|
||||||
|
"<if test=\"isReviewer == true\">" +
|
||||||
|
"and news.status in (2, 3) " +
|
||||||
|
"</if>" +
|
||||||
"</where>) tmp" +
|
"</where>) tmp" +
|
||||||
"</script>")
|
"</script>")
|
||||||
int queryTotal(@Param("keywords") List<String> keywords,
|
int queryTotal(@Param("keywords") List<String> keywords,
|
||||||
|
|
@ -223,12 +236,74 @@ public interface NewsMapper {
|
||||||
@Param("tags") List<Long> tags,
|
@Param("tags") List<Long> tags,
|
||||||
@Param("industries") List<Long> industries,
|
@Param("industries") List<Long> industries,
|
||||||
@Param("datelineFrom") Date datelineFrom,
|
@Param("datelineFrom") Date datelineFrom,
|
||||||
@Param("datelineTo") Date datelineTo);
|
@Param("datelineTo") Date datelineTo,
|
||||||
|
@Param("deleted") Integer deleted,
|
||||||
|
@Param("rating") Byte rating,
|
||||||
|
@Param("isReviewer") boolean isReviewer);
|
||||||
|
|
||||||
@Select("select id, title, summary, picture, content, status, " +
|
@Select("select id, llm_title as title, summary, picture, llm_content as content, status, " +
|
||||||
"create_time as createTime, " +
|
"create_time as createTime, " +
|
||||||
"publish_time as publishTime, " +
|
"publish_time as publishTime, " +
|
||||||
"update_time as updateTime " +
|
"update_time as updateTime " +
|
||||||
"from news where newsinfo_id = #{newsinfoId}")
|
"from news where newsinfo_id = #{newsinfoId}")
|
||||||
News getNewsDetailByNewsInfoId(@Param("newsinfoId") String newsinfoId);
|
News getNewsDetailByNewsInfoId(@Param("newsinfoId") String newsinfoId);
|
||||||
|
|
||||||
|
@Select("SELECT cluster_id FROM news WHERE newsinfo_id IS NOT NULL AND cluster_id IS NOT NULL GROUP BY cluster_id HAVING COUNT(*) > 1")
|
||||||
|
List<String> getDuplicatedCluster();
|
||||||
|
|
||||||
|
@Select("select id, draft_id as draftId, newsinfo_id as newsinfoId, is_delete as deleted, editor_id as editorId from news where cluster_id = #{clusterId} and newsinfo_id IS NOT NULL")
|
||||||
|
List<News> getDuplicatedNews(@Param("clusterId") String clusterId);
|
||||||
|
|
||||||
|
@Delete("delete from news where id = #{id}")
|
||||||
|
void deleteById(@Param("id") Long id);
|
||||||
|
|
||||||
|
|
||||||
|
@Results({
|
||||||
|
@Result(column = "id", property = "id", id = true),
|
||||||
|
@Result(column = "llm_title", property = "title"),
|
||||||
|
@Result(column = "llm_content", property = "content"),
|
||||||
|
@Result(column = "summary", property = "summary"),
|
||||||
|
@Result(column = "publish_time", property = "publishTime"),
|
||||||
|
@Result(column = "industry_label", property = "industryLabel", typeHandler = JsonArrayTypeHandler.class),
|
||||||
|
@Result(column = "industry_confidence", property = "industryConfidence", typeHandler = JsonArrayTypeHandler.class),
|
||||||
|
@Result(column = "industry_score", property = "industryScore", typeHandler = JsonArrayTypeHandler.class),
|
||||||
|
@Result(column = "concept_label", property = "conceptLabel", typeHandler = JsonArrayTypeHandler.class),
|
||||||
|
@Result(column = "concept_confidence", property = "conceptConfidence", typeHandler = JsonArrayTypeHandler.class),
|
||||||
|
@Result(column = "concept_score", property = "conceptScore", typeHandler = JsonArrayTypeHandler.class),
|
||||||
|
@Result(column = "source", property = "source"),
|
||||||
|
@Result(column = "source_impact", property = "sourceImpact"),
|
||||||
|
@Result(column = "China_factor", property = "chinaFactor"),
|
||||||
|
@Result(column = "public_opinion_score", property = "publicOpinionScore"),
|
||||||
|
@Result(column = "news_score", property = "newsScore"),
|
||||||
|
})
|
||||||
|
@Select("<script>" +
|
||||||
|
"select " +
|
||||||
|
"news.id as id," +
|
||||||
|
"news.llm_title," +
|
||||||
|
"news.llm_content," +
|
||||||
|
"news.summary, " +
|
||||||
|
"news.publish_time," +
|
||||||
|
"news_tags.news_score, " +
|
||||||
|
"news_tags.source, " +
|
||||||
|
"news_tags.industry_label, " +
|
||||||
|
"news_tags.industry_confidence," +
|
||||||
|
"news_tags.industry_score," +
|
||||||
|
"news_tags.concept_label," +
|
||||||
|
"news_tags.concept_confidence," +
|
||||||
|
"news_tags.concept_score," +
|
||||||
|
"news_tags.source_impact," +
|
||||||
|
"news_tags.China_factor," +
|
||||||
|
"news_tags.public_opinion_score" +
|
||||||
|
"from news " +
|
||||||
|
" left join news_tags on news.newsinfo_id = news_tags.newsinfo_id " +
|
||||||
|
"<where>" +
|
||||||
|
" news.status = 2 and news.is_delete = 0 and news.publish_time >= adddate(date(now()), -2) " +
|
||||||
|
"<if test=\"last != null\">" +
|
||||||
|
"and news.id > #{last}" +
|
||||||
|
"</if>" +
|
||||||
|
"</where>" +
|
||||||
|
"order by id desc " +
|
||||||
|
"limit ${limit}" +
|
||||||
|
"</script>")
|
||||||
|
List<NewsApiVO> queryNewsByApi(@Param("last") Long last, @Param("limit") int limit);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
package com.jinrui.reference.core.mapper;
|
package com.jinrui.reference.core.mapper;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Insert;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Result;
|
import org.apache.ibatis.annotations.Result;
|
||||||
import org.apache.ibatis.annotations.Results;
|
import org.apache.ibatis.annotations.Results;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import com.jinrui.reference.core.model.entity.News;
|
||||||
import com.jinrui.reference.core.model.entity.NewsTags;
|
import com.jinrui.reference.core.model.entity.NewsTags;
|
||||||
import com.jinrui.reference.core.typehandler.JsonArrayTypeHandler;
|
import com.jinrui.reference.core.typehandler.JsonArrayTypeHandler;
|
||||||
|
|
||||||
|
|
@ -32,4 +34,8 @@ public interface NewsTagsMapper {
|
||||||
})
|
})
|
||||||
@Select("select * from news_tags where newsinfo_id = #{newsId}")
|
@Select("select * from news_tags where newsinfo_id = #{newsId}")
|
||||||
NewsTags getNewsTagsByNewsId(@Param("newsId") String newsId);
|
NewsTags getNewsTagsByNewsId(@Param("newsId") String newsId);
|
||||||
|
|
||||||
|
@Insert("insert into news_tags(abstract, title, rewrite_content, industry_label, industry_confidence, industry_score, concept_label, concept_confidence, concept_score, source, source_impact, China_factor, public_opinion_score, news_score, news_id, deleted, create_time, update_time)" +
|
||||||
|
"values (#{summary}, #{title}, #{rewriteContent}, #{industryLabel, jdbcType=VARCHAR,typeHandler=com.jinrui.reference.core.typehandler.JsonArrayTypeHandler}, #{industryConfidence,jdbcType=VARCHAR,typeHandler=com.jinrui.reference.core.typehandler.JsonArrayTypeHandler}, #{industryScore,jdbcType=VARCHAR,typeHandler=com.jinrui.reference.core.typehandler.JsonArrayTypeHandler}, #{conceptLabel,jdbcType=VARCHAR,typeHandler=com.jinrui.reference.core.typehandler.JsonArrayTypeHandler}, #{conceptConfidence,jdbcType=VARCHAR,typeHandler=com.jinrui.reference.core.typehandler.JsonArrayTypeHandler}, #{conceptScore,jdbcType=VARCHAR,typeHandler=com.jinrui.reference.core.typehandler.JsonArrayTypeHandler}, #{source}, #{sourceImpact}, #{chinaFactor}, #{publicOpinionScore}, #{newsScore}, #{newsId}, #{deleted},#{createTime}, #{updateTime})")
|
||||||
|
void save(NewsTags newsTags);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.jinrui.reference.core.mapper;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Insert;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Result;
|
||||||
|
import org.apache.ibatis.annotations.Results;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
import org.apache.ibatis.type.JdbcType;
|
||||||
|
|
||||||
|
import com.jinrui.reference.core.model.entity.UserOperationLog;
|
||||||
|
|
||||||
|
public interface UserOperationLogMapper {
|
||||||
|
@Insert("insert into user_operation_log(user_id, username, user_type, data_id, type, behavior)" +
|
||||||
|
"values (#{userId},#{username},#{userType}, #{dataId}, #{type}, #{behavior})")
|
||||||
|
void save(@Param("userId") Long userId,@Param("username") String username,@Param("userType") String userType,@Param("dataId") Long dataId, @Param("type") String type, @Param("behavior") String behavior);
|
||||||
|
|
||||||
|
@Results({
|
||||||
|
@Result(column = "id", property = "id", id = true),
|
||||||
|
@Result(column = "data_id", property = "dataId"),
|
||||||
|
@Result(column = "user_id", property = "userId"),
|
||||||
|
@Result(column = "username", property = "username"),
|
||||||
|
@Result(column = "user_type", property = "userType"),
|
||||||
|
@Result(column = "type", property = "type"),
|
||||||
|
@Result(column = "behavior", property = "behavior"),
|
||||||
|
@Result(column = "create_time", property = "createTime", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP),
|
||||||
|
})
|
||||||
|
@Select("select * from user_operation_log where data_id = #{dataId} and type = #{type} order by create_time desc limit ${limit} offset ${offset}")
|
||||||
|
List<UserOperationLog> selectByDataIdAndType(@Param("dataId") Long dataId, @Param("type") String type, @Param("limit") int limit, @Param("offset") int offset);
|
||||||
|
|
||||||
|
@Select("select count(*) from user_operation_log where data_id = #{dataId} and type = #{type}")
|
||||||
|
int queryTotal(@Param("dataId") Long dataId, @Param("type") String type);
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,10 @@ public class SaveNewsDTO {
|
||||||
private String contentText;
|
private String contentText;
|
||||||
private Integer status;
|
private Integer status;
|
||||||
private Date publishTime;
|
private Date publishTime;
|
||||||
|
|
||||||
|
private Byte rating;
|
||||||
|
|
||||||
|
private String revision;
|
||||||
|
|
||||||
public SaveNewsDTO() {}
|
public SaveNewsDTO() {}
|
||||||
|
|
||||||
|
|
@ -144,4 +148,20 @@ public class SaveNewsDTO {
|
||||||
newsInfo.setInputDate(newsInfo.getCreateTime());
|
newsInfo.setInputDate(newsInfo.getCreateTime());
|
||||||
return newsInfo;
|
return newsInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Byte getRating() {
|
||||||
|
return rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRating(Byte rating) {
|
||||||
|
this.rating = rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRevision() {
|
||||||
|
return revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRevision(String revision) {
|
||||||
|
this.revision = revision;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ public class News {
|
||||||
private String contentText;
|
private String contentText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新闻状态 0-草稿 | 1-未发布 | 2-已发布
|
* 新闻状态 0-草稿 | 1-未发布 | 2-已发布 | 3-送审
|
||||||
*/
|
*/
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
|
@ -77,7 +77,17 @@ public class News {
|
||||||
private String newsinfoId;
|
private String newsinfoId;
|
||||||
|
|
||||||
private Double score;
|
private Double score;
|
||||||
|
|
||||||
|
private String llmTitle;
|
||||||
|
|
||||||
|
private String llmContent;
|
||||||
|
|
||||||
|
private Boolean deleted;
|
||||||
|
|
||||||
|
private Byte rating;
|
||||||
|
|
||||||
|
private String revision;
|
||||||
|
|
||||||
public News() {}
|
public News() {}
|
||||||
|
|
||||||
public News(SaveNewsDTO saveNewsDTO) {
|
public News(SaveNewsDTO saveNewsDTO) {
|
||||||
|
|
@ -90,7 +100,10 @@ public class News {
|
||||||
this.content = saveNewsDTO.getContent();
|
this.content = saveNewsDTO.getContent();
|
||||||
this.contentText = saveNewsDTO.getContentText();
|
this.contentText = saveNewsDTO.getContentText();
|
||||||
this.publishTime = saveNewsDTO.getPublishTime();
|
this.publishTime = saveNewsDTO.getPublishTime();
|
||||||
// this.status = 0;
|
this.llmTitle = saveNewsDTO.getTitle();
|
||||||
|
this.llmContent = saveNewsDTO.getContent();
|
||||||
|
this.rating = saveNewsDTO.getRating();
|
||||||
|
this.revision = saveNewsDTO.getRevision();
|
||||||
this.createTime = new Date();
|
this.createTime = new Date();
|
||||||
this.updateTime = new Date();
|
this.updateTime = new Date();
|
||||||
}
|
}
|
||||||
|
|
@ -214,4 +227,44 @@ public class News {
|
||||||
public void setScore(Double score) {
|
public void setScore(Double score) {
|
||||||
this.score = score;
|
this.score = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLlmTitle() {
|
||||||
|
return llmTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLlmTitle(String llmTitle) {
|
||||||
|
this.llmTitle = llmTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLlmContent() {
|
||||||
|
return llmContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLlmContent(String llmContent) {
|
||||||
|
this.llmContent = llmContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getDeleted() {
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeleted(Boolean deleted) {
|
||||||
|
this.deleted = deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Byte getRating() {
|
||||||
|
return rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRating(Byte rating) {
|
||||||
|
this.rating = rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRevision(String revision) {
|
||||||
|
this.revision = revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRevision() {
|
||||||
|
return revision;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.jinrui.reference.core.model.entity;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class NewsDeleted {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private Long newsId;
|
||||||
|
|
||||||
|
private String newsinfoId;
|
||||||
|
|
||||||
|
private String clusterId;
|
||||||
|
|
||||||
|
private Date deletedTime;
|
||||||
|
|
||||||
|
public NewsDeleted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public NewsDeleted(News news, String clusterId) {
|
||||||
|
this.newsId = news.getId();
|
||||||
|
this.newsinfoId = news.getNewsinfoId();
|
||||||
|
this.clusterId = clusterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getNewsId() {
|
||||||
|
return newsId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewsId(Long newsId) {
|
||||||
|
this.newsId = newsId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNewsinfoId() {
|
||||||
|
return newsinfoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewsinfoId(String newsinfoId) {
|
||||||
|
this.newsinfoId = newsinfoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClusterId() {
|
||||||
|
return clusterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClusterId(String clusterId) {
|
||||||
|
this.clusterId = clusterId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDeletedTime() {
|
||||||
|
return deletedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeletedTime(Date deletedTime) {
|
||||||
|
this.deletedTime = deletedTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,8 @@ public class NewsInfo {
|
||||||
public static final String CONTENT_ES_NAME = "CN_content";
|
public static final String CONTENT_ES_NAME = "CN_content";
|
||||||
public static final String SOURCE_ES_NAME = "sourcename.keyword";
|
public static final String SOURCE_ES_NAME = "sourcename.keyword";
|
||||||
public static final String DELETED_ES_NAME = "deleted.keyword";
|
public static final String DELETED_ES_NAME = "deleted.keyword";
|
||||||
|
public static final String SCORE_ES_NAME = "news_tags.news_score";
|
||||||
|
public static final String INPUT_DATE_ES_NAME = "input_date";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全量资讯ID
|
* 全量资讯ID
|
||||||
|
|
@ -33,7 +35,7 @@ public class NewsInfo {
|
||||||
/**
|
/**
|
||||||
* 数据输入时间
|
* 数据输入时间
|
||||||
*/
|
*/
|
||||||
@JsonProperty("input_date")
|
@JsonProperty(INPUT_DATE_ES_NAME)
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Shanghai")
|
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Shanghai")
|
||||||
private Date inputDate;
|
private Date inputDate;
|
||||||
|
|
||||||
|
|
@ -137,6 +139,8 @@ public class NewsInfo {
|
||||||
*/
|
*/
|
||||||
private Long editorId;
|
private Long editorId;
|
||||||
|
|
||||||
|
@JsonProperty("news_tags")
|
||||||
|
private NewsTags newsTags;
|
||||||
|
|
||||||
public NewsInfo() {}
|
public NewsInfo() {}
|
||||||
|
|
||||||
|
|
@ -315,12 +319,22 @@ public class NewsInfo {
|
||||||
public void setWords(Integer words) {
|
public void setWords(Integer words) {
|
||||||
this.words = words;
|
this.words = words;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NewsTags getNewsTags() {
|
||||||
|
return newsTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewsTags(NewsTags newsTags) {
|
||||||
|
this.newsTags = newsTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public News toNews() {
|
public News toNews() {
|
||||||
News news = new News();
|
News news = new News();
|
||||||
news.setTitle(this.getTitle());
|
news.setTitle(this.getTitle());
|
||||||
news.setContent(this.getContent());
|
news.setContent(this.getContent());
|
||||||
|
news.setLlmTitle(this.getTitle());
|
||||||
|
news.setLlmContent(this.getContent());
|
||||||
news.setStatus(this.getStatus());
|
news.setStatus(this.getStatus());
|
||||||
news.setSummary(this.getSummary());
|
news.setSummary(this.getSummary());
|
||||||
news.setPublishTime(this.getInputDate());
|
news.setPublishTime(this.getInputDate());
|
||||||
|
|
|
||||||
|
|
@ -3,43 +3,67 @@ package com.jinrui.reference.core.model.entity;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
public class NewsTags {
|
public class NewsTags {
|
||||||
|
@JsonProperty("id")
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
|
@JsonProperty("abstract")
|
||||||
private String summary;
|
private String summary;
|
||||||
|
|
||||||
|
@JsonProperty("title")
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
|
@JsonProperty("rewrite_content")
|
||||||
private String rewriteContent;
|
private String rewriteContent;
|
||||||
|
|
||||||
|
@JsonProperty("industry_label")
|
||||||
private List<String> industryLabel;
|
private List<String> industryLabel;
|
||||||
|
|
||||||
|
@JsonProperty("industry_confidence")
|
||||||
private List<Double> industryConfidence;
|
private List<Double> industryConfidence;
|
||||||
|
|
||||||
|
@JsonProperty("industry_score")
|
||||||
private List<Double> industryScore;
|
private List<Double> industryScore;
|
||||||
|
|
||||||
|
@JsonProperty("concept_label")
|
||||||
private List<String> conceptLabel;
|
private List<String> conceptLabel;
|
||||||
|
|
||||||
|
@JsonProperty("concept_confidence")
|
||||||
private List<Double> conceptConfidence;
|
private List<Double> conceptConfidence;
|
||||||
|
|
||||||
|
@JsonProperty("concept_score")
|
||||||
private List<Double> conceptScore;
|
private List<Double> conceptScore;
|
||||||
|
|
||||||
|
@JsonProperty("source")
|
||||||
private String source;
|
private String source;
|
||||||
|
|
||||||
|
@JsonProperty("source_impact")
|
||||||
private Integer sourceImpact;
|
private Integer sourceImpact;
|
||||||
|
|
||||||
|
@JsonProperty("China_factor")
|
||||||
private Double chinaFactor;
|
private Double chinaFactor;
|
||||||
|
|
||||||
|
@JsonProperty("public_opinion_score")
|
||||||
private Integer publicOpinionScore;
|
private Integer publicOpinionScore;
|
||||||
|
|
||||||
|
@JsonProperty("news_score")
|
||||||
private Double newsScore;
|
private Double newsScore;
|
||||||
|
|
||||||
|
@JsonProperty("news_id")
|
||||||
private Long newsId;
|
private Long newsId;
|
||||||
|
|
||||||
private Boolean deleted;
|
@JsonProperty("deleted")
|
||||||
|
private Integer deleted;
|
||||||
|
|
||||||
|
@JsonProperty("create_time")
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Shanghai")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
|
@JsonProperty("update_time")
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Shanghai")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
public List<Double> getIndustryScore() {
|
public List<Double> getIndustryScore() {
|
||||||
|
|
@ -170,11 +194,11 @@ public class NewsTags {
|
||||||
this.newsId = newsId;
|
this.newsId = newsId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getDeleted() {
|
public Integer getDeleted() {
|
||||||
return deleted;
|
return deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeleted(Boolean deleted) {
|
public void setDeleted(Integer deleted) {
|
||||||
this.deleted = deleted;
|
this.deleted = deleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.jinrui.reference.core.model.entity;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class UserOperationLog {
|
||||||
|
private Long id;
|
||||||
|
private Long dataId;
|
||||||
|
private String type;
|
||||||
|
private String behavior;
|
||||||
|
private Long userId;
|
||||||
|
private String username;
|
||||||
|
private String userType;
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
public Long getDataId() {
|
||||||
|
return dataId;
|
||||||
|
}
|
||||||
|
public void setDataId(Long dataId) {
|
||||||
|
this.dataId = dataId;
|
||||||
|
}
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
public String getBehavior() {
|
||||||
|
return behavior;
|
||||||
|
}
|
||||||
|
public void setBehavior(String behavior) {
|
||||||
|
this.behavior = behavior;
|
||||||
|
}
|
||||||
|
public Long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
public void setUserId(Long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
public Date getCreateTime() {
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
public void setCreateTime(Date createTime) {
|
||||||
|
this.createTime = createTime;
|
||||||
|
}
|
||||||
|
public String getUserType() {
|
||||||
|
return userType;
|
||||||
|
}
|
||||||
|
public void setUserType(String userType) {
|
||||||
|
this.userType = userType;
|
||||||
|
}
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,221 @@
|
||||||
|
package com.jinrui.reference.core.model.vo.news;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
|
||||||
|
public class NewsApiVO {
|
||||||
|
/**
|
||||||
|
* 资讯ID
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资讯标题
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资讯内容
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 报道时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
|
||||||
|
private Date publishTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资讯摘要
|
||||||
|
*/
|
||||||
|
private String summary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资讯评分
|
||||||
|
*/
|
||||||
|
private Double newsScore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资讯来源
|
||||||
|
*/
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 行业分类标签
|
||||||
|
*/
|
||||||
|
private List<String> industryLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 行业分类置信度
|
||||||
|
*/
|
||||||
|
private List<Number> industryConfidence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 行业分类评分
|
||||||
|
*/
|
||||||
|
private List<Number> industryScore;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 概念标签
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<String> conceptLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 概念标签置信度
|
||||||
|
*/
|
||||||
|
private List<Number> conceptConfidence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 概念标签评分
|
||||||
|
*/
|
||||||
|
private List<Number> conceptScore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 媒体影响力
|
||||||
|
*/
|
||||||
|
private Integer sourceImpact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中国股市相关性
|
||||||
|
*/
|
||||||
|
private Double chinaFactor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资讯质量
|
||||||
|
*/
|
||||||
|
private Integer publicOpinionScore;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getPublishTime() {
|
||||||
|
return publishTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublishTime(Date publishTime) {
|
||||||
|
this.publishTime = publishTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSummary() {
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSummary(String summary) {
|
||||||
|
this.summary = summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSource(String source) {
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getIndustryLabel() {
|
||||||
|
return industryLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndustryLabel(List<String> industryLabel) {
|
||||||
|
this.industryLabel = industryLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getConceptLabel() {
|
||||||
|
return conceptLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConceptLabel(List<String> conceptLabel) {
|
||||||
|
this.conceptLabel = conceptLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getNewsScore() {
|
||||||
|
return newsScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewsScore(Double newsScore) {
|
||||||
|
this.newsScore = newsScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Number> getIndustryConfidence() {
|
||||||
|
return industryConfidence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndustryConfidence(List<Number> industryConfidence) {
|
||||||
|
this.industryConfidence = industryConfidence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Number> getIndustryScore() {
|
||||||
|
return industryScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndustryScore(List<Number> industryScore) {
|
||||||
|
this.industryScore = industryScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Number> getConceptConfidence() {
|
||||||
|
return conceptConfidence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConceptConfidence(List<Number> conceptConfidence) {
|
||||||
|
this.conceptConfidence = conceptConfidence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Number> getConceptScore() {
|
||||||
|
return conceptScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConceptScore(List<Number> conceptScore) {
|
||||||
|
this.conceptScore = conceptScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSourceImpact() {
|
||||||
|
return sourceImpact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceImpact(Integer sourceImpact) {
|
||||||
|
this.sourceImpact = sourceImpact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getChinaFactor() {
|
||||||
|
return chinaFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChinaFactor(Double chinaFactor) {
|
||||||
|
this.chinaFactor = chinaFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPublicOpinionScore() {
|
||||||
|
return publicOpinionScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicOpinionScore(Integer publicOpinionScore) {
|
||||||
|
this.publicOpinionScore = publicOpinionScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,12 +8,16 @@ import com.jinrui.reference.core.model.entity.NewsDraft;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class NewsDetailVO {
|
public class NewsDetailVO {
|
||||||
|
|
||||||
|
public static final String AI_TITLE_FLAG = "title";
|
||||||
|
public static final String AI_CONENT_FLAG = "content";
|
||||||
|
public static final String AI_TITLE_CONTENT_FLAG = "title&content";
|
||||||
|
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
private String title;
|
private String title; // 标题
|
||||||
|
|
||||||
private String summary;
|
private String summary;
|
||||||
|
|
||||||
private String picture;
|
private String picture;
|
||||||
|
|
||||||
|
|
@ -23,10 +27,22 @@ public class NewsDetailVO {
|
||||||
|
|
||||||
private List<NewsDetailIndustry> industry;
|
private List<NewsDetailIndustry> industry;
|
||||||
|
|
||||||
private String content;
|
private String content; // 正文
|
||||||
|
|
||||||
private Date publishTime;
|
private Date publishTime;
|
||||||
|
|
||||||
|
private Boolean titleTranslated; // 大模型翻译标识
|
||||||
|
|
||||||
|
private Boolean contentTranslated; // 大模型翻译标识
|
||||||
|
|
||||||
|
private Boolean deleted; // 删除标识
|
||||||
|
|
||||||
|
private String newsInfoId; // 获取原文和参考译文的字段
|
||||||
|
|
||||||
|
private Byte rating; // 打分
|
||||||
|
|
||||||
|
private String revision; // 修订说明
|
||||||
|
|
||||||
public NewsDetailVO() {
|
public NewsDetailVO() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,6 +53,10 @@ public class NewsDetailVO {
|
||||||
this.picture = news.getPicture();
|
this.picture = news.getPicture();
|
||||||
this.content = news.getContent();
|
this.content = news.getContent();
|
||||||
this.publishTime = news.getPublishTime();
|
this.publishTime = news.getPublishTime();
|
||||||
|
this.deleted = news.getDeleted();
|
||||||
|
this.newsInfoId = news.getNewsinfoId();
|
||||||
|
this.rating = news.getRating();
|
||||||
|
this.revision = news.getRevision();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NewsDetailVO(NewsDraft newsDraft) {
|
public NewsDetailVO(NewsDraft newsDraft) {
|
||||||
|
|
@ -117,5 +137,68 @@ public class NewsDetailVO {
|
||||||
public void setPublishTime(Date publishTime) {
|
public void setPublishTime(Date publishTime) {
|
||||||
this.publishTime = publishTime;
|
this.publishTime = publishTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getTitleTranslated() {
|
||||||
|
return titleTranslated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitleTranslated(Boolean titleTranslated) {
|
||||||
|
this.titleTranslated = titleTranslated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getContentTranslated() {
|
||||||
|
return contentTranslated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentTranslated(Boolean contentTranslated) {
|
||||||
|
this.contentTranslated = contentTranslated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getDeleted() {
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeleted(Boolean deleted) {
|
||||||
|
this.deleted = deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNewsInfoId() {
|
||||||
|
return newsInfoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNewsInfoId(String newsInfoId) {
|
||||||
|
this.newsInfoId = newsInfoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markTranslatedFlag(String aiFlag) {
|
||||||
|
if (AI_TITLE_FLAG.equals(aiFlag)) {
|
||||||
|
this.setTitleTranslated(true);
|
||||||
|
this.setContentTranslated(false);
|
||||||
|
} else if (AI_CONENT_FLAG.equals(aiFlag)) {
|
||||||
|
this.setTitleTranslated(false);
|
||||||
|
this.setContentTranslated(true);
|
||||||
|
} else if (AI_TITLE_CONTENT_FLAG.equals(aiFlag)) {
|
||||||
|
this.setTitleTranslated(true);
|
||||||
|
this.setContentTranslated(true);
|
||||||
|
} else {
|
||||||
|
this.setTitleTranslated(false);
|
||||||
|
this.setContentTranslated(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Byte getRating() {
|
||||||
|
return rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRating(Byte rating) {
|
||||||
|
this.rating = rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRevision() {
|
||||||
|
return revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRevision(String revision) {
|
||||||
|
this.revision = revision;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.jinrui.reference.core.model.vo.news;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.jinrui.reference.core.model.entity.UserOperationLog;
|
||||||
|
|
||||||
|
public class NewsLogVO {
|
||||||
|
private String username;
|
||||||
|
private String userType;
|
||||||
|
private String behavior;
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
public NewsLogVO(UserOperationLog userOperationLog) {
|
||||||
|
this.username = userOperationLog.getUsername();
|
||||||
|
this.userType = userOperationLog.getUserType();
|
||||||
|
this.behavior = userOperationLog.getBehavior();
|
||||||
|
this.createTime = userOperationLog.getCreateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
public String getUserType() {
|
||||||
|
return userType;
|
||||||
|
}
|
||||||
|
public void setUserType(String userType) {
|
||||||
|
this.userType = userType;
|
||||||
|
}
|
||||||
|
public String getBehavior() {
|
||||||
|
return behavior;
|
||||||
|
}
|
||||||
|
public void setBehavior(String behavior) {
|
||||||
|
this.behavior = behavior;
|
||||||
|
}
|
||||||
|
public Date getCreateTime() {
|
||||||
|
return createTime;
|
||||||
|
}
|
||||||
|
public void setCreateTime(Date createTime) {
|
||||||
|
this.createTime = createTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.jinrui.reference.core.model.vo.news;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.jinrui.reference.core.model.entity.News;
|
||||||
|
import com.jinrui.reference.core.model.entity.NewsDraft;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class NewsTranslatorVO {
|
||||||
|
private String titleEN; // 原文标题
|
||||||
|
|
||||||
|
private String contentEN; // 原文正文
|
||||||
|
|
||||||
|
private String titleCN; // 参考翻译标题
|
||||||
|
|
||||||
|
private String contentCN; // 参考翻译正文
|
||||||
|
|
||||||
|
public String getTitleEN() {
|
||||||
|
return titleEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitleEN(String titleEN) {
|
||||||
|
this.titleEN = titleEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentEN() {
|
||||||
|
return contentEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentEN(String contentEN) {
|
||||||
|
this.contentEN = contentEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitleCN() {
|
||||||
|
return titleCN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitleCN(String titleCN) {
|
||||||
|
this.titleCN = titleCN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentCN() {
|
||||||
|
return contentCN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentCN(String contentCN) {
|
||||||
|
this.contentCN = contentCN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -53,6 +53,18 @@ public class NewsVO {
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
private Double score;
|
private Double score;
|
||||||
|
|
||||||
|
public Boolean getDeleted() {
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeleted(Boolean deleted) {
|
||||||
|
this.deleted = deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean deleted; // 删除标识
|
||||||
|
|
||||||
|
private Byte rating; // 打分
|
||||||
|
|
||||||
public NewsVO(News news) {
|
public NewsVO(News news) {
|
||||||
this.id = news.getId();
|
this.id = news.getId();
|
||||||
|
|
@ -62,6 +74,8 @@ public class NewsVO {
|
||||||
this.publishTime = news.getPublishTime();
|
this.publishTime = news.getPublishTime();
|
||||||
this.updateTime = news.getUpdateTime();
|
this.updateTime = news.getUpdateTime();
|
||||||
this.score = news.getScore();
|
this.score = news.getScore();
|
||||||
|
this.deleted = news.getDeleted();
|
||||||
|
this.rating = news.getRating();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
|
|
@ -123,4 +137,12 @@ public class NewsVO {
|
||||||
public void setScore(Double score) {
|
public void setScore(Double score) {
|
||||||
this.score = score;
|
this.score = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Byte getRating() {
|
||||||
|
return rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRating(Byte rating) {
|
||||||
|
this.rating = rating;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,12 @@ public class NewsInfoVO {
|
||||||
*/
|
*/
|
||||||
private Long editorId;
|
private Long editorId;
|
||||||
|
|
||||||
public NewsInfoVO(NewsInfo newsInfo) {
|
/**
|
||||||
|
* 资讯评分
|
||||||
|
*/
|
||||||
|
private Double score;
|
||||||
|
|
||||||
|
public NewsInfoVO(NewsInfo newsInfo) {
|
||||||
this.id = newsInfo.getId();
|
this.id = newsInfo.getId();
|
||||||
this.title = newsInfo.getTitle();
|
this.title = newsInfo.getTitle();
|
||||||
this.summary = newsInfo.getSummary();
|
this.summary = newsInfo.getSummary();
|
||||||
|
|
@ -86,6 +91,9 @@ public class NewsInfoVO {
|
||||||
this.createTime = newsInfo.getCreateTime();
|
this.createTime = newsInfo.getCreateTime();
|
||||||
this.updateTime = newsInfo.getUpdateTime();
|
this.updateTime = newsInfo.getUpdateTime();
|
||||||
this.inputDate = newsInfo.getInputDate();
|
this.inputDate = newsInfo.getInputDate();
|
||||||
|
if (newsInfo.getNewsTags() != null) {
|
||||||
|
this.score = newsInfo.getNewsTags().getNewsScore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
|
@ -191,4 +199,12 @@ public class NewsInfoVO {
|
||||||
public void setContent(String content) {
|
public void setContent(String content) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Double getScore() {
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScore(Double score) {
|
||||||
|
this.score = score;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -140,12 +140,20 @@ public class SaveNewsInfoDTO {
|
||||||
News news = new News();
|
News news = new News();
|
||||||
news.setTitle(this.getTitle());
|
news.setTitle(this.getTitle());
|
||||||
news.setSummary(this.getSummary());
|
news.setSummary(this.getSummary());
|
||||||
|
news.setLlmTitle(this.getTitle());
|
||||||
|
news.setLlmContent(this.getContent());
|
||||||
news.setStatus(this.getStatus());
|
news.setStatus(this.getStatus());
|
||||||
news.setContent(this.getContent());
|
news.setContent(this.getContent());
|
||||||
news.setCreateTime(new Date());
|
news.setCreateTime(new Date());
|
||||||
news.setUpdateTime(news.getCreateTime());
|
news.setUpdateTime(news.getCreateTime());
|
||||||
news.setType(1);
|
news.setType(1);
|
||||||
news.setNewsinfoId(this.getId());
|
news.setNewsinfoId(this.getId());
|
||||||
|
// 报道时间
|
||||||
|
if (this.getPublishTime() != null) {
|
||||||
|
news.setPublishTime(this.getPublishTime());
|
||||||
|
} else {
|
||||||
|
news.setPublishTime(news.getCreateTime());
|
||||||
|
}
|
||||||
return news;
|
return news;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.jinrui.reference.core.service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import com.jinrui.reference.core.api.ApiKeyGenerator;
|
||||||
|
import com.jinrui.reference.core.mapper.ApiUserMapper;
|
||||||
|
import com.jinrui.reference.core.model.vo.ResultObject;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ApiKeyService {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(ApiKeyService.class);
|
||||||
|
|
||||||
|
private final ApiUserMapper apiUserMapper;
|
||||||
|
|
||||||
|
public ApiKeyService(ApiUserMapper apiUserMapper) {
|
||||||
|
this.apiUserMapper = apiUserMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecretKeyByAk(String ak) {
|
||||||
|
String secretKey = apiUserMapper.getClientSecretkey(ak);
|
||||||
|
return secretKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultObject<Map<String, Object>> generateApiKey(String clientName) {
|
||||||
|
Map<String, Object> clientKeyMap = apiUserMapper.getClientKey(clientName);
|
||||||
|
if (ObjectUtils.isEmpty(clientKeyMap)) {
|
||||||
|
String accessKey = ApiKeyGenerator.generateAK();
|
||||||
|
String secretKey = ApiKeyGenerator.generateSK();
|
||||||
|
try {
|
||||||
|
apiUserMapper.save(clientName, accessKey, secretKey);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("产生客户API密钥对失败", e);
|
||||||
|
ResultObject.failed("客户已存在!");
|
||||||
|
}
|
||||||
|
clientKeyMap = new HashMap<>();
|
||||||
|
clientKeyMap.put("access_key", accessKey);
|
||||||
|
clientKeyMap.put("secret_key", secretKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultObject.success(clientKeyMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
package com.jinrui.reference.core.service;
|
package com.jinrui.reference.core.service;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -13,7 +17,6 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.jinrui.reference.core.mapper.IndustryMapper;
|
import com.jinrui.reference.core.mapper.IndustryMapper;
|
||||||
|
|
@ -33,6 +36,7 @@ import com.jinrui.reference.core.model.vo.ResultObject;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsDetailIndustry;
|
import com.jinrui.reference.core.model.vo.news.NewsDetailIndustry;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsDetailTag;
|
import com.jinrui.reference.core.model.vo.news.NewsDetailTag;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsDetailTagItem;
|
import com.jinrui.reference.core.model.vo.news.NewsDetailTagItem;
|
||||||
|
import com.jinrui.reference.core.model.vo.news.NewsScoreVO;
|
||||||
import com.jinrui.reference.core.model.vo.newsinfo.NewsInfoDetailVO;
|
import com.jinrui.reference.core.model.vo.newsinfo.NewsInfoDetailVO;
|
||||||
import com.jinrui.reference.core.model.vo.newsinfo.NewsInfoVO;
|
import com.jinrui.reference.core.model.vo.newsinfo.NewsInfoVO;
|
||||||
import com.jinrui.reference.core.model.vo.newsinfo.SaveNewsInfoDTO;
|
import com.jinrui.reference.core.model.vo.newsinfo.SaveNewsInfoDTO;
|
||||||
|
|
@ -40,12 +44,14 @@ import com.jinrui.reference.core.model.vo.newsinfo.SaveNewsInfoDTO;
|
||||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||||
import co.elastic.clients.elasticsearch._types.ElasticsearchException;
|
import co.elastic.clients.elasticsearch._types.ElasticsearchException;
|
||||||
import co.elastic.clients.elasticsearch._types.Refresh;
|
import co.elastic.clients.elasticsearch._types.Refresh;
|
||||||
|
import co.elastic.clients.elasticsearch._types.SortOptions;
|
||||||
import co.elastic.clients.elasticsearch._types.SortOrder;
|
import co.elastic.clients.elasticsearch._types.SortOrder;
|
||||||
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
|
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
|
||||||
import co.elastic.clients.elasticsearch._types.query_dsl.MultiMatchQuery;
|
import co.elastic.clients.elasticsearch._types.query_dsl.MultiMatchQuery;
|
||||||
import co.elastic.clients.elasticsearch._types.query_dsl.Operator;
|
import co.elastic.clients.elasticsearch._types.query_dsl.Operator;
|
||||||
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
|
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
|
||||||
import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
|
import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
|
||||||
|
import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery;
|
||||||
import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery;
|
import co.elastic.clients.elasticsearch._types.query_dsl.TermQuery;
|
||||||
import co.elastic.clients.elasticsearch.core.GetResponse;
|
import co.elastic.clients.elasticsearch.core.GetResponse;
|
||||||
import co.elastic.clients.elasticsearch.core.IndexResponse;
|
import co.elastic.clients.elasticsearch.core.IndexResponse;
|
||||||
|
|
@ -53,8 +59,7 @@ import co.elastic.clients.elasticsearch.core.SearchRequest;
|
||||||
import co.elastic.clients.elasticsearch.core.SearchResponse;
|
import co.elastic.clients.elasticsearch.core.SearchResponse;
|
||||||
import co.elastic.clients.elasticsearch.core.search.Hit;
|
import co.elastic.clients.elasticsearch.core.search.Hit;
|
||||||
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
|
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
|
||||||
import co.elastic.clients.json.JsonpUtils;
|
import co.elastic.clients.json.JsonData;
|
||||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class NewsInfoService {
|
public class NewsInfoService {
|
||||||
|
|
@ -104,6 +109,14 @@ public class NewsInfoService {
|
||||||
News relNews = newsInfo.toNews();
|
News relNews = newsInfo.toNews();
|
||||||
relNews.setStatus(1);
|
relNews.setStatus(1);
|
||||||
relNews.setEditorId(editorId);
|
relNews.setEditorId(editorId);
|
||||||
|
|
||||||
|
NewsTags newsTags = newsTagsMapper.getNewsTagsByNewsId(id);
|
||||||
|
if (newsTags != null) {
|
||||||
|
String llmTitle = Optional.ofNullable(newsTags.getTitle()).filter(s -> !s.isEmpty()).orElse(relNews.getTitle());
|
||||||
|
relNews.setLlmTitle(llmTitle);
|
||||||
|
String llmContent = Optional.ofNullable(newsTags.getRewriteContent()).filter(s -> !s.isEmpty()).orElse(relNews.getContent());
|
||||||
|
relNews.setLlmContent(llmContent);
|
||||||
|
}
|
||||||
newsMapper.saveNews(relNews);
|
newsMapper.saveNews(relNews);
|
||||||
saveNewsRel(id, relNews.getId());
|
saveNewsRel(id, relNews.getId());
|
||||||
}
|
}
|
||||||
|
|
@ -336,6 +349,7 @@ public class NewsInfoService {
|
||||||
News relateNews = newsMapper.getNewsDetailByNewsInfoId(id);
|
News relateNews = newsMapper.getNewsDetailByNewsInfoId(id);
|
||||||
|
|
||||||
if (relateNews == null) {
|
if (relateNews == null) {
|
||||||
|
saveNewsInfoDTO.setPublishTime(newsInfo.getInputDate()); // 报道时间
|
||||||
relateNews = createRelateNews(saveNewsInfoDTO);
|
relateNews = createRelateNews(saveNewsInfoDTO);
|
||||||
NewsInfo updatedNewsInfo = toNewsInfo(relateNews.getId(), saveNewsInfoDTO);
|
NewsInfo updatedNewsInfo = toNewsInfo(relateNews.getId(), saveNewsInfoDTO);
|
||||||
elasticsearchClient.update(e -> e.index(NewsInfo.INDEX_NAME).id(updatedNewsInfo.getId()).doc(updatedNewsInfo).refresh(Refresh.True), NewsInfo.class);
|
elasticsearchClient.update(e -> e.index(NewsInfo.INDEX_NAME).id(updatedNewsInfo.getId()).doc(updatedNewsInfo).refresh(Refresh.True), NewsInfo.class);
|
||||||
|
|
@ -351,7 +365,7 @@ public class NewsInfoService {
|
||||||
return ResultObject.success();
|
return ResultObject.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultObject<Void> deleteNewsInfo(String newsInfoId) {
|
public ResultObject<Void> deleteNewsInfo(String newsInfoId, Long editorId) {
|
||||||
try {
|
try {
|
||||||
GetResponse<NewsInfo> getResp = elasticsearchClient.get(e -> e.index(NewsInfo.INDEX_NAME).id(String.valueOf(newsInfoId)), NewsInfo.class);
|
GetResponse<NewsInfo> getResp = elasticsearchClient.get(e -> e.index(NewsInfo.INDEX_NAME).id(String.valueOf(newsInfoId)), NewsInfo.class);
|
||||||
if (getResp.found()) {
|
if (getResp.found()) {
|
||||||
|
|
@ -359,7 +373,7 @@ public class NewsInfoService {
|
||||||
Long newsId = newsInfo.getNewsId();
|
Long newsId = newsInfo.getNewsId();
|
||||||
// 删除资讯精选中关联的数据
|
// 删除资讯精选中关联的数据
|
||||||
deleteNewsRel(newsId);
|
deleteNewsRel(newsId);
|
||||||
newsMapper.deleteNews(newsId);
|
newsMapper.deleteNews(newsId, editorId);
|
||||||
|
|
||||||
NewsInfo deletedNewsInfo = new NewsInfo();
|
NewsInfo deletedNewsInfo = new NewsInfo();
|
||||||
deletedNewsInfo.setDeleted(1);
|
deletedNewsInfo.setDeleted(1);
|
||||||
|
|
@ -385,7 +399,7 @@ public class NewsInfoService {
|
||||||
try {
|
try {
|
||||||
IndexResponse resp = elasticsearchClient.index(c -> c.index(NewsInfo.INDEX_NAME).document(newsInfo).refresh(Refresh.True));
|
IndexResponse resp = elasticsearchClient.index(c -> c.index(NewsInfo.INDEX_NAME).document(newsInfo).refresh(Refresh.True));
|
||||||
news.setNewsinfoId(resp.id());
|
news.setNewsinfoId(resp.id());
|
||||||
newsMapper.updateNews(news);
|
newsMapper.updateNews(news, news.getStatus());
|
||||||
} catch(IOException|ElasticsearchException e) {
|
} catch(IOException|ElasticsearchException e) {
|
||||||
log.error("新建全量资讯出错!", e);
|
log.error("新建全量资讯出错!", e);
|
||||||
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
||||||
|
|
@ -419,7 +433,7 @@ public class NewsInfoService {
|
||||||
private void updateRelateNews(Long newsId, SaveNewsInfoDTO saveNewsDTO) {
|
private void updateRelateNews(Long newsId, SaveNewsInfoDTO saveNewsDTO) {
|
||||||
News news = saveNewsDTO.toNews();
|
News news = saveNewsDTO.toNews();
|
||||||
news.setId(newsId);
|
news.setId(newsId);
|
||||||
newsMapper.updateNews(news);
|
newsMapper.updateNews(news, news.getStatus());
|
||||||
|
|
||||||
tagMapper.deleteNews(newsId);
|
tagMapper.deleteNews(newsId);
|
||||||
industryMapper.deleteNews(newsId);
|
industryMapper.deleteNews(newsId);
|
||||||
|
|
@ -489,30 +503,10 @@ public class NewsInfoService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PageObject<NewsInfoVO> queryNewsInfo(String title, String content, String stockcode, Long sourcename, int page, int size,
|
public PageObject<NewsInfoVO> queryNewsInfo(String title, String content, String stockcode, Long sourcename, int page, int size,
|
||||||
String last, Integer current, String orderBy, String direction) {
|
String last, Integer current, String orderBy, String direction, Double minScore, Double maxScore,
|
||||||
|
Date inputDateFrom, Date inputDateTo) {
|
||||||
|
|
||||||
if (StringUtils.hasText(orderBy)) {
|
final String orderByField = mappingToEsFieldName(orderBy);
|
||||||
switch (orderBy) {
|
|
||||||
case "publishTime": {
|
|
||||||
orderBy = "publish_time";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "updateTime": {
|
|
||||||
orderBy = "update_time";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "createTime": {
|
|
||||||
orderBy = "create_time";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "inputDate": {
|
|
||||||
orderBy = "input_date";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final String orderByField = orderBy;
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
offset = (Math.max(0, current - 1)) * size;
|
offset = (Math.max(0, current - 1)) * size;
|
||||||
|
|
@ -542,18 +536,34 @@ public class NewsInfoService {
|
||||||
filters.add(sourcenameQuery);
|
filters.add(sourcenameQuery);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 评分范围查询
|
||||||
if (conditions.size() == 0) {
|
Query scoreRangeQuery = buildRangeQuery(NewsInfo.SCORE_ES_NAME, minScore, maxScore);
|
||||||
conditions.add(QueryBuilders.matchAll().build()._toQuery());
|
if (scoreRangeQuery != null) {
|
||||||
|
filters.add(scoreRangeQuery);
|
||||||
}
|
}
|
||||||
|
// 报道时间范围查询
|
||||||
|
Query inputDateRangeQuery = buildRangeQuery(NewsInfo.INPUT_DATE_ES_NAME, inputDateFrom, inputDateTo);
|
||||||
|
if (inputDateRangeQuery != null) {
|
||||||
|
filters.add(inputDateRangeQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SortOptions> sortOptions = new ArrayList<>();
|
||||||
|
if (conditions.size() > 0) {
|
||||||
|
sortOptions.add(SortOptions.of(e -> e.score(x -> x.order(SortOrder.Desc))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (conditions.size() == 0) {
|
||||||
|
// conditions.add(QueryBuilders.matchAll().build()._toQuery());
|
||||||
|
// }
|
||||||
Query resultQuery = new Query.Builder().bool(b -> b.must(conditions).filter(filters)).build();
|
Query resultQuery = new Query.Builder().bool(b -> b.must(conditions).filter(filters)).build();
|
||||||
SortOrder sortOrder = (Objects.equals(direction, SortOrder.Asc.jsonValue()) ?SortOrder.Asc:SortOrder.Desc);
|
SortOrder sortOrder = (Objects.equals(direction, SortOrder.Asc.jsonValue()) ?SortOrder.Asc:SortOrder.Desc);
|
||||||
|
sortOptions.add(SortOptions.of(e -> e.field(f -> f.field(orderByField).order(sortOrder))));
|
||||||
|
|
||||||
SearchRequest request = SearchRequest.of(s ->
|
SearchRequest request = SearchRequest.of(s ->
|
||||||
s.from(from)
|
s.index(NewsInfo.INDEX_NAME).from(from)
|
||||||
.size(size) // 分页参数
|
.size(size) // 分页参数
|
||||||
.trackTotalHits(e -> e.enabled(true))
|
.trackTotalHits(e -> e.enabled(true))
|
||||||
.sort(so -> so.field(f -> f.field(orderByField).order(sortOrder))) // 排序字段
|
.sort(sortOptions) // 排序字段
|
||||||
.query(resultQuery).trackScores(true)
|
.query(resultQuery).trackScores(true)
|
||||||
.highlight(h -> h.preTags("<font color='red'>")
|
.highlight(h -> h.preTags("<font color='red'>")
|
||||||
.postTags("</font>")
|
.postTags("</font>")
|
||||||
|
|
@ -592,4 +602,73 @@ public class NewsInfoService {
|
||||||
pageObject.setData(newsInfoList);
|
pageObject.setData(newsInfoList);
|
||||||
return pageObject;
|
return pageObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Query buildRangeQuery(String fieldName, Object fromValue, Object toValue) {
|
||||||
|
if (fromValue == null && toValue == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
RangeQuery.Builder rangeBuilder = QueryBuilders.range().field(fieldName);
|
||||||
|
if (fromValue != null) {
|
||||||
|
if (fromValue instanceof Date) {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
rangeBuilder = rangeBuilder.gte(JsonData.of(sdf.format(fromValue)));
|
||||||
|
} else {
|
||||||
|
rangeBuilder = rangeBuilder.gte(JsonData.of(fromValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (toValue != null) {
|
||||||
|
if (toValue instanceof Date) {
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime((Date)toValue);
|
||||||
|
calendar.add(Calendar.DATE, 1);
|
||||||
|
Date expireDate = calendar.getTime();
|
||||||
|
rangeBuilder = rangeBuilder.lt(JsonData.of(sdf.format(expireDate)));
|
||||||
|
} else {
|
||||||
|
rangeBuilder = rangeBuilder.lte(JsonData.of(toValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return rangeBuilder.build()._toQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String mappingToEsFieldName(String orderBy) {
|
||||||
|
String esFieldName = "";
|
||||||
|
switch (orderBy) {
|
||||||
|
case "publishTime": {
|
||||||
|
esFieldName = "publish_time";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "updateTime": {
|
||||||
|
esFieldName = "update_time";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "createTime": {
|
||||||
|
esFieldName = "create_time";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "inputDate": {
|
||||||
|
esFieldName = "input_date";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "score": {
|
||||||
|
esFieldName = "news_tags.news_score";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
esFieldName = "input_date";
|
||||||
|
}
|
||||||
|
return esFieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultObject<NewsScoreVO> getScore(String id) {
|
||||||
|
NewsTags newsTags = newsTagsMapper.getNewsTagsByNewsId(id);
|
||||||
|
if (newsTags == null) {
|
||||||
|
return ResultObject.success();
|
||||||
|
}
|
||||||
|
NewsScoreVO newsScoreVO = new NewsScoreVO(newsTags);
|
||||||
|
return ResultObject.success(newsScoreVO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -22,15 +23,18 @@ import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import com.aliyun.oss.common.utils.DateUtil;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.jinrui.reference.core.mapper.ColumnMapper;
|
import com.jinrui.reference.core.mapper.ColumnMapper;
|
||||||
import com.jinrui.reference.core.mapper.IndustryMapper;
|
import com.jinrui.reference.core.mapper.IndustryMapper;
|
||||||
|
import com.jinrui.reference.core.mapper.NewsDeletedMapper;
|
||||||
import com.jinrui.reference.core.mapper.NewsMapper;
|
import com.jinrui.reference.core.mapper.NewsMapper;
|
||||||
import com.jinrui.reference.core.mapper.NewsTagsMapper;
|
import com.jinrui.reference.core.mapper.NewsTagsMapper;
|
||||||
import com.jinrui.reference.core.mapper.TagMapper;
|
import com.jinrui.reference.core.mapper.TagMapper;
|
||||||
|
import com.jinrui.reference.core.mapper.UserOperationLogMapper;
|
||||||
import com.jinrui.reference.core.model.dto.news.SaveDraftColumn;
|
import com.jinrui.reference.core.model.dto.news.SaveDraftColumn;
|
||||||
import com.jinrui.reference.core.model.dto.news.SaveDraftColumnItem;
|
import com.jinrui.reference.core.model.dto.news.SaveDraftColumnItem;
|
||||||
import com.jinrui.reference.core.model.dto.news.SaveDraftColumnVip;
|
import com.jinrui.reference.core.model.dto.news.SaveDraftColumnVip;
|
||||||
|
|
@ -43,26 +47,32 @@ import com.jinrui.reference.core.model.entity.DraftTagRel;
|
||||||
import com.jinrui.reference.core.model.entity.Industry;
|
import com.jinrui.reference.core.model.entity.Industry;
|
||||||
import com.jinrui.reference.core.model.entity.News;
|
import com.jinrui.reference.core.model.entity.News;
|
||||||
import com.jinrui.reference.core.model.entity.NewsColumnRel;
|
import com.jinrui.reference.core.model.entity.NewsColumnRel;
|
||||||
|
import com.jinrui.reference.core.model.entity.NewsDeleted;
|
||||||
import com.jinrui.reference.core.model.entity.NewsDraft;
|
import com.jinrui.reference.core.model.entity.NewsDraft;
|
||||||
import com.jinrui.reference.core.model.entity.NewsIndustryRel;
|
import com.jinrui.reference.core.model.entity.NewsIndustryRel;
|
||||||
import com.jinrui.reference.core.model.entity.NewsInfo;
|
import com.jinrui.reference.core.model.entity.NewsInfo;
|
||||||
import com.jinrui.reference.core.model.entity.NewsTagRel;
|
import com.jinrui.reference.core.model.entity.NewsTagRel;
|
||||||
import com.jinrui.reference.core.model.entity.NewsTags;
|
import com.jinrui.reference.core.model.entity.NewsTags;
|
||||||
import com.jinrui.reference.core.model.entity.Tag;
|
import com.jinrui.reference.core.model.entity.Tag;
|
||||||
|
import com.jinrui.reference.core.model.entity.UserOperationLog;
|
||||||
import com.jinrui.reference.core.model.vo.PageObject;
|
import com.jinrui.reference.core.model.vo.PageObject;
|
||||||
import com.jinrui.reference.core.model.vo.ResultObject;
|
import com.jinrui.reference.core.model.vo.ResultObject;
|
||||||
import com.jinrui.reference.core.model.vo.column.ColumnVO;
|
import com.jinrui.reference.core.model.vo.column.ColumnVO;
|
||||||
|
import com.jinrui.reference.core.model.vo.news.NewsApiVO;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsDetailColumn;
|
import com.jinrui.reference.core.model.vo.news.NewsDetailColumn;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsDetailColumnVip;
|
import com.jinrui.reference.core.model.vo.news.NewsDetailColumnVip;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsDetailIndustry;
|
import com.jinrui.reference.core.model.vo.news.NewsDetailIndustry;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsDetailTag;
|
import com.jinrui.reference.core.model.vo.news.NewsDetailTag;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsDetailTagItem;
|
import com.jinrui.reference.core.model.vo.news.NewsDetailTagItem;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsDetailVO;
|
import com.jinrui.reference.core.model.vo.news.NewsDetailVO;
|
||||||
|
import com.jinrui.reference.core.model.vo.news.NewsLogVO;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsScoreVO;
|
import com.jinrui.reference.core.model.vo.news.NewsScoreVO;
|
||||||
|
import com.jinrui.reference.core.model.vo.news.NewsTranslatorVO;
|
||||||
import com.jinrui.reference.core.model.vo.news.NewsVO;
|
import com.jinrui.reference.core.model.vo.news.NewsVO;
|
||||||
|
|
||||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||||
import co.elastic.clients.elasticsearch._types.Refresh;
|
import co.elastic.clients.elasticsearch._types.Refresh;
|
||||||
|
import co.elastic.clients.elasticsearch.core.GetResponse;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class NewsService {
|
public class NewsService {
|
||||||
|
|
@ -76,6 +86,8 @@ public class NewsService {
|
||||||
private final IndustryMapper industryMapper;
|
private final IndustryMapper industryMapper;
|
||||||
private final ElasticsearchClient elasticsearchClient;
|
private final ElasticsearchClient elasticsearchClient;
|
||||||
private final NewsTagsMapper newsTagsMapper;
|
private final NewsTagsMapper newsTagsMapper;
|
||||||
|
private final NewsDeletedMapper newsDeletedMapper;
|
||||||
|
private final UserOperationLogMapper userOperationLogMapper;
|
||||||
|
|
||||||
public NewsService(NewsMapper newsMapper,
|
public NewsService(NewsMapper newsMapper,
|
||||||
ColumnMapper columnMapper,
|
ColumnMapper columnMapper,
|
||||||
|
|
@ -83,7 +95,9 @@ public class NewsService {
|
||||||
TagMapper tagMapper,
|
TagMapper tagMapper,
|
||||||
IndustryMapper industryMapper,
|
IndustryMapper industryMapper,
|
||||||
ElasticsearchClient elasticsearchClient,
|
ElasticsearchClient elasticsearchClient,
|
||||||
NewsTagsMapper newsTagsMapper) {
|
NewsTagsMapper newsTagsMapper,
|
||||||
|
NewsDeletedMapper newsDeletedMapper,
|
||||||
|
UserOperationLogMapper userOperationLogMapper) {
|
||||||
this.newsMapper = newsMapper;
|
this.newsMapper = newsMapper;
|
||||||
this.columnMapper = columnMapper;
|
this.columnMapper = columnMapper;
|
||||||
this.objectMapper = objectMapper;
|
this.objectMapper = objectMapper;
|
||||||
|
|
@ -91,26 +105,30 @@ public class NewsService {
|
||||||
this.industryMapper = industryMapper;
|
this.industryMapper = industryMapper;
|
||||||
this.elasticsearchClient = elasticsearchClient;
|
this.elasticsearchClient = elasticsearchClient;
|
||||||
this.newsTagsMapper = newsTagsMapper;
|
this.newsTagsMapper = newsTagsMapper;
|
||||||
|
this.newsDeletedMapper = newsDeletedMapper;
|
||||||
|
this.userOperationLogMapper = userOperationLogMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultObject<Void> publish(long id, long editorId) {
|
public ResultObject<Void> publish(long id, long editorId) {
|
||||||
News news = newsMapper.getById(id);
|
News news = newsMapper.getById(id);
|
||||||
if (news == null) {
|
if (news == null) {
|
||||||
log.warn("找不到ID为{}的新闻!", id);
|
log.warn("找不到ID为{}的新闻!", id);
|
||||||
return ResultObject.failed("找不到ID为" + id + "的新闻!");
|
return ResultObject.failed("找不到ID为" + id + "的新闻!");
|
||||||
}
|
}
|
||||||
Integer status = news.getStatus();
|
Integer oldStatus = news.getStatus();
|
||||||
if (status == 2) {
|
if (oldStatus == 1) {
|
||||||
newsMapper.simpleUnpublish(id);
|
return ResultObject.failed("资讯已被撤稿,请刷新列表页面!");
|
||||||
|
}
|
||||||
|
if (oldStatus == 2) {
|
||||||
|
newsMapper.changeFrom(id, oldStatus, 3, editorId);
|
||||||
return ResultObject.success();
|
return ResultObject.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Long draftId = news.getDraftId();
|
Long draftId = news.getDraftId();
|
||||||
if (draftId == null) {
|
if (draftId == null) {
|
||||||
newsMapper.simplePublish(id, editorId);
|
newsMapper.changeFrom(id, oldStatus, 2, editorId);
|
||||||
return ResultObject.success();
|
return ResultObject.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultObject<NewsDetailVO> resultObject = detail(id);
|
ResultObject<NewsDetailVO> resultObject = detail(id);
|
||||||
int code = resultObject.getCode();
|
int code = resultObject.getCode();
|
||||||
NewsDetailVO newsDetailVO = resultObject.getData();
|
NewsDetailVO newsDetailVO = resultObject.getData();
|
||||||
|
|
@ -118,7 +136,7 @@ public class NewsService {
|
||||||
return ResultObject.failed(resultObject.getCode(), resultObject.getMsg());
|
return ResultObject.failed(resultObject.getCode(), resultObject.getMsg());
|
||||||
}
|
}
|
||||||
SaveNewsDTO saveNewsDTO = new SaveNewsDTO(newsDetailVO);
|
SaveNewsDTO saveNewsDTO = new SaveNewsDTO(newsDetailVO);
|
||||||
return createPublish(editorId, saveNewsDTO);
|
return createPublish(editorId, saveNewsDTO, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultObject<NewsDetailVO> detail(Long id) {
|
public ResultObject<NewsDetailVO> detail(Long id) {
|
||||||
|
|
@ -139,6 +157,10 @@ public class NewsService {
|
||||||
NewsDraft newsDraft = newsMapper.getDraftDetail(draftId);
|
NewsDraft newsDraft = newsMapper.getDraftDetail(draftId);
|
||||||
NewsDetailVO newsDetailVO = new NewsDetailVO(newsDraft);
|
NewsDetailVO newsDetailVO = new NewsDetailVO(newsDraft);
|
||||||
newsDetailVO.setId(id);
|
newsDetailVO.setId(id);
|
||||||
|
newsDetailVO.setDeleted(news.getDeleted());
|
||||||
|
newsDetailVO.setNewsInfoId(news.getNewsinfoId());
|
||||||
|
newsDetailVO.setRating(news.getRating());
|
||||||
|
newsDetailVO.setRevision(news.getRevision());
|
||||||
|
|
||||||
Set<Long> set = new HashSet<>();
|
Set<Long> set = new HashSet<>();
|
||||||
set.add(draftId);
|
set.add(draftId);
|
||||||
|
|
@ -221,33 +243,13 @@ public class NewsService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processLLMFlag(newsDetailVO);
|
||||||
// List<NewsTagRel> tagRelListNews = tagMapper.getNewsTagRelList(id);
|
|
||||||
// NewsDetailTag newsDetailTag2 = new NewsDetailTag();
|
|
||||||
// newsDetailVO.setTag(newsDetailTag2);
|
|
||||||
// List<NewsDetailTagItem> arr = new ArrayList<>();
|
|
||||||
// if (!CollectionUtils.isEmpty(tagRelListNews)) {
|
|
||||||
// for (NewsTagRel rel : tagRelListNews) {
|
|
||||||
// Long tagId = rel.getTagId();
|
|
||||||
// Tag tag = tagMap.get(tagId);
|
|
||||||
// Long parentId = tag.getParentId();
|
|
||||||
// NewsDetailTagItem tagItem = new NewsDetailTagItem();
|
|
||||||
// tagItem.setId(tagId);
|
|
||||||
// tagItem.setName(tag.getName());
|
|
||||||
// if (parentId != null && parentId == 1) {
|
|
||||||
// newsDetailTag2.setSource(tagItem);
|
|
||||||
// } else {
|
|
||||||
//// newsDetailTag2.setField(tagItem);
|
|
||||||
// arr.add(tagItem);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// newsDetailTag2.setFieldArr(arr);
|
|
||||||
// }
|
|
||||||
return ResultObject.success(newsDetailVO);
|
return ResultObject.success(newsDetailVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
news = newsMapper.getNewsDetail(id);
|
news = newsMapper.getNewsDetail(id);
|
||||||
NewsDetailVO newsDetailVO = new NewsDetailVO(news);
|
NewsDetailVO newsDetailVO = new NewsDetailVO(news);
|
||||||
|
processLLMFlag(newsDetailVO);
|
||||||
|
|
||||||
Set<Long> set = new HashSet<>();
|
Set<Long> set = new HashSet<>();
|
||||||
set.add(id);
|
set.add(id);
|
||||||
|
|
@ -338,15 +340,49 @@ public class NewsService {
|
||||||
}
|
}
|
||||||
return ResultObject.success(newsDetailVO);
|
return ResultObject.success(newsDetailVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processLLMFlag(NewsDetailVO newsDetailVO) {
|
||||||
|
String newsInfoId = newsDetailVO.getNewsInfoId();
|
||||||
|
String llmFlag = null;
|
||||||
|
if (ObjectUtils.isEmpty(newsInfoId)) {
|
||||||
|
newsDetailVO.markTranslatedFlag(llmFlag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewsTags newsTags = newsTagsMapper.getNewsTagsByNewsId(newsInfoId);
|
||||||
|
if (newsTags == null) {
|
||||||
|
newsDetailVO.markTranslatedFlag(llmFlag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
llmFlag = checkNewsLLMFlag(newsTags);
|
||||||
|
newsDetailVO.markTranslatedFlag(llmFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String checkNewsLLMFlag(NewsTags newsTags) {
|
||||||
|
String llmFlag = null;
|
||||||
|
if (!ObjectUtils.isEmpty(newsTags.getTitle()) && !ObjectUtils.isEmpty(newsTags.getRewriteContent())) {
|
||||||
|
llmFlag = NewsDetailVO.AI_TITLE_CONTENT_FLAG;
|
||||||
|
} else if (!ObjectUtils.isEmpty(newsTags.getTitle())) {
|
||||||
|
llmFlag = NewsDetailVO.AI_TITLE_FLAG;
|
||||||
|
} else if (!ObjectUtils.isEmpty(newsTags.getRewriteContent())) {
|
||||||
|
llmFlag = NewsDetailVO.AI_CONENT_FLAG;
|
||||||
|
}
|
||||||
|
return llmFlag;
|
||||||
|
}
|
||||||
|
|
||||||
public ResultObject<Void> createPublish(Long editorId, SaveNewsDTO saveNewsDTO) {
|
public ResultObject<Void> createPublish(Long editorId, SaveNewsDTO saveNewsDTO, boolean isReviewer) {
|
||||||
Long id = saveNewsDTO.getId();
|
Long id = saveNewsDTO.getId();
|
||||||
Long newsId = saveNewsDTO.getId();
|
Long newsId = saveNewsDTO.getId();
|
||||||
|
Integer newStatus = (isReviewer ? 2: 3);
|
||||||
|
Integer oldStatus = (isReviewer ? 3: 1);
|
||||||
News news;
|
News news;
|
||||||
|
Long draftId = null;
|
||||||
|
String newsInfoId = null;
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
news = newsMapper.getById(id);
|
news = newsMapper.getById(id);
|
||||||
Long draftId = news.getDraftId();
|
draftId = news.getDraftId();
|
||||||
if (draftId != null) {
|
newsInfoId = news.getNewsinfoId();
|
||||||
|
if (draftId != null && newStatus.intValue() == 2) {
|
||||||
deleteDraft(draftId);
|
deleteDraft(draftId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -356,14 +392,20 @@ public class NewsService {
|
||||||
// 已发布
|
// 已发布
|
||||||
saveNewsDTO.setStatus(2);
|
saveNewsDTO.setStatus(2);
|
||||||
saveNewsDTO.setPublishTime(new Date());
|
saveNewsDTO.setPublishTime(new Date());
|
||||||
saveNewDraft(saveNewsDTO, null);
|
saveNewDraft(saveNewsDTO, null, isReviewer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Long newIdRl = saveNewsDTO.getId();
|
Long newIdRl = saveNewsDTO.getId();
|
||||||
news = new News(saveNewsDTO);
|
news = new News(saveNewsDTO);
|
||||||
news.setStatus(2);
|
news.setStatus(newStatus);
|
||||||
news.setEditorId(editorId);
|
news.setEditorId(editorId);
|
||||||
newsMapper.publishNews(news);
|
news.setNewsinfoId(newsInfoId);
|
||||||
|
news.setDraftId(isReviewer ? null: draftId);
|
||||||
|
|
||||||
|
int count = newsMapper.updateNews(news, oldStatus);
|
||||||
|
if (count == 0) {
|
||||||
|
return ResultObject.failed("该资讯正在审核中,请勿重复操作");
|
||||||
|
}
|
||||||
// zzp
|
// zzp
|
||||||
deleteNewsRel(newsId);
|
deleteNewsRel(newsId);
|
||||||
try {
|
try {
|
||||||
|
|
@ -477,57 +519,37 @@ public class NewsService {
|
||||||
elasticsearchClient.update(e -> e.index(NewsInfo.INDEX_NAME).refresh(Refresh.True).id(newsInfoId).doc(newsInfo), NewsInfo.class);
|
elasticsearchClient.update(e -> e.index(NewsInfo.INDEX_NAME).refresh(Refresh.True).id(newsInfoId).doc(newsInfo), NewsInfo.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultObject<Void> saveDraft(SaveNewsDTO saveNewsDTO) {
|
public ResultObject<Void> saveDraft(SaveNewsDTO saveNewsDTO, boolean isReviewer) {
|
||||||
Long id = saveNewsDTO.getId();
|
Long id = saveNewsDTO.getId();
|
||||||
|
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
return saveNewDraft(saveNewsDTO, null);
|
saveNewsDTO.setStatus(1);
|
||||||
|
return saveNewDraft(saveNewsDTO, null, isReviewer);
|
||||||
}
|
}
|
||||||
return updateDraft(saveNewsDTO);
|
return updateDraft(saveNewsDTO, isReviewer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResultObject<Void> updateDraft(SaveNewsDTO saveNewsDTO) {
|
private ResultObject<Void> updateDraft(SaveNewsDTO saveNewsDTO, boolean isReviewer) {
|
||||||
Long id = saveNewsDTO.getId();
|
Long id = saveNewsDTO.getId();
|
||||||
News news = newsMapper.getById(id);
|
News news = newsMapper.getById(id);
|
||||||
Long draftId = news.getDraftId();
|
Long draftId = news.getDraftId();
|
||||||
if (draftId != null) {
|
if (draftId != null) {
|
||||||
deleteDraft(draftId);
|
deleteDraft(draftId);
|
||||||
}
|
}
|
||||||
return saveNewDraft(saveNewsDTO, news);
|
return saveNewDraft(saveNewsDTO, news, isReviewer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResultObject<Void> deleteNews(Long newsId) {
|
public ResultObject<Void> deleteNews(Long newsId, Long editorId) {
|
||||||
News news = newsMapper.getById(newsId);
|
News news = newsMapper.getById(newsId);
|
||||||
Integer status = news.getStatus();
|
Integer status = news.getStatus();
|
||||||
if (status == 2) {
|
if (status == 2) {
|
||||||
return ResultObject.failed("请先手动下架新闻然后进行删除!");
|
return ResultObject.failed("请先手动下架新闻然后进行删除!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Long draftId = news.getDraftId();
|
|
||||||
if (draftId != null) {
|
|
||||||
try {
|
|
||||||
deleteDraft(draftId);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("删除新闻草稿异常!", e);
|
|
||||||
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
deleteNewsRel(newsId);
|
int count = newsMapper.deleteNews(newsId, editorId);
|
||||||
} catch (Exception e) {
|
if (count == 0) {
|
||||||
log.error("删除新闻栏目标签异常!", e);
|
return ResultObject.failed("该资讯正在审核中,请勿重复操作");
|
||||||
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
newsMapper.deleteNews(newsId);
|
|
||||||
String newsInfoId = news.getNewsinfoId();
|
|
||||||
if (!ObjectUtils.isEmpty(newsInfoId)) {
|
|
||||||
NewsInfo deletedNewsInfo = new NewsInfo();
|
|
||||||
deletedNewsInfo.setDeleted(1);
|
|
||||||
elasticsearchClient.update(e -> e.index(NewsInfo.INDEX_NAME)
|
|
||||||
.refresh(Refresh.True)
|
|
||||||
.id(newsInfoId)
|
|
||||||
.doc(deletedNewsInfo), NewsInfo.class);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("删除新闻异常!", e);
|
log.error("删除新闻异常!", e);
|
||||||
|
|
@ -549,7 +571,7 @@ public class NewsService {
|
||||||
industryMapper.deleteDraft(draftId);
|
industryMapper.deleteDraft(draftId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResultObject<Void> saveNewDraft(SaveNewsDTO saveNewsDTO, News news) {
|
private ResultObject<Void> saveNewDraft(SaveNewsDTO saveNewsDTO, News news, boolean isReviewer) {
|
||||||
NewsDraft newsDraft = new NewsDraft(saveNewsDTO);
|
NewsDraft newsDraft = new NewsDraft(saveNewsDTO);
|
||||||
try {
|
try {
|
||||||
newsMapper.saveDraft(newsDraft);
|
newsMapper.saveDraft(newsDraft);
|
||||||
|
|
@ -558,6 +580,7 @@ public class NewsService {
|
||||||
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Integer oldStatus = (isReviewer ? 3: 1);
|
||||||
Long draftId = newsDraft.getId();
|
Long draftId = newsDraft.getId();
|
||||||
if (news == null) {
|
if (news == null) {
|
||||||
news = new News(saveNewsDTO);
|
news = new News(saveNewsDTO);
|
||||||
|
|
@ -570,29 +593,19 @@ public class NewsService {
|
||||||
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Integer status = news.getStatus();
|
|
||||||
String newsInfoId = news.getNewsinfoId();
|
String newsInfoId = news.getNewsinfoId();
|
||||||
if (status < 2) {
|
news = new News(saveNewsDTO);
|
||||||
news = new News(saveNewsDTO);
|
news.setStatus(oldStatus);
|
||||||
news.setStatus(status);
|
news.setDraftId(draftId);
|
||||||
news.setDraftId(draftId);
|
news.setNewsinfoId(newsInfoId);
|
||||||
news.setNewsinfoId(newsInfoId);
|
try {
|
||||||
try {
|
int count = newsMapper.updateNews(news, oldStatus);
|
||||||
newsMapper.updateNews(news);
|
if (count == 0) {
|
||||||
} catch (Exception e) {
|
return ResultObject.failed("该资讯正在审核中,请勿重复操作");
|
||||||
log.error("更新新闻报错!", e);
|
|
||||||
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
news = new News(saveNewsDTO);
|
|
||||||
news.setDraftId(draftId);
|
|
||||||
news.setNewsinfoId(newsInfoId);
|
|
||||||
try {
|
|
||||||
newsMapper.updateNews(news);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("更新新闻报错!", e);
|
|
||||||
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("更新新闻报错!", e);
|
||||||
|
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Long newsId = news.getId();
|
Long newsId = news.getId();
|
||||||
|
|
@ -781,7 +794,7 @@ public class NewsService {
|
||||||
public PageObject<NewsVO> queryNews(String keyword, String columnParam, Integer status, int page, int size,
|
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, Long mediaId,
|
String tag, String industry, Long mediaId,
|
||||||
Date datelineFrom, Date datelineTo) {
|
Date datelineFrom, Date datelineTo, Integer deleted, Byte rating,boolean isReviewer) {
|
||||||
String orderByClause = null;
|
String orderByClause = null;
|
||||||
if (StringUtils.hasText(orderBy)) {
|
if (StringUtils.hasText(orderBy)) {
|
||||||
String orderByStr = orderBy;
|
String orderByStr = orderBy;
|
||||||
|
|
@ -800,6 +813,8 @@ public class NewsService {
|
||||||
orderByClause = orderByClause.replace("news.score", "news_tags.news_score");
|
orderByClause = orderByClause.replace("news.score", "news_tags.news_score");
|
||||||
orderByClause = " IF(ISNULL(news_tags.news_score), 1, 0) asc, " + orderByClause;
|
orderByClause = " IF(ISNULL(news_tags.news_score), 1, 0) asc, " + orderByClause;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
orderByClause = (deleted != null && (deleted.intValue() == 1))? "news.update_time desc":"news.publish_time desc";
|
||||||
}
|
}
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
|
|
@ -844,7 +859,7 @@ public class NewsService {
|
||||||
|
|
||||||
List<News> newsList;
|
List<News> newsList;
|
||||||
try {
|
try {
|
||||||
newsList = newsMapper.queryNews(keywords, minScore, maxScore, columnParam, status, last, orderByClause, size, offset, tags, industries, datelineFrom, datelineTo);
|
newsList = newsMapper.queryNews(keywords, minScore, maxScore, columnParam, status, last, orderByClause, size, offset, tags, industries, datelineFrom, datelineTo, deleted, rating, isReviewer);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("搜索新闻异常!", e);
|
log.error("搜索新闻异常!", e);
|
||||||
return PageObject.failedPage(500, "服务器错误,请联系系统管理员!");
|
return PageObject.failedPage(500, "服务器错误,请联系系统管理员!");
|
||||||
|
|
@ -853,7 +868,7 @@ public class NewsService {
|
||||||
PageObject<NewsVO> pageObject = new PageObject<>();
|
PageObject<NewsVO> pageObject = new PageObject<>();
|
||||||
if (page == 1) {
|
if (page == 1) {
|
||||||
try {
|
try {
|
||||||
int total = newsMapper.queryTotal(keywords,minScore, maxScore, columnParam, status, tags, industries, datelineFrom, datelineTo);
|
int total = newsMapper.queryTotal(keywords,minScore, maxScore, columnParam, status, tags, industries, datelineFrom, datelineTo, deleted, rating, isReviewer);
|
||||||
pageObject.setTotal(total);
|
pageObject.setTotal(total);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("获取新闻总数异常!", e);
|
log.error("获取新闻总数异常!", e);
|
||||||
|
|
@ -958,11 +973,172 @@ public class NewsService {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public ResultObject<NewsTranslatorVO> getTranslator(Long id) {
|
||||||
String keyword = "中国 美国 俄罗斯";
|
News news = newsMapper.getNewsDetail(id);
|
||||||
keyword = keyword.replaceAll("\\s+", "%");
|
String newsInfoId = news.getNewsinfoId();
|
||||||
System.out.println(keyword);
|
if (ObjectUtils.isEmpty(newsInfoId)) {
|
||||||
|
return ResultObject.success();
|
||||||
|
}
|
||||||
|
NewsTranslatorVO newsTranslatorVO = new NewsTranslatorVO();
|
||||||
|
try {
|
||||||
|
GetResponse<ObjectNode> newsInfoResp = elasticsearchClient.get(g -> g.index(NewsInfo.INDEX_NAME).id(newsInfoId), ObjectNode.class);
|
||||||
|
if (!newsInfoResp.found()) {
|
||||||
|
return ResultObject.success();
|
||||||
|
}
|
||||||
|
ObjectNode newsInfo = newsInfoResp.source();
|
||||||
|
String titleEN = Optional.ofNullable(newsInfo.get("title_EN")).filter(JsonNode::isTextual).map(JsonNode::asText).orElse(null);
|
||||||
|
String contentEN = Optional.ofNullable(newsInfo.get("EN_content")).filter(JsonNode::isTextual).map(JsonNode::asText).orElse(null);
|
||||||
|
|
||||||
|
//大模型翻译
|
||||||
|
String title = Optional.ofNullable(newsInfo.at("/news_tags/title")).filter(JsonNode::isTextual).map(JsonNode::asText).orElse(null);
|
||||||
|
String rewriteContent = Optional.ofNullable(newsInfo.at("/news_tags/rewrite_content")).filter(JsonNode::isTextual).map(JsonNode::asText).orElse(null);
|
||||||
|
|
||||||
|
newsTranslatorVO.setTitleEN(titleEN);
|
||||||
|
newsTranslatorVO.setContentEN(contentEN);
|
||||||
|
if (!ObjectUtils.isEmpty(title)) {
|
||||||
|
newsTranslatorVO.setTitleCN(news.getTitle());
|
||||||
|
}
|
||||||
|
if (!ObjectUtils.isEmpty(rewriteContent)) {
|
||||||
|
newsTranslatorVO.setContentCN(news.getContent());
|
||||||
|
}
|
||||||
|
return ResultObject.success(newsTranslatorVO);
|
||||||
|
} catch(IOException e) {
|
||||||
|
log.error("获取全量资讯详情异常!", e);
|
||||||
|
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void backupDuplicatedNews(List<News> newsList, String clusterId) {
|
||||||
|
for (News news: newsList) {
|
||||||
|
NewsDeleted newsDeleted = new NewsDeleted(news, clusterId);
|
||||||
|
newsDeletedMapper.save(newsDeleted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挪到service层
|
||||||
|
* @param newsList
|
||||||
|
*/
|
||||||
|
public void deletDuplicatedNews(List<News> newsList) {
|
||||||
|
for (News news: newsList) {
|
||||||
|
Long draftId = news.getDraftId();
|
||||||
|
if (draftId != null) {
|
||||||
|
newsMapper.deleteDraft(draftId);
|
||||||
|
columnMapper.deleteDraft(draftId);
|
||||||
|
tagMapper.deleteDraft(draftId);
|
||||||
|
industryMapper.deleteDraft(draftId);
|
||||||
|
}
|
||||||
|
Long newsId = news.getId();
|
||||||
|
columnMapper.deleteNews(newsId);
|
||||||
|
tagMapper.deleteNews(newsId);
|
||||||
|
industryMapper.deleteNews(newsId);
|
||||||
|
newsMapper.deleteById(newsId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultObject<Void> recoverNews(Long id, Long adminUserId) {
|
||||||
|
News news = newsMapper.getById(id);
|
||||||
|
if (news == null) {
|
||||||
|
return ResultObject.failed("要恢复的数据不存在,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
newsMapper.recoverNews(id, adminUserId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("恢复新闻异常!", e);
|
||||||
|
return ResultObject.failed(500, "服务器错误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
return ResultObject.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回最近两天的数据
|
||||||
|
* @param num
|
||||||
|
* @param last
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ResultObject<List<NewsApiVO>> requestNewsByApi(Integer num, Long last) {
|
||||||
|
List<NewsApiVO> result = newsMapper.queryNewsByApi(last, Integer.min(num, 1000));
|
||||||
|
|
||||||
|
Map<Long, Industry> industryMap = industryMapper.queryAll().stream().collect(Collectors.toMap(Industry::getId, Function.identity()));
|
||||||
|
result.stream().forEach( e -> {
|
||||||
|
List<Tag> newsTagRels = tagMapper.getNewsTagRelList(e.getId()).stream().map(x -> tagMapper.queryById(x.getTagId())).collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (ObjectUtils.isEmpty(e.getSource())) {
|
||||||
|
Optional<Tag> sourceTag = newsTagRels.stream().filter(x -> x != null && (x.getParentId() == 1L)).findFirst();
|
||||||
|
if (sourceTag.isPresent()) {
|
||||||
|
e.setSource(sourceTag.get().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<String> conceptLabel = newsTagRels.stream().filter(t -> t != null).map(Tag::getDisplayName).collect(Collectors.toList());
|
||||||
|
e.setConceptLabel(conceptLabel);
|
||||||
|
|
||||||
|
List<String> industryLabel = industryMapper.getNewsIndustryRelList(e.getId()).stream().map(x -> industryMap.get(x.getIndustryId())).filter(i -> i != null).map(n -> n.getDisplayName()).collect(Collectors.toList());
|
||||||
|
e.setIndustryLabel(industryLabel);
|
||||||
|
});
|
||||||
|
return ResultObject.success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultObject<Void> submit(long id, long editorId) {
|
||||||
|
News news = newsMapper.getById(id);
|
||||||
|
if (news == null) {
|
||||||
|
log.warn("找不到ID为{}的新闻!", id);
|
||||||
|
return ResultObject.failed("找不到ID为" + id + "的新闻!");
|
||||||
|
}
|
||||||
|
Integer oldStatus = news.getStatus();
|
||||||
|
if (oldStatus != 1) {
|
||||||
|
return ResultObject.failed("该资讯正在审核中,请勿重复操作");
|
||||||
|
}
|
||||||
|
|
||||||
|
newsMapper.changeFrom(id, oldStatus, 3, editorId);
|
||||||
|
return ResultObject.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultObject<Void> revoke(Long id, Long editorId, boolean isReviewer) {
|
||||||
|
News news = newsMapper.getById(id);
|
||||||
|
if (news == null) {
|
||||||
|
log.warn("找不到ID为{}的新闻!", id);
|
||||||
|
return ResultObject.failed("找不到ID为" + id + "的新闻!");
|
||||||
|
}
|
||||||
|
Integer oldStatus = news.getStatus();
|
||||||
|
if (isReviewer) {
|
||||||
|
if (oldStatus != 2) {
|
||||||
|
return ResultObject.failed("该资讯正在审核中,请勿重复操作");
|
||||||
|
}
|
||||||
|
newsMapper.changeFrom(id, oldStatus, 3, editorId);
|
||||||
|
return ResultObject.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldStatus != 3) {
|
||||||
|
return ResultObject.failed("该资讯正在审核中,请勿重复操作");
|
||||||
|
}
|
||||||
|
|
||||||
|
newsMapper.changeFrom(id, oldStatus, 1, editorId);
|
||||||
|
return ResultObject.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PageObject<NewsLogVO> getLog(Long id, int page, int size, Integer current) {
|
||||||
|
int offset = 0;
|
||||||
|
if (current != null) {
|
||||||
|
offset = (Math.max(0, current - 1)) * size;
|
||||||
|
}
|
||||||
|
List<UserOperationLog> dataOperationLogs = userOperationLogMapper.selectByDataIdAndType(id, "news", size, offset);
|
||||||
|
List<NewsLogVO> newsLogList = dataOperationLogs.stream().map(e -> new NewsLogVO(e)).collect(Collectors.toList());
|
||||||
|
|
||||||
|
PageObject<NewsLogVO> pageObject = new PageObject<>();
|
||||||
|
pageObject.setData(newsLogList);
|
||||||
|
pageObject.setCode(200);
|
||||||
|
pageObject.setCurrent(page);
|
||||||
|
size = Math.min(newsLogList.size(), size);
|
||||||
|
pageObject.setSize(size);
|
||||||
|
try {
|
||||||
|
int total = userOperationLogMapper.queryTotal(id, "news");
|
||||||
|
pageObject.setTotal(total);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取新闻总数异常!", e);
|
||||||
|
return PageObject.failedPage(500, "服务器错误,请联系系统管理员!");
|
||||||
|
}
|
||||||
|
return pageObject;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,11 @@
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<!-- <dependency>
|
||||||
<groupId>redis.clients</groupId>
|
<groupId>redis.clients</groupId>
|
||||||
<artifactId>jedis</artifactId>
|
<artifactId>jedis</artifactId>
|
||||||
<version>${jedis.version}</version>
|
<version>${jedis.version}</version>
|
||||||
</dependency>
|
</dependency>-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.elasticsearch.client</groupId>
|
<groupId>org.elasticsearch.client</groupId>
|
||||||
<artifactId>elasticsearch-rest-client</artifactId>
|
<artifactId>elasticsearch-rest-client</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,10 @@
|
||||||
package com.jinrui.reference.mini;
|
package com.jinrui.reference.mini;
|
||||||
|
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
import redis.clients.jedis.JedisPool;
|
|
||||||
import redis.clients.jedis.JedisPoolConfig;
|
|
||||||
|
|
||||||
@SpringBootApplication(scanBasePackages = {
|
@SpringBootApplication(scanBasePackages = {
|
||||||
"com.jinrui.reference.mini",
|
"com.jinrui.reference.mini",
|
||||||
|
|
@ -23,17 +19,17 @@ public class MiniApplication {
|
||||||
SpringApplication.run(MiniApplication.class, args);
|
SpringApplication.run(MiniApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
// @Bean
|
||||||
public JedisPool jedisPool(@Value("${redis.host}") String host,
|
// public JedisPool jedisPool(@Value("${redis.host}") String host,
|
||||||
@Value("${redis.port}") int port,
|
// @Value("${redis.port}") int port,
|
||||||
@Value("${redis.timeout:1000}") int timeout,
|
// @Value("${redis.timeout:1000}") int timeout,
|
||||||
@Value("${redis.password:}") String password) {
|
// @Value("${redis.password:}") String password) {
|
||||||
if (StringUtils.hasText(password)) {
|
// if (StringUtils.hasText(password)) {
|
||||||
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
|
// JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
|
||||||
return new JedisPool(jedisPoolConfig, host, port, timeout, password);
|
// return new JedisPool(jedisPoolConfig, host, port, timeout, password);
|
||||||
}
|
// }
|
||||||
return new JedisPool(host, port);
|
// return new JedisPool(host, port);
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public RestTemplate restTemplate() {
|
public RestTemplate restTemplate() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue