|
@@ -646,6 +646,7 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
/** 服务号推送 / 公众号推送 走 Daily 人群_渠道,与即转稳定数据隔离 */
|
|
/** 服务号推送 / 公众号推送 走 Daily 人群_渠道,与即转稳定数据隔离 */
|
|
|
private static final String CHANNEL_NAME_GZH_DAILY = "公众号合作-Daily-自选";
|
|
private static final String CHANNEL_NAME_GZH_DAILY = "公众号合作-Daily-自选";
|
|
|
private static final String CHANNEL_NAME_QW = "群/企微合作-稳定";
|
|
private static final String CHANNEL_NAME_QW = "群/企微合作-稳定";
|
|
|
|
|
+ private static final String CHANNEL_NAME_XCX = "小程序投流-稳定";
|
|
|
private static final double PRIOR_GROUP_KEEP_RATIO = 0.5;
|
|
private static final double PRIOR_GROUP_KEEP_RATIO = 0.5;
|
|
|
/** posterior 按 demand_content_id 分组后保留 total_rov 排名前 50% 的需求组,
|
|
/** posterior 按 demand_content_id 分组后保留 total_rov 排名前 50% 的需求组,
|
|
|
* 砍掉群体表现弱的需求,避免低 total_rov 的 demand 带回来的相似变体稀释结果。 */
|
|
* 砍掉群体表现弱的需求,避免低 total_rov 的 demand 带回来的相似变体稀释结果。 */
|
|
@@ -657,10 +658,10 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
/**
|
|
/**
|
|
|
* 推导 channel_name(人群_渠道) 作为 demand 池强过滤。
|
|
* 推导 channel_name(人群_渠道) 作为 demand 池强过滤。
|
|
|
* 信号优先级:
|
|
* 信号优先级:
|
|
|
- * 1. type 明确时按 type 映射 — 0→公众号合作-即转-稳定;1/4→公众号合作-Daily-自选;2/3→群/企微合作-稳定
|
|
|
|
|
|
|
+ * 1. type 明确时按 type 映射 — 0→公众号合作-即转-稳定;1/4→公众号合作-Daily-自选;2/3→群/企微合作-稳定;5→小程序投流-稳定
|
|
|
* 2. type=999/null 但带 ghName(公众号参数)→ 公众号入口,映射即转稳定(与历史一致)
|
|
* 2. type=999/null 但带 ghName(公众号参数)→ 公众号入口,映射即转稳定(与历史一致)
|
|
|
* 3. 否则 null,不限 channel_name(保留原行为)
|
|
* 3. 否则 null,不限 channel_name(保留原行为)
|
|
|
- * type 取值: 0-自动回复(公众号入口) / 1-服务号推送 / 2-企微-社群 / 3-企微-自动回复 / 4-公众号推送 / 999-不限。
|
|
|
|
|
|
|
+ * type 取值: 0-自动回复(公众号入口) / 1-服务号推送 / 2-企微-社群 / 3-企微-自动回复 / 4-公众号推送 / 5-小程序投流 / 999-不限。
|
|
|
* 作用:解决 crowd_segment 跨渠道客户(如 gzyhc/wxm)在企微/公众号入口下被对侧数据污染的问题。
|
|
* 作用:解决 crowd_segment 跨渠道客户(如 gzyhc/wxm)在企微/公众号入口下被对侧数据污染的问题。
|
|
|
*/
|
|
*/
|
|
|
private String resolveChannelName(VideoContentListParam param) {
|
|
private String resolveChannelName(VideoContentListParam param) {
|
|
@@ -669,6 +670,7 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
if (type == 2 || type == 3) return CHANNEL_NAME_QW;
|
|
if (type == 2 || type == 3) return CHANNEL_NAME_QW;
|
|
|
if (type == 1 || type == 4) return CHANNEL_NAME_GZH_DAILY;
|
|
if (type == 1 || type == 4) return CHANNEL_NAME_GZH_DAILY;
|
|
|
if (type == 0) return CHANNEL_NAME_GZH;
|
|
if (type == 0) return CHANNEL_NAME_GZH;
|
|
|
|
|
+ if (type == 5) return CHANNEL_NAME_XCX;
|
|
|
}
|
|
}
|
|
|
if (StringUtils.hasText(param.getGhName())) return CHANNEL_NAME_GZH;
|
|
if (StringUtils.hasText(param.getGhName())) return CHANNEL_NAME_GZH;
|
|
|
return null;
|
|
return null;
|
|
@@ -980,17 +982,18 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
String ghName = StringUtils.hasText(param.getGhName()) ? param.getGhName() : null;
|
|
String ghName = StringUtils.hasText(param.getGhName()) ? param.getGhName() : null;
|
|
|
|
|
|
|
|
String category = StringUtils.hasText(param.getCategory()) ? param.getCategory() : null;
|
|
String category = StringUtils.hasText(param.getCategory()) ? param.getCategory() : null;
|
|
|
|
|
+ String crowdPackage = StringUtils.hasText(param.getCrowdPackage()) ? param.getCrowdPackage() : null;
|
|
|
// priorScene 池新识别:demand_strategy='人群需求' AND match_method='场景已看视频'(0519+ 起,旧 demand_strategy='人群需求-场景' 已迁走)
|
|
// priorScene 池新识别:demand_strategy='人群需求' AND match_method='场景已看视频'(0519+ 起,旧 demand_strategy='人群需求-场景' 已迁走)
|
|
|
List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
|
|
List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, null, null, null, ghName, null, category, MATCH_METHOD_PRIOR_SCENE, limit, false);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, null, null, null, ghName, null, category, MATCH_METHOD_PRIOR_SCENE, crowdPackage, limit, false);
|
|
|
if (ghName != null && rows.isEmpty()) {
|
|
if (ghName != null && rows.isEmpty()) {
|
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, null, null, null, null, null, category, MATCH_METHOD_PRIOR_SCENE, limit, false);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, null, null, null, null, null, category, MATCH_METHOD_PRIOR_SCENE, crowdPackage, limit, false);
|
|
|
}
|
|
}
|
|
|
// 跨渠道退化:channel_name 命中但 crowd_segment 在对侧渠道下 0 行(如公众号账号切到企微入口)→ 去 crowd_segment,只按 channel_name 拉通用数据
|
|
// 跨渠道退化:channel_name 命中但 crowd_segment 在对侧渠道下 0 行(如公众号账号切到企微入口)→ 去 crowd_segment,只按 channel_name 拉通用数据
|
|
|
if (channelName != null && rows.isEmpty()) {
|
|
if (channelName != null && rows.isEmpty()) {
|
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, channelName, null, DEMAND_STRATEGY_PRIOR, null, null, null, null, null, category, MATCH_METHOD_PRIOR_SCENE, limit, false);
|
|
|
|
|
|
|
+ dt, channelName, null, DEMAND_STRATEGY_PRIOR, null, null, null, null, null, category, MATCH_METHOD_PRIOR_SCENE, crowdPackage, limit, false);
|
|
|
}
|
|
}
|
|
|
// 1. 同 video_id 取 total_rov 最大的代表行(SQL 已排序,putIfAbsent 保留首次)
|
|
// 1. 同 video_id 取 total_rov 最大的代表行(SQL 已排序,putIfAbsent 保留首次)
|
|
|
LinkedHashMap<Long, ContentPlatformDemandVideo> bestPerVideo = new LinkedHashMap<>();
|
|
LinkedHashMap<Long, ContentPlatformDemandVideo> bestPerVideo = new LinkedHashMap<>();
|
|
@@ -1053,16 +1056,17 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
int fetchLimit = Math.max(limit * 3, DEMAND_CANDIDATE_LIMIT);
|
|
int fetchLimit = Math.max(limit * 3, DEMAND_CANDIDATE_LIMIT);
|
|
|
|
|
|
|
|
String category = StringUtils.hasText(param.getCategory()) ? param.getCategory() : null;
|
|
String category = StringUtils.hasText(param.getCategory()) ? param.getCategory() : null;
|
|
|
|
|
+ String crowdPackage = StringUtils.hasText(param.getCrowdPackage()) ? param.getCrowdPackage() : null;
|
|
|
List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
|
|
List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, dimension, null, null, ghName, null, category, MATCH_METHOD_PRIOR, fetchLimit, false);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, dimension, null, null, ghName, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, false);
|
|
|
|
|
|
|
|
if (ghName != null && rows.isEmpty()) {
|
|
if (ghName != null && rows.isEmpty()) {
|
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, dimension, null, null, null, null, category, MATCH_METHOD_PRIOR, fetchLimit, false);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, dimension, null, null, null, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, false);
|
|
|
}
|
|
}
|
|
|
if (channelName != null && rows.isEmpty()) {
|
|
if (channelName != null && rows.isEmpty()) {
|
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, channelName, null, DEMAND_STRATEGY_PRIOR, dimension, null, null, null, null, category, MATCH_METHOD_PRIOR, fetchLimit, false);
|
|
|
|
|
|
|
+ dt, channelName, null, DEMAND_STRATEGY_PRIOR, dimension, null, null, null, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, false);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
rows = rows.stream()
|
|
rows = rows.stream()
|
|
@@ -1131,20 +1135,21 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
int fetchLimit = Math.max(limit * 3, DEMAND_CANDIDATE_LIMIT);
|
|
int fetchLimit = Math.max(limit * 3, DEMAND_CANDIDATE_LIMIT);
|
|
|
|
|
|
|
|
String category = StringUtils.hasText(param.getCategory()) ? param.getCategory() : null;
|
|
String category = StringUtils.hasText(param.getCategory()) ? param.getCategory() : null;
|
|
|
|
|
+ String crowdPackage = StringUtils.hasText(param.getCrowdPackage()) ? param.getCrowdPackage() : null;
|
|
|
// posterior 池加 match_method='票圈推荐库' 兜底,防止未来上游对优质相似分量出别的 match_method 值后污染本池
|
|
// posterior 池加 match_method='票圈推荐库' 兜底,防止未来上游对优质相似分量出别的 match_method 值后污染本池
|
|
|
// 优质相似池:drive_dimension_time 一律不限制(含主查与退化路径),避免仅「昨日」窗口召回过少。
|
|
// 优质相似池:drive_dimension_time 一律不限制(含主查与退化路径),避免仅「昨日」窗口召回过少。
|
|
|
List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
|
|
List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, null, ghName, null, category, MATCH_METHOD_PRIOR, fetchLimit, true);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, null, ghName, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, true);
|
|
|
|
|
|
|
|
// 退化:该 ghName 无数据 → 退回渠道粒度
|
|
// 退化:该 ghName 无数据 → 退回渠道粒度
|
|
|
if (ghName != null && rows.isEmpty()) {
|
|
if (ghName != null && rows.isEmpty()) {
|
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, null, null, null, category, MATCH_METHOD_PRIOR, fetchLimit, true);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, null, null, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, true);
|
|
|
}
|
|
}
|
|
|
// 跨渠道退化:channel_name 命中但 crowd_segment 在对侧 0 行 → 去 crowd_segment 拉通用数据
|
|
// 跨渠道退化:channel_name 命中但 crowd_segment 在对侧 0 行 → 去 crowd_segment 拉通用数据
|
|
|
if (channelName != null && rows.isEmpty()) {
|
|
if (channelName != null && rows.isEmpty()) {
|
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, channelName, null, DEMAND_STRATEGY_POSTERIOR, null, null, null, null, null, category, MATCH_METHOD_PRIOR, fetchLimit, true);
|
|
|
|
|
|
|
+ dt, channelName, null, DEMAND_STRATEGY_POSTERIOR, null, null, null, null, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, true);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 近 7 日 rov 下限,与 prior 池一致(cdjh 0514 验证 ≥0.02 保留 ~54%)
|
|
// 近 7 日 rov 下限,与 prior 池一致(cdjh 0514 验证 ≥0.02 保留 ~54%)
|
|
@@ -2079,8 +2084,10 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
String rootSourceId = MessageUtil.getRootSourceId(pageUrl);
|
|
String rootSourceId = MessageUtil.getRootSourceId(pageUrl);
|
|
|
xcxPlan.setPageUrl(pageUrl);
|
|
xcxPlan.setPageUrl(pageUrl);
|
|
|
xcxPlan.setRootSourceId(rootSourceId);
|
|
xcxPlan.setRootSourceId(rootSourceId);
|
|
|
|
|
+ xcxPlan.setStatus(PlanStatusEnum.NORMAL.getVal());
|
|
|
xcxPlan.setCreateAccountId(loginUser.getId());
|
|
xcxPlan.setCreateAccountId(loginUser.getId());
|
|
|
xcxPlan.setCreateTimestamp(now);
|
|
xcxPlan.setCreateTimestamp(now);
|
|
|
|
|
+ xcxPlan.setUpdateTimestamp(now);
|
|
|
planMapperExt.insertXcxPlanReturnId(xcxPlan);
|
|
planMapperExt.insertXcxPlanReturnId(xcxPlan);
|
|
|
list.add(xcxPlan);
|
|
list.add(xcxPlan);
|
|
|
// 保存视频内容
|
|
// 保存视频内容
|
|
@@ -2091,8 +2098,12 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void xcxPlanDelete(Long id) {
|
|
public void xcxPlanDelete(Long id) {
|
|
|
|
|
+ ContentPlatformAccount loginUser = LoginUserContext.getUser();
|
|
|
|
|
+ if (!Objects.equals(loginUser.getType(), 2)) {
|
|
|
|
|
+ throw new CommonException(ExceptionEnum.XCX_PLAN_INTERNAL_ONLY);
|
|
|
|
|
+ }
|
|
|
ContentPlatformXcxPlan plan = xcxPlanMapper.selectByPrimaryKey(id);
|
|
ContentPlatformXcxPlan plan = xcxPlanMapper.selectByPrimaryKey(id);
|
|
|
- if (Objects.isNull(plan)) {
|
|
|
|
|
|
|
+ if (Objects.isNull(plan) || !Objects.equals(plan.getCreateAccountId(), loginUser.getId())) {
|
|
|
throw new CommonException(ExceptionEnum.XCX_PLAN_NOT_EXISTS);
|
|
throw new CommonException(ExceptionEnum.XCX_PLAN_NOT_EXISTS);
|
|
|
}
|
|
}
|
|
|
plan.setStatus(PlanStatusEnum.DELETED.getVal());
|
|
plan.setStatus(PlanStatusEnum.DELETED.getVal());
|
|
@@ -2100,6 +2111,15 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
xcxPlanMapper.updateByPrimaryKeySelective(plan);
|
|
xcxPlanMapper.updateByPrimaryKeySelective(plan);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public List<String> getXcxAudiencePackageList() {
|
|
|
|
|
+ String dt = demandVideoMapperExt.getMaxDt(CHANNEL_NAME_XCX);
|
|
|
|
|
+ if (!StringUtils.hasText(dt)) {
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+ return demandVideoMapperExt.selectDistinctCrowdPackages(dt, CHANNEL_NAME_XCX);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private List<XcxPlanItemVO> buildXcxPlanItemVOList(List<ContentPlatformXcxPlan> planList) {
|
|
private List<XcxPlanItemVO> buildXcxPlanItemVOList(List<ContentPlatformXcxPlan> planList) {
|
|
|
if (CollectionUtils.isEmpty(planList)) {
|
|
if (CollectionUtils.isEmpty(planList)) {
|
|
|
return null;
|
|
return null;
|