feat(erp):优化品牌商标缓存与方舟API调用逻辑

- 品牌商标缓存服务增加一天内去重保存逻辑- 方舟API调用支持TOKEN失效自动重新注册
- 增加证书验证失败重试机制
- 修复代理池API签名密钥
-优化商标检查面板完成状态计算逻辑- 更新应用配置注释格式
This commit is contained in:
2025-11-17 14:34:08 +08:00
parent 937a84bb81
commit d29d4d69da
9 changed files with 112 additions and 24 deletions

View File

@@ -1012,13 +1012,12 @@ onUnmounted(() => {
width: 100%; width: 100%;
height: 60px; height: 60px;
margin-bottom: 16px; margin-bottom: 16px;
padding: 0 4px;
box-sizing: border-box; box-sizing: border-box;
} }
.brand-logo { .brand-logo {
max-width: 100%; width: 100%;
max-height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
border-radius: 12px; border-radius: 12px;
} }

View File

@@ -582,7 +582,7 @@ async function startTrademarkQuery() {
if (!trademarkLoading.value) return if (!trademarkLoading.value) return
await processBrandResult(brandResult) await processBrandResult(brandResult)
brandData.completed = brandResult.data.unregistered || 0 brandData.completed = trademarkFullData.value.length
queryStatus.value = 'done' queryStatus.value = 'done'
trademarkProgress.value = 100 trademarkProgress.value = 100
@@ -1006,12 +1006,11 @@ defineExpose({
</div> </div>
</div> </div>
<!-- 3. 选择需查询的可多选 -->
<div class="flow-item"> <div class="flow-item">
<div class="step-index">3</div> <div class="step-index">3</div>
<div class="step-card"> <div class="step-card">
<div class="step-header"> <div class="step-header">
<div class="title">选择需查询的可多选</div> <div class="title">商标筛查条件</div>
</div> </div>
<div class="desc">商标筛查包含以下维度,后续将开放更 <div class="desc">商标筛查包含以下维度,后续将开放更
多维度的筛查条件与自定义条件组合功 多维度的筛查条件与自定义条件组合功

View File

@@ -30,11 +30,22 @@ public class BrandTrademarkCacheServiceImpl implements BrandTrademarkCacheServic
@Override @Override
public void saveResults(Map<String, Boolean> results) { public void saveResults(Map<String, Boolean> results) {
LocalDateTime cutoffTime = LocalDateTime.now().minusDays(1);
results.forEach((brand, registered) -> { results.forEach((brand, registered) -> {
repository.findByBrandAndCreatedAtAfter(brand, cutoffTime)
.ifPresentOrElse(
existing -> {
existing.setRegistered(registered);
existing.setCreatedAt(LocalDateTime.now());
repository.save(existing);
},
() -> {
BrandTrademarkCacheEntity entity = new BrandTrademarkCacheEntity(); BrandTrademarkCacheEntity entity = new BrandTrademarkCacheEntity();
entity.setBrand(brand); entity.setBrand(brand);
entity.setRegistered(registered); entity.setRegistered(registered);
repository.save(entity); repository.save(entity);
}
);
}); });
} }

View File

@@ -14,6 +14,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@@ -97,10 +98,11 @@ public class FangzhouApiServiceImpl implements IFangzhouApiService {
String result = restTemplate.postForObject(FANGZHOU_API_URL, requestEntity, String.class); String result = restTemplate.postForObject(FANGZHOU_API_URL, requestEntity, String.class);
JsonNode json = objectMapper.readTree(result); JsonNode json = objectMapper.readTree(result);
// 处理 Token 过期,自动刷新重试 // 处理 Token 失效
if (json.get("S").asInt() == TOKEN_EXPIRED_CODE) { int statusCode = json.get("S").asInt();
logger.info("Token 过期,刷新后重试"); if (statusCode == TOKEN_EXPIRED_CODE || statusCode == -1002) {
String newToken = refreshToken(); String newToken = statusCode == -1002 ? getToken() : refreshToken();
logger.info("Token 失效({}), {}后重试", statusCode, statusCode == -1002 ? "重新注册" : "刷新");
formData.set("t", newToken); formData.set("t", newToken);
formData.set("s", md5(ts + data + API_SECRET)); formData.set("s", md5(ts + data + API_SECRET));
requestEntity = new HttpEntity<>(formData, headers); requestEntity = new HttpEntity<>(formData, headers);
@@ -109,6 +111,27 @@ public class FangzhouApiServiceImpl implements IFangzhouApiService {
} }
return json; return json;
} catch (ResourceAccessException e) {
logger.warn("证书验证失败,尝试重新注册: {}", e.getMessage());
String newToken = refreshToken();
long ts = System.currentTimeMillis();
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("c", command);
formData.add("d", data);
formData.add("t", newToken);
formData.add("s", md5(ts + data + API_SECRET));
formData.add("ts", String.valueOf(ts));
formData.add("website", "1");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
try {
String result = restTemplate.postForObject(FANGZHOU_API_URL, requestEntity, String.class);
return objectMapper.readTree(result);
} catch (Exception ex) {
logger.error("重试失败", ex);
throw new RuntimeException("调用 API 失败: " + ex.getMessage());
}
} catch (Exception e) { } catch (Exception e) {
logger.error("调用方舟精选 API 失败", e); logger.error("调用方舟精选 API 失败", e);
throw new RuntimeException("调用 API 失败: " + e.getMessage()); throw new RuntimeException("调用 API 失败: " + e.getMessage());
@@ -137,10 +160,11 @@ public class FangzhouApiServiceImpl implements IFangzhouApiService {
String result = restTemplate.postForObject(FANGZHOU_API_URL, requestEntity, String.class); String result = restTemplate.postForObject(FANGZHOU_API_URL, requestEntity, String.class);
JsonNode json = objectMapper.readTree(result); JsonNode json = objectMapper.readTree(result);
// 处理 Token 过期 // 处理 Token 失效
if (json.get("S").asInt() == TOKEN_EXPIRED_CODE) { int statusCode = json.get("S").asInt();
logger.info("Token 过期,刷新后重试"); if (statusCode == TOKEN_EXPIRED_CODE || statusCode == -1002) {
String newToken = refreshToken(); String newToken = statusCode == -1002 ? getToken() : refreshToken();
logger.info("Token 失效({}), {}后重试", statusCode, statusCode == -1002 ? "重新注册" : "刷新");
formData.set("t", newToken); formData.set("t", newToken);
formData.set("s", md5(ts + data + API_SECRET)); formData.set("s", md5(ts + data + API_SECRET));
requestEntity = new HttpEntity<>(formData, headers); requestEntity = new HttpEntity<>(formData, headers);
@@ -149,6 +173,29 @@ public class FangzhouApiServiceImpl implements IFangzhouApiService {
} }
return json; return json;
} catch (ResourceAccessException e) {
logger.warn("证书验证失败,尝试重新注册: {}", e.getMessage());
String newToken = refreshToken();
String data = String.format("{\"name\":\"%s\",\"type\":1}", file.getOriginalFilename());
long ts = System.currentTimeMillis();
MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
formData.add("c", "Create");
formData.add("t", newToken);
formData.add("ts", ts);
formData.add("d", data);
formData.add("s", md5(ts + data + API_SECRET));
formData.add("website", "1");
formData.add("files", file.getResource());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(formData, headers);
try {
String result = restTemplate.postForObject(FANGZHOU_API_URL, requestEntity, String.class);
return objectMapper.readTree(result);
} catch (Exception ex) {
logger.error("重试失败", ex);
throw new RuntimeException("上传文件失败: " + ex.getMessage());
}
} catch (Exception e) { } catch (Exception e) {
logger.error("上传文件失败", e); logger.error("上传文件失败", e);
throw new RuntimeException("上传文件失败: " + e.getMessage()); throw new RuntimeException("上传文件失败: " + e.getMessage());

View File

@@ -11,7 +11,7 @@ import java.util.List;
@Component @Component
public class ProxyPool { public class ProxyPool {
private static final String API_URL = "http://api.tianqiip.com/getip?secret=y0thbcco1rgxn9e9&num=%d&type=txt&port=2&time=3&mr=1&sign=a8a42f3cd3f22a7fbf84530deb91c1d8"; private static final String API_URL = "http://api.tianqiip.com/getip?secret=y0thbcco1rgxn9e9&num=%d&type=txt&port=2&time=3&mr=1&sign=9be780c7e27aea815f1e0874446b9e35";
/** /**
* 获取一个代理IP * 获取一个代理IP

View File

@@ -48,7 +48,7 @@ api:
server: server:
# 主服务器API配置 # 主服务器API配置
base-url: "http://8.138.23.49:8085" base-url: "http://8.138.23.49:8085"
# base-url: "http://192.168.1.89:8085" #base-url: "http://192.168.1.89:8085"
paths: paths:
monitor: "/monitor/client/api" monitor: "/monitor/client/api"
login: "/monitor/account/login" login: "/monitor/account/login"

View File

@@ -27,7 +27,7 @@ public class MarkController {
/** /**
* 获取 Token * 获取 Token
* 如果 Redis 中不存在 Token自动注册新账号 * 如果 Redis 中不存在 Token 或 Token 不可用,自动注册新账号
* *
* @return Token 字符串 * @return Token 字符串
*/ */
@@ -37,11 +37,12 @@ public class MarkController {
// 先尝试从 Redis 获取现有 Token // 先尝试从 Redis 获取现有 Token
String token = redisCache.getCacheMapValue(CacheConstants.MARK_ACCOUNT_KEY, "token"); String token = redisCache.getCacheMapValue(CacheConstants.MARK_ACCOUNT_KEY, "token");
if (token != null && !token.isEmpty()) { // 验证 Token 是否可用
if (token != null && !token.isEmpty() && markService.validateToken(token)) {
return AjaxResult.success("获取成功", token); return AjaxResult.success("获取成功", token);
} }
// Token 不存在,自动注册新账号 // Token 不存在或不可用,重新注册新账号
token = markService.reg(); token = markService.reg();
return AjaxResult.success("注册成功", token); return AjaxResult.success("注册成功", token);

View File

@@ -21,5 +21,12 @@ public interface IMarkService {
* 登录 * 登录
*/ */
String login(); String login();
/**
* 验证Token是否可用
* @param token 待验证的Token
* @return true=可用, false=不可用
*/
boolean validateToken(String token);
} }

View File

@@ -124,5 +124,29 @@ public class MarkServiceImpl implements IMarkService {
throw new RuntimeException("MD5加密失败", e); throw new RuntimeException("MD5加密失败", e);
} }
} }
@Override
public boolean validateToken(String token) {
try {
String data = "{\"name\":\"\",\"page_size\":1,\"current_page\":1}";
long ts = System.currentTimeMillis();
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("c", "TaskPageList");
formData.add("d", data);
formData.add("t", token);
formData.add("s", md5(ts + data + API_SECRET));
formData.add("ts", String.valueOf(ts));
formData.add("website", "1");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
String result = restTemplate.postForObject("https://api.fangzhoujingxuan.com/Task", requestEntity, String.class);
JsonNode json = objectMapper.readTree(result);
int statusCode = json.get("S").asInt();
return statusCode == 1;
} catch (Exception e) {
return false;
}
}
} }