新增媒资全量聚合接口并支持多栏目查询

- 新增 /openapi/partner/media/list-all 接口,按一级栏目(如471电影)聚合其下所有二级栏目内容一次返回,解决第三方逐个栏目频繁调用后端的问题
- /list 接口支持 catalogid 逗号分隔传多个,单栏目走橘视厅原生分页,多栏目聚合后本地分页
- JetsenMediaClient 抽取 fetchByCatalogIds 方法,fetchAllByParentCatalog 复用,pagesize=5000 一次拉取减少请求数
This commit is contained in:
zhaogd
2026-07-28 11:15:23 +08:00
parent 30198c7191
commit 100aaa62c3
2 changed files with 137 additions and 15 deletions

View File

@@ -150,6 +150,52 @@ public class JetsenMediaClient {
return tree; return tree;
} }
/**
* 按多个栏目id聚合拉取内容(各栏目全量拉取后合并,不去重)
* @param catalogids 栏目id列表
* @return 合并后的全部内容列表
*/
public List<JSONObject> fetchByCatalogIds(List<String> catalogids) {
List<JSONObject> all = new ArrayList<>();
for (String catalogid : catalogids) {
int page = 1;
int fetched = 0;
while (true) {
JSONObject resp = getContentList(catalogid, page, 5000);
List<JSONObject> items = extractList(resp);
all.addAll(items);
fetched += items.size();
Integer totalPage = resp.getInteger("pagetotal");
if (totalPage == null || page >= totalPage || items.isEmpty()) {
break;
}
page++;
}
logger.info("栏目[{}]拉取完成, 本栏目{}条, 累计{}条", catalogid, fetched, all.size());
}
return all;
}
/**
* 按一级栏目全量拉取内容
* <p>遍历一级栏目下所有二级子栏目,分页拉取全部内容并合并返回(不去重,第三方自行处理)。</p>
* <p>用于第三方一次性获取某一级栏目(如471电影)下的全部内容,避免逐个子栏目多次请求。</p>
*
* @param parentCatalogid 一级栏目id(如 "471"=电影)
* @return 全部内容列表(各二级栏目合并,可能存在跨栏目重复)
*/
public List<JSONObject> fetchAllByParentCatalog(String parentCatalogid) {
List<JSONObject> subs = extractList(getTagsList(parentCatalogid));
logger.info("全量拉取一级栏目[{}]下{}个二级栏目", parentCatalogid, subs.size());
List<String> subIds = new ArrayList<>();
for (JSONObject sub : subs) {
subIds.add(String.valueOf(sub.get("id")));
}
List<JSONObject> all = fetchByCatalogIds(subIds);
logger.info("一级栏目[{}]全量拉取完成, 共{}条", parentCatalogid, all.size());
return all;
}
/** 从橘视厅响应 result 字段提取为 List */ /** 从橘视厅响应 result 字段提取为 List */
private List<JSONObject> extractList(JSONObject resp) { private List<JSONObject> extractList(JSONObject resp) {
List<JSONObject> list = new ArrayList<>(); List<JSONObject> list = new ArrayList<>();

View File

@@ -190,26 +190,39 @@ public class OpenApiMediaController {
data.put("list", from < total ? all.subList(from, to) : new ArrayList<>()); data.put("list", from < total ? all.subList(from, to) : new ArrayList<>());
data.put("totalCount", total); data.put("totalCount", total);
data.put("totalPage", (total + pagesize - 1) / pagesize); data.put("totalPage", (total + pagesize - 1) / pagesize);
} else if (catalogIds != null) {
// CATALOG级别:校验catalogid在授权范围内
if (StringUtils.isBlank(catalogid) || !catalogIds.contains(catalogid)) {
logCall(req, "/list", "GET", 400, start);
return R.error("catalogid不在授权范围内,可用栏目: " + pkg.getCatalogIds());
}
JSONObject resp = jetsenMediaClient.getContentList(catalogid, pageindex, pagesize);
data.put("list", extractList(resp));
data.put("totalCount", resp.getIntValue("sizetotal"));
data.put("totalPage", resp.getIntValue("pagetotal"));
} else { } else {
// FULL级别:直接查 // CATALOG / FULL 级别
if (StringUtils.isBlank(catalogid)) { if (StringUtils.isBlank(catalogid)) {
logCall(req, "/list", "GET", 400, start); logCall(req, "/list", "GET", 400, start);
return R.error("catalogid不能为空"); return R.error("catalogid不能为空");
} }
JSONObject resp = jetsenMediaClient.getContentList(catalogid, pageindex, pagesize); // 解析 catalogid(支持逗号分隔多个)
data.put("list", extractList(resp)); List<String> ids = parseCatalogIdList(catalogid);
data.put("totalCount", resp.getIntValue("sizetotal")); // CATALOG级别:校验每个 catalogid 都在授权范围内
data.put("totalPage", resp.getIntValue("pagetotal")); if (catalogIds != null) {
for (String id : ids) {
if (!catalogIds.contains(id)) {
logCall(req, "/list", "GET", 400, start);
return R.error("catalogid[" + id + "]不在授权范围内,可用栏目: " + pkg.getCatalogIds());
}
}
}
if (ids.size() == 1) {
// 单栏目:橘视厅分页
JSONObject resp = jetsenMediaClient.getContentList(ids.get(0), pageindex, pagesize);
data.put("list", extractList(resp));
data.put("totalCount", resp.getIntValue("sizetotal"));
data.put("totalPage", resp.getIntValue("pagetotal"));
} else {
// 多栏目:聚合全量 + 本地分页
List<JSONObject> all = jetsenMediaClient.fetchByCatalogIds(ids);
int total = all.size();
int from = Math.max(0, (pageindex - 1) * pagesize);
int to = Math.min(from + pagesize, total);
data.put("list", from < total ? all.subList(from, to) : new ArrayList<>());
data.put("totalCount", total);
data.put("totalPage", (total + pagesize - 1) / pagesize);
}
} }
data.put("currPage", pageindex); data.put("currPage", pageindex);
data.put("pageSize", pagesize); data.put("pageSize", pagesize);
@@ -217,6 +230,69 @@ public class OpenApiMediaController {
return R.dataSuccess(data); return R.dataSuccess(data);
} }
/**
* 全量内容列表(按一级栏目聚合)
* <p>一次请求返回某一级栏目(如471电影)下所有二级栏目去重后的全部内容。</p>
* <p>第三方低频调用(建议按天),避免逐个 catalogid 多次请求后端。</p>
* <p>三级授权:CONTENT(按contentcode过滤) > CATALOG(按授权栏目过滤) > FULL(全量)</p>
*/
@ApiOperation("全量内容列表(按一级栏目聚合)")
@GetMapping("/list-all")
public R listAll(@RequestParam(defaultValue = "471") String parentCatalogid,
HttpServletRequest req) {
long start = System.currentTimeMillis();
String partnerId = partnerIdFrom(req);
ContentPackageEntity pkg = contentPackageService.getByPartnerId(partnerId);
Set<String> contentCodes = parseContentCodes(pkg);
Set<String> catalogIds = parseCatalogIds(pkg);
List<JSONObject> all = jetsenMediaClient.fetchAllByParentCatalog(parentCatalogid);
if (contentCodes != null) {
// CONTENT级别:只保留授权contentcode
all = new ArrayList<>(all);
all.removeIf(item -> !contentCodes.contains(item.getString("contentcode")));
} else if (catalogIds != null) {
// CATALOG级别:只保留属于授权二级栏目的内容(item的catalogid为逗号分隔多栏目串)
all = new ArrayList<>(all);
all.removeIf(item -> !catalogMatch(item, catalogIds));
}
// FULL: 返回全量
Map<String, Object> data = new HashMap<>();
data.put("list", all);
data.put("totalCount", all.size());
data.put("parentCatalogid", parentCatalogid);
logCall(req, "/list-all", "GET", 0, start);
return R.dataSuccess(data);
}
/** 判断内容的 catalogid 逗号串是否命中任一授权栏目 */
private boolean catalogMatch(JSONObject item, Set<String> catalogIds) {
String cats = item.getString("catalogid");
if (cats == null) {
return false;
}
for (String c : cats.split(",")) {
if (catalogIds.contains(c.trim())) {
return true;
}
}
return false;
}
/** 解析 catalogid 参数(支持逗号分隔多个) */
private List<String> parseCatalogIdList(String catalogid) {
List<String> ids = new ArrayList<>();
for (String s : catalogid.split(",")) {
String t = s.trim();
if (!t.isEmpty()) {
ids.add(t);
}
}
return ids;
}
/** 搜索(按授权过滤) */ /** 搜索(按授权过滤) */
@ApiOperation("搜索") @ApiOperation("搜索")
@GetMapping("/search") @GetMapping("/search")