|
@@ -615,6 +615,9 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
private static final String DEMAND_STRATEGY_PRIOR_SCENE = "人群需求-场景";
|
|
private static final String DEMAND_STRATEGY_PRIOR_SCENE = "人群需求-场景";
|
|
|
private static final String DEMAND_STRATEGY_POSTERIOR = "优质相似";
|
|
private static final String DEMAND_STRATEGY_POSTERIOR = "优质相似";
|
|
|
private static final String PRIOR_PREMIUM_DIMENSION = "传播的头部";
|
|
private static final String PRIOR_PREMIUM_DIMENSION = "传播的头部";
|
|
|
|
|
+ /** type → channel_name 映射(强过滤):同 crowd_segment 跨渠道客户(如 gzyhc/wxm)按入口平台切数据源 */
|
|
|
|
|
+ private static final String CHANNEL_NAME_GZH = "公众号合作-即转-稳定";
|
|
|
|
|
+ private static final String CHANNEL_NAME_QW = "群/企微合作-稳定";
|
|
|
private static final double PRIOR_GROUP_KEEP_RATIO = 0.5;
|
|
private static final double PRIOR_GROUP_KEEP_RATIO = 0.5;
|
|
|
private static final String POSTERIOR_FILTER_ABS_LIKE = "绝对高效率%";
|
|
private static final String POSTERIOR_FILTER_ABS_LIKE = "绝对高效率%";
|
|
|
private static final String POSTERIOR_FILTER_REL_LIKE = "相对裂变率%";
|
|
private static final String POSTERIOR_FILTER_REL_LIKE = "相对裂变率%";
|
|
@@ -623,6 +626,25 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
private static final String SOURCE_POSTERIOR = "posterior";
|
|
private static final String SOURCE_POSTERIOR = "posterior";
|
|
|
private static final String SOURCE_HOT = "hot";
|
|
private static final String SOURCE_HOT = "hot";
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 推导 channel_name(人群_渠道) 作为 demand 池强过滤。
|
|
|
|
|
+ * 信号优先级:
|
|
|
|
|
+ * 1. type 明确时按 type 映射 — 0/1/4 → 公众号合作-即转-稳定;2/3 → 群/企微合作-稳定
|
|
|
|
|
+ * 2. type=999/null 但带 ghName(公众号参数)→ 公众号入口,映射公众号
|
|
|
|
|
+ * 3. 否则 null,不限 channel_name(保留原行为)
|
|
|
|
|
+ * type 取值: 0-自动回复(公众号入口) / 1-服务号推送 / 2-企微-社群 / 3-企微-自动回复 / 4-公众号推送 / 999-不限。
|
|
|
|
|
+ * 作用:解决 crowd_segment 跨渠道客户(如 gzyhc/wxm)在企微/公众号入口下被对侧数据污染的问题。
|
|
|
|
|
+ */
|
|
|
|
|
+ private String resolveChannelName(VideoContentListParam param) {
|
|
|
|
|
+ Integer type = param.getType();
|
|
|
|
|
+ if (type != null) {
|
|
|
|
|
+ if (type == 2 || type == 3) return CHANNEL_NAME_QW;
|
|
|
|
|
+ if (type == 0 || type == 1 || type == 4) return CHANNEL_NAME_GZH;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.hasText(param.getGhName())) return CHANNEL_NAME_GZH;
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
public Page<VideoContentItemVO> getVideoContentList(VideoContentListParam param) {
|
|
public Page<VideoContentItemVO> getVideoContentList(VideoContentListParam param) {
|
|
|
ContentPlatformAccount user = LoginUserContext.getUser();
|
|
ContentPlatformAccount user = LoginUserContext.getUser();
|
|
@@ -841,12 +863,13 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
}
|
|
}
|
|
|
String crowdSegment = user.getChannel();
|
|
String crowdSegment = user.getChannel();
|
|
|
String ghName = StringUtils.hasText(param.getGhName()) ? param.getGhName() : null;
|
|
String ghName = StringUtils.hasText(param.getGhName()) ? param.getGhName() : null;
|
|
|
|
|
+ String channelName = resolveChannelName(param);
|
|
|
|
|
|
|
|
List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
|
|
List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, crowdSegment, DEMAND_STRATEGY_PRIOR_SCENE, null, null, null, ghName, null, limit, false);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR_SCENE, null, null, null, ghName, null, limit, false);
|
|
|
if (ghName != null && rows.isEmpty()) {
|
|
if (ghName != null && rows.isEmpty()) {
|
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, crowdSegment, DEMAND_STRATEGY_PRIOR_SCENE, null, null, null, null, null, limit, false);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR_SCENE, null, null, null, null, null, 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<>();
|
|
@@ -888,15 +911,16 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
}
|
|
}
|
|
|
String crowdSegment = user.getChannel();
|
|
String crowdSegment = user.getChannel();
|
|
|
String ghName = StringUtils.hasText(param.getGhName()) ? param.getGhName() : null;
|
|
String ghName = StringUtils.hasText(param.getGhName()) ? param.getGhName() : null;
|
|
|
|
|
+ String channelName = resolveChannelName(param);
|
|
|
int fetchLimit = Math.max(limit * 3, DEMAND_CANDIDATE_LIMIT);
|
|
int fetchLimit = Math.max(limit * 3, DEMAND_CANDIDATE_LIMIT);
|
|
|
|
|
|
|
|
List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
|
|
List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, crowdSegment, DEMAND_STRATEGY_PRIOR, PRIOR_PREMIUM_DIMENSION, null, null, ghName, null, fetchLimit, false);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, PRIOR_PREMIUM_DIMENSION, null, null, ghName, null, fetchLimit, false);
|
|
|
|
|
|
|
|
// 退化:该 ghName 无数据 → 退回渠道粒度
|
|
// 退化:该 ghName 无数据 → 退回渠道粒度
|
|
|
if (ghName != null && rows.isEmpty()) {
|
|
if (ghName != null && rows.isEmpty()) {
|
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
rows = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, crowdSegment, DEMAND_STRATEGY_PRIOR, PRIOR_PREMIUM_DIMENSION, null, null, null, null, fetchLimit, false);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, PRIOR_PREMIUM_DIMENSION, null, null, null, null, fetchLimit, false);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Function<ContentPlatformDemandVideo, String> keyFn = r ->
|
|
Function<ContentPlatformDemandVideo, String> keyFn = r ->
|
|
@@ -956,19 +980,20 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
}
|
|
}
|
|
|
String crowdSegment = user.getChannel();
|
|
String crowdSegment = user.getChannel();
|
|
|
String ghName = StringUtils.hasText(param.getGhName()) ? param.getGhName() : null;
|
|
String ghName = StringUtils.hasText(param.getGhName()) ? param.getGhName() : null;
|
|
|
|
|
+ String channelName = resolveChannelName(param);
|
|
|
int fetchLimit = Math.max(limit * 3, DEMAND_CANDIDATE_LIMIT);
|
|
int fetchLimit = Math.max(limit * 3, DEMAND_CANDIDATE_LIMIT);
|
|
|
|
|
|
|
|
List<ContentPlatformDemandVideo> stageAbs = demandVideoMapperExt.selectForRecommend(
|
|
List<ContentPlatformDemandVideo> stageAbs = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_ABS_LIKE, ghName, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_ABS_LIKE, ghName, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
|
|
|
List<ContentPlatformDemandVideo> stageRel = demandVideoMapperExt.selectForRecommend(
|
|
List<ContentPlatformDemandVideo> stageRel = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_REL_LIKE, ghName, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_REL_LIKE, ghName, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
|
|
|
|
|
|
|
|
// 退化:该 ghName 在两阶段都无数据 → 退回渠道粒度(drive_dimension_time 仍严格为"昨日")
|
|
// 退化:该 ghName 在两阶段都无数据 → 退回渠道粒度(drive_dimension_time 仍严格为"昨日")
|
|
|
if (ghName != null && stageAbs.isEmpty() && stageRel.isEmpty()) {
|
|
if (ghName != null && stageAbs.isEmpty() && stageRel.isEmpty()) {
|
|
|
stageAbs = demandVideoMapperExt.selectForRecommend(
|
|
stageAbs = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_ABS_LIKE, null, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_ABS_LIKE, null, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
|
|
|
stageRel = demandVideoMapperExt.selectForRecommend(
|
|
stageRel = demandVideoMapperExt.selectForRecommend(
|
|
|
- dt, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_REL_LIKE, null, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
|
|
|
|
|
|
|
+ dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_REL_LIKE, null, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Function<ContentPlatformDemandVideo, String> keyFn = r ->
|
|
Function<ContentPlatformDemandVideo, String> keyFn = r ->
|