1. 前端页面优化, 增强统计功能, 支持生成二维码

2. 添加统计接口
This commit is contained in:
QAIU
2024-09-24 17:08:29 +08:00
parent 0d5c9651f0
commit e002d19f1b
15 changed files with 5380 additions and 3849 deletions

View File

@@ -51,7 +51,7 @@ public class CacheManager {
.mapEmpty();
}
// 统计网盘厂商API解析次数
// 写入网盘厂商API解析次数
public Future<Integer> updateTotalByCached(String shareKey) {
Promise<Integer> promise = Promise.promise();
String sql = """
@@ -81,7 +81,7 @@ public class CacheManager {
return fullShareKey.split(":")[0];
}
// 统计网盘厂商API解析次数
// 写入网盘厂商API解析次数
public Future<Integer> updateTotalByParser(String shareKey) {
Promise<Integer> promise = Promise.promise();
String sql = """
@@ -125,5 +125,31 @@ public class CacheManager {
return promise.future();
}
public Future<Map<String, Integer>> getShareKeyTotal(String shareKey) {
String sql = """
select `share_key`, sum(cache_hit_total) hit_total, sum(api_parser_total) parser_total,
from `api_statistics_info`
group by `share_key` having `share_key` = #{shareKey}
""";
Promise<Map<String, Integer>> promise = Promise.promise();
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("shareKey", shareKey);
SqlTemplate.forQuery(jdbcPool, sql)
.mapTo(Row::toJson)
.execute(paramMap)
.onSuccess(res -> {
if(res.iterator().hasNext()) {
JsonObject next = res.iterator().next();
Map<String, Integer> resp = new HashMap<>(){{
put("hit_total" ,next.getInteger("hit_total"));
put("parser_total" ,next.getInteger("parser_total"));
}};
promise.complete(resp);
} else {
promise.complete();
}
});
return promise.future();
}
}

View File

@@ -0,0 +1,83 @@
package cn.qaiu.lz.web.controller;
import cn.qaiu.entity.ShareLinkInfo;
import cn.qaiu.lz.common.cache.CacheManager;
import cn.qaiu.lz.common.util.URLParamUtil;
import cn.qaiu.lz.web.model.LinkInfoResp;
import cn.qaiu.lz.web.model.SysUser;
import cn.qaiu.lz.web.service.DbService;
import cn.qaiu.lz.web.service.UserService;
import cn.qaiu.lz.web.model.StatisticsInfo;
import cn.qaiu.parser.ParserCreate;
import cn.qaiu.vx.core.annotaions.RouteHandler;
import cn.qaiu.vx.core.annotaions.RouteMapping;
import cn.qaiu.vx.core.enums.RouteMethod;
import cn.qaiu.vx.core.util.AsyncServiceUtil;
import cn.qaiu.vx.core.util.ResponseUtil;
import cn.qaiu.vx.core.util.SharedDataUtil;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.net.HostAndPort;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@RouteHandler(value = "/v2", order = 10)
@Slf4j
public class ParserApi {
private final UserService userService = AsyncServiceUtil.getAsyncServiceInstance(UserService.class);
private final DbService dbService = AsyncServiceUtil.getAsyncServiceInstance(DbService.class);
@RouteMapping(value = "/login", method = RouteMethod.POST)
public Future<SysUser> login(SysUser user) {
log.info("<------- login: {}", user.getUsername());
return userService.login(user);
}
@RouteMapping(value = "/statisticsInfo", method = RouteMethod.GET, order = 99)
public Future<StatisticsInfo> statisticsInfo() {
return dbService.getStatisticsInfo();
}
private final CacheManager cacheManager = new CacheManager();
@RouteMapping(value = "/linkInfo", method = RouteMethod.GET)
public Future<LinkInfoResp> parse(HttpServerRequest request, String pwd) {
Promise<LinkInfoResp> promise = Promise.promise();
String url = URLParamUtil.parserParams(request);
ShareLinkInfo shareLinkInfo = ParserCreate.fromShareUrl(url).setShareLinkInfoPwd(pwd).getShareLinkInfo();
LinkInfoResp build = LinkInfoResp.builder()
.downLink(getDownLink(shareLinkInfo, false))
.apiLink(getDownLink(shareLinkInfo, true))
.shareLinkInfo(shareLinkInfo).build();
// 解析次数统计
cacheManager.getShareKeyTotal(shareLinkInfo.getCacheKey()).onSuccess(res -> {
if (res != null) {
build.setCacheHitTotal(res.get("hit_total") == null ? 0: res.get("hit_total"));
build.setParserTotal(res.get("parser_total") == null ? 0: res.get("parser_total"));
build.setSumTotal(build.getCacheHitTotal() + build.getParserTotal());
}
promise.complete(build);
}).onFailure(t->{
t.printStackTrace();
promise.complete(build);
});
return promise.future();
}
private static String getDownLink(ShareLinkInfo shareLinkInfo, boolean isJson) {
String linkPrefix = SharedDataUtil.getJsonConfig("server")
.getString("domainName");
if (StringUtils.isBlank(linkPrefix)) {
linkPrefix = "http://127.0.0.1";
}
String pwd = shareLinkInfo.getSharePassword();
return linkPrefix + (isJson ? "/json/" : "/") + shareLinkInfo.getType() + "/" + shareLinkInfo.getShareKey() +
(StringUtils.isBlank(pwd) ? "" : ("@" + pwd));
}
}

View File

@@ -1,4 +1,4 @@
package cn.qaiu.lz.web.http;
package cn.qaiu.lz.web.controller;
import cn.qaiu.lz.common.util.URLParamUtil;
import cn.qaiu.lz.web.model.CacheLinkInfo;
@@ -26,7 +26,7 @@ public class ServerApi {
private final CacheService cacheService = AsyncServiceUtil.getAsyncServiceInstance(CacheService.class);
@RouteMapping(value = "/parser", method = RouteMethod.GET, order = 4)
@RouteMapping(value = "/parser", method = RouteMethod.GET, order = 1)
public Future<Void> parse(HttpServerResponse response, HttpServerRequest request, String pwd) {
Promise<Void> promise = Promise.promise();
String url = URLParamUtil.parserParams(request);
@@ -40,13 +40,13 @@ public class ServerApi {
return promise.future();
}
@RouteMapping(value = "/json/parser", method = RouteMethod.GET, order = 3)
@RouteMapping(value = "/json/parser", method = RouteMethod.GET, order = 1)
public Future<CacheLinkInfo> parseJson(HttpServerRequest request, String pwd) {
String url = URLParamUtil.parserParams(request);
return cacheService.getCachedByShareUrlAndPwd(url, pwd);
}
@RouteMapping(value = "/json/:type/:key", method = RouteMethod.GET, order = 2)
@RouteMapping(value = "/json/:type/:key", method = RouteMethod.GET)
public Future<CacheLinkInfo> parseKeyJson(String type, String key) {
String pwd = "";
if (key.contains("@")) {
@@ -57,7 +57,7 @@ public class ServerApi {
return cacheService.getCachedByShareKeyAndPwd(type, key, pwd);
}
@RouteMapping(value = "/:type/:key", method = RouteMethod.GET, order = 1)
@RouteMapping(value = "/:type/:key", method = RouteMethod.GET)
public Future<Void> parseKey(HttpServerResponse response, String type, String key) {
Promise<Void> promise = Promise.promise();
String pwd = "";

View File

@@ -1,32 +0,0 @@
package cn.qaiu.lz.web.http;
import cn.qaiu.lz.web.model.SysUser;
import cn.qaiu.lz.web.service.DbService;
import cn.qaiu.lz.web.service.UserService;
import cn.qaiu.lz.web.model.StatisticsInfo;
import cn.qaiu.vx.core.annotaions.RouteHandler;
import cn.qaiu.vx.core.annotaions.RouteMapping;
import cn.qaiu.vx.core.enums.RouteMethod;
import cn.qaiu.vx.core.util.AsyncServiceUtil;
import io.vertx.core.Future;
import lombok.extern.slf4j.Slf4j;
@RouteHandler(value = "/v2", order = 10)
@Slf4j
public class ParserApi {
private final UserService userService = AsyncServiceUtil.getAsyncServiceInstance(UserService.class);
private final DbService dbService = AsyncServiceUtil.getAsyncServiceInstance(DbService.class);
@RouteMapping(value = "/login", method = RouteMethod.POST)
public Future<SysUser> login(SysUser user) {
log.info("<------- login: {}", user.getUsername());
return userService.login(user);
}
@RouteMapping(value = "/statisticsInfo", method = RouteMethod.GET, order = 99)
public Future<StatisticsInfo> statisticsInfo() {
return dbService.getStatisticsInfo();
}
}

View File

@@ -0,0 +1,17 @@
package cn.qaiu.lz.web.model;
import cn.qaiu.entity.ShareLinkInfo;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class LinkInfoResp {
// 解析链接
private String downLink;
private String apiLink;
private Integer cacheHitTotal;
private Integer parserTotal;
private Integer sumTotal;
private ShareLinkInfo shareLinkInfo;
}

View File

@@ -23,8 +23,8 @@ public class CacheServiceImpl implements CacheService {
Promise<CacheLinkInfo> promise = Promise.promise();
// 构建组合的缓存key
ShareLinkInfo shareLinkInfo = parserCreate.getShareLinkInfo();
String cacheKey = generateCacheKey(shareLinkInfo.getType(), shareLinkInfo.getShareKey());
// 尝试从缓存中获取
String cacheKey = shareLinkInfo.getCacheKey();
cacheManager.get(cacheKey).onSuccess(result -> {
// 判断是否已过期
// 未命中或者过期
@@ -57,11 +57,6 @@ public class CacheServiceImpl implements CacheService {
return promise.future();
}
private String generateCacheKey(String type, String shareKey) {
// 将type和shareKey组合成一个字符串作为缓存key
return type + ":" + shareKey;
}
private String generateDate(Long ts) {
return DateFormatUtils.format(new Date(ts), "yyyy-MM-dd HH:mm:ss");
}

View File

@@ -2,11 +2,14 @@
server:
port: 6400
contextPath: /
# 使用静态页面
enableStaticHtmlService: false
# 使用数据库
enableDatabase: true
# 使用静态页面
enableStaticHtmlService: false
staticResourcePath: webroot/
# 服务域名或者IP
domainName: https://lz.qaiu.top
# 反向代理服务器配置路径(不用加后缀)
proxyConf: server-proxy

View File

@@ -152,6 +152,9 @@ GET http://127.0.0.1:6400/json/parser?url=https://iwx.mail.qq.com/ftn/download?f
###
GET http://127.0.0.1:6400/v2/statisticsInfo
###
GET http://127.0.0.1:6400/v2/linkInfo?url=https://www.123pan.com/s/iaKtVv-6OECd.html&pwd=DcGe
###
POST http://127.0.0.1:6400/v2/login?username=asd