|
|
@@ -25,6 +25,7 @@ import com.tzld.piaoquan.api.model.vo.contentplatform.GzhPlanVideoContentItemVO;
|
|
|
import com.tzld.piaoquan.api.model.vo.contentplatform.QwPlanItemExportVO;
|
|
|
import com.tzld.piaoquan.api.model.vo.contentplatform.QwPlanItemVO;
|
|
|
import com.tzld.piaoquan.api.model.vo.contentplatform.VideoContentItemVO;
|
|
|
+import com.tzld.piaoquan.api.model.vo.contentplatform.XcxPlanItemExportVO;
|
|
|
import com.tzld.piaoquan.api.model.vo.contentplatform.XcxPlanItemVO;
|
|
|
import com.tzld.piaoquan.api.service.CgiReplyService;
|
|
|
import com.tzld.piaoquan.api.service.GhDetailService;
|
|
|
@@ -57,6 +58,7 @@ import org.springframework.stereotype.Service;
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
import java.time.LocalDate;
|
|
|
+import java.time.ZoneId;
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
import java.util.*;
|
|
|
@@ -575,8 +577,8 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
private void updateGhDetail(ContentPlatformGzhAccount account, Integer selectVideoType, List<Long> videoIds,
|
|
|
Map<Long, String> videoIdTestIdMap) {
|
|
|
ContentPlatformAccount loginUser = LoginUserContext.getUser();
|
|
|
- // 根据 content_platform_account 的 type 判断公众号类型:type=2 内部账号 -> 内部公众号,否则 -> 外部公众号
|
|
|
- Integer ghType = Objects.equals(loginUser.getType(), 2) ? GhTypeEnum.GH.type : GhTypeEnum.THIRD_PARTY_GH.type;
|
|
|
+ // 根据 content_platform_account 的 type 判断公众号类型:内部账号 -> 内部公众号,否则 -> 外部公众号
|
|
|
+ Integer ghType = Objects.equals(loginUser.getType(), ContentPlatformAccountTypeEnum.INTERNAL.getVal()) ? GhTypeEnum.GH.type : GhTypeEnum.THIRD_PARTY_GH.type;
|
|
|
GhDetail ghDetail = ghDetailService.getGhDetailByGhIdType(account.getGhId(), ghType);
|
|
|
GhDetailVo detailVo = new GhDetailVo();
|
|
|
Integer strategyStatus = selectVideoType == 0 ? StrategyStatusEnum.DEFAULT.status : StrategyStatusEnum.STRATEGY.status;
|
|
|
@@ -646,6 +648,7 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
/** 服务号推送 / 公众号推送 走 Daily 人群_渠道,与即转稳定数据隔离 */
|
|
|
private static final String CHANNEL_NAME_GZH_DAILY = "公众号合作-Daily-自选";
|
|
|
private static final String CHANNEL_NAME_QW = "群/企微合作-稳定";
|
|
|
+ private static final String CHANNEL_NAME_XCX = "小程序投流-稳定";
|
|
|
private static final double PRIOR_GROUP_KEEP_RATIO = 0.5;
|
|
|
/** posterior 按 demand_content_id 分组后保留 total_rov 排名前 50% 的需求组,
|
|
|
* 砍掉群体表现弱的需求,避免低 total_rov 的 demand 带回来的相似变体稀释结果。 */
|
|
|
@@ -657,10 +660,10 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
/**
|
|
|
* 推导 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(公众号参数)→ 公众号入口,映射即转稳定(与历史一致)
|
|
|
* 3. 否则 null,不限 channel_name(保留原行为)
|
|
|
- * type 取值: 0-自动回复(公众号入口) / 1-服务号推送 / 2-企微-社群 / 3-企微-自动回复 / 4-公众号推送 / 999-不限。
|
|
|
+ * type 取值: 0-自动回复(公众号入口) / 1-服务号推送 / 2-企微-社群 / 3-企微-自动回复 / 4-公众号推送 / 5-小程序投流 / 999-不限。
|
|
|
* 作用:解决 crowd_segment 跨渠道客户(如 gzyhc/wxm)在企微/公众号入口下被对侧数据污染的问题。
|
|
|
*/
|
|
|
private String resolveChannelName(VideoContentListParam param) {
|
|
|
@@ -669,6 +672,7 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
if (type == 2 || type == 3) return CHANNEL_NAME_QW;
|
|
|
if (type == 1 || type == 4) return CHANNEL_NAME_GZH_DAILY;
|
|
|
if (type == 0) return CHANNEL_NAME_GZH;
|
|
|
+ if (type == 5) return CHANNEL_NAME_XCX;
|
|
|
}
|
|
|
if (StringUtils.hasText(param.getGhName())) return CHANNEL_NAME_GZH;
|
|
|
return null;
|
|
|
@@ -980,17 +984,18 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
String ghName = StringUtils.hasText(param.getGhName()) ? param.getGhName() : 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='人群需求-场景' 已迁走)
|
|
|
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()) {
|
|
|
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 拉通用数据
|
|
|
if (channelName != null && rows.isEmpty()) {
|
|
|
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 保留首次)
|
|
|
LinkedHashMap<Long, ContentPlatformDemandVideo> bestPerVideo = new LinkedHashMap<>();
|
|
|
@@ -1053,16 +1058,17 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
int fetchLimit = Math.max(limit * 3, DEMAND_CANDIDATE_LIMIT);
|
|
|
|
|
|
String category = StringUtils.hasText(param.getCategory()) ? param.getCategory() : null;
|
|
|
+ String crowdPackage = StringUtils.hasText(param.getCrowdPackage()) ? param.getCrowdPackage() : null;
|
|
|
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()) {
|
|
|
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()) {
|
|
|
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()
|
|
|
@@ -1131,20 +1137,21 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
int fetchLimit = Math.max(limit * 3, DEMAND_CANDIDATE_LIMIT);
|
|
|
|
|
|
String category = StringUtils.hasText(param.getCategory()) ? param.getCategory() : null;
|
|
|
+ String crowdPackage = StringUtils.hasText(param.getCrowdPackage()) ? param.getCrowdPackage() : null;
|
|
|
// posterior 池加 match_method='视频库_解构特征_向量相似匹配' 兜底,防止未来上游对优质相似分量出别的 match_method 值后污染本池
|
|
|
// 优质相似池:drive_dimension_time 一律不限制(含主查与退化路径),避免仅「昨日」窗口召回过少。
|
|
|
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 无数据 → 退回渠道粒度
|
|
|
if (ghName != null && rows.isEmpty()) {
|
|
|
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 拉通用数据
|
|
|
if (channelName != null && rows.isEmpty()) {
|
|
|
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%)
|
|
|
@@ -2058,10 +2065,62 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 小程序投流计划导出:复用 xcxPlanList 的 filter(audiencePackage/title/时间范围),
|
|
|
+ * 不传时间范围时默认仅导出当天数据,最多导出 2000 条。
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public String xcxPlanExport(XcxPlanListParam param) {
|
|
|
+ // 未传时间窗口时,默认仅导出当天数据(本地时区 00:00 ~ 次日 00:00)
|
|
|
+ if (param.getCreateTimestampStart() == null && param.getCreateTimestampEnd() == null) {
|
|
|
+ ZoneId zone = ZoneId.systemDefault();
|
|
|
+ long startOfToday = LocalDate.now().atStartOfDay(zone).toInstant().toEpochMilli();
|
|
|
+ long startOfTomorrow = LocalDate.now().plusDays(1).atStartOfDay(zone).toInstant().toEpochMilli();
|
|
|
+ param.setCreateTimestampStart(startOfToday);
|
|
|
+ param.setCreateTimestampEnd(startOfTomorrow);
|
|
|
+ }
|
|
|
+ // 强制分页参数:最多导出 2000 条
|
|
|
+ param.setPageNum(1);
|
|
|
+ param.setPageSize(2000);
|
|
|
+
|
|
|
+ ContentPlatformAccount loginAccount = LoginUserContext.getUser();
|
|
|
+ List<ContentPlatformXcxPlan> planList = planMapperExt.getXcxPlanList(param,
|
|
|
+ loginAccount.getId(), 0, param.getPageSize());
|
|
|
+ List<XcxPlanItemVO> list = buildXcxPlanItemVOList(planList);
|
|
|
+ return generateXcxPlanExcelFile(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String generateXcxPlanExcelFile(List<XcxPlanItemVO> dataList) {
|
|
|
+ List<XcxPlanItemExportVO> list = new ArrayList<>();
|
|
|
+ if (CollectionUtils.isNotEmpty(dataList)) {
|
|
|
+ for (XcxPlanItemVO data : dataList) {
|
|
|
+ XcxPlanItemExportVO vo = new XcxPlanItemExportVO();
|
|
|
+ vo.setAudiencePackage(data.getAudiencePackage());
|
|
|
+ vo.setTitle(data.getTitle());
|
|
|
+ vo.setCover(data.getShareCover() != null ? data.getShareCover() : data.getCover());
|
|
|
+ vo.setPageUrl(data.getPageUrl());
|
|
|
+ vo.setRemark(data.getRemark());
|
|
|
+ if (Objects.nonNull(data.getCreateTimestamp())) {
|
|
|
+ vo.setCreateTime(DateUtil.getDateString(data.getCreateTimestamp(), "yyyy-MM-dd HH:mm:ss"));
|
|
|
+ }
|
|
|
+ list.add(vo);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ list.add(new XcxPlanItemExportVO());
|
|
|
+ }
|
|
|
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
|
+ EasyExcel.write(out, XcxPlanItemExportVO.class).sheet("小程序投流计划").doWrite(list);
|
|
|
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(out.toByteArray());
|
|
|
+ String fileName = "小程序投流计划_" + System.currentTimeMillis() + ".xls";
|
|
|
+ AliOssFileTool.saveInPublicReturnHost(byteArrayInputStream, EnumPublicBuckets.PUBBUCKET, fileName, EnumFileType.TEMP_PICTURE);
|
|
|
+ return CdnUtil.DOWNLOAD_CDN_URL_HOST_PICTURE + fileName;
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public List<XcxPlanItemVO> xcxPlanSave(XcxPlanSaveParam param) {
|
|
|
ContentPlatformAccount loginUser = LoginUserContext.getUser();
|
|
|
- if (!Objects.equals(loginUser.getType(), 2)) {
|
|
|
+ if (!Objects.equals(loginUser.getType(), ContentPlatformAccountTypeEnum.INTERNAL.getVal())
|
|
|
+ && !Objects.equals(loginUser.getType(), ContentPlatformAccountTypeEnum.AGENT.getVal())) {
|
|
|
throw new CommonException(ExceptionEnum.XCX_PLAN_INTERNAL_ONLY);
|
|
|
}
|
|
|
Long now = System.currentTimeMillis();
|
|
|
@@ -2079,8 +2138,10 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
String rootSourceId = MessageUtil.getRootSourceId(pageUrl);
|
|
|
xcxPlan.setPageUrl(pageUrl);
|
|
|
xcxPlan.setRootSourceId(rootSourceId);
|
|
|
+ xcxPlan.setStatus(PlanStatusEnum.NORMAL.getVal());
|
|
|
xcxPlan.setCreateAccountId(loginUser.getId());
|
|
|
xcxPlan.setCreateTimestamp(now);
|
|
|
+ xcxPlan.setUpdateTimestamp(now);
|
|
|
planMapperExt.insertXcxPlanReturnId(xcxPlan);
|
|
|
list.add(xcxPlan);
|
|
|
// 保存视频内容
|
|
|
@@ -2091,8 +2152,13 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
|
|
|
@Override
|
|
|
public void xcxPlanDelete(Long id) {
|
|
|
+ ContentPlatformAccount loginUser = LoginUserContext.getUser();
|
|
|
+ if (!Objects.equals(loginUser.getType(), ContentPlatformAccountTypeEnum.INTERNAL.getVal())
|
|
|
+ && !Objects.equals(loginUser.getType(), ContentPlatformAccountTypeEnum.AGENT.getVal())) {
|
|
|
+ throw new CommonException(ExceptionEnum.XCX_PLAN_INTERNAL_ONLY);
|
|
|
+ }
|
|
|
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);
|
|
|
}
|
|
|
plan.setStatus(PlanStatusEnum.DELETED.getVal());
|
|
|
@@ -2100,6 +2166,94 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
xcxPlanMapper.updateByPrimaryKeySelective(plan);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public List<XcxPlanItemVO> xcxPlanMultiLink(XcxPlanMultiLinkParam param) {
|
|
|
+ ContentPlatformAccount loginUser = LoginUserContext.getUser();
|
|
|
+ if (!Objects.equals(loginUser.getType(), ContentPlatformAccountTypeEnum.INTERNAL.getVal())
|
|
|
+ && !Objects.equals(loginUser.getType(), ContentPlatformAccountTypeEnum.AGENT.getVal())) {
|
|
|
+ throw new CommonException(ExceptionEnum.XCX_PLAN_INTERNAL_ONLY);
|
|
|
+ }
|
|
|
+ if (Objects.isNull(param.getPlanId()) || Objects.isNull(param.getCount())
|
|
|
+ || param.getCount() < 1 || param.getCount() > 200) {
|
|
|
+ throw new CommonException(ExceptionEnum.PARAM_ERROR);
|
|
|
+ }
|
|
|
+ ContentPlatformXcxPlan src = xcxPlanMapper.selectByPrimaryKey(param.getPlanId());
|
|
|
+ if (Objects.isNull(src) || !Objects.equals(src.getCreateAccountId(), loginUser.getId())
|
|
|
+ || !Objects.equals(src.getStatus(), PlanStatusEnum.NORMAL.getVal())) {
|
|
|
+ throw new CommonException(ExceptionEnum.XCX_PLAN_NOT_EXISTS);
|
|
|
+ }
|
|
|
+ ContentPlatformXcxPlanVideoExample videoExample = new ContentPlatformXcxPlanVideoExample();
|
|
|
+ videoExample.createCriteria().andPlanIdEqualTo(src.getId());
|
|
|
+ List<ContentPlatformXcxPlanVideo> srcVideoList = xcxPlanVideoMapper.selectByExample(videoExample);
|
|
|
+ if (CollectionUtils.isEmpty(srcVideoList)) {
|
|
|
+ throw new CommonException(ExceptionEnum.XCX_PLAN_NOT_EXISTS);
|
|
|
+ }
|
|
|
+ ContentPlatformXcxPlanVideo srcVideo = srcVideoList.get(0);
|
|
|
+
|
|
|
+ Long now = System.currentTimeMillis();
|
|
|
+ List<ContentPlatformXcxPlan> created = new ArrayList<>();
|
|
|
+ try {
|
|
|
+ for (int i = 0; i < param.getCount(); i++) {
|
|
|
+ ContentPlatformXcxPlan xcxPlan = new ContentPlatformXcxPlan();
|
|
|
+ xcxPlan.setAudiencePackage(src.getAudiencePackage());
|
|
|
+ xcxPlan.setRemark(src.getRemark());
|
|
|
+ Staff staff = new Staff();
|
|
|
+ staff.setCarrierId("wxf7261ed54f2e450e");
|
|
|
+ staff.setRemark(src.getRemark());
|
|
|
+ String pageUrl = messageAttachmentService.getPageNoCache("pages/category", "touliu", "tencent", staff,
|
|
|
+ srcVideo.getVideoId(), "小程序", null, null, srcVideo.getExperimentId());
|
|
|
+ String rootSourceId = MessageUtil.getRootSourceId(pageUrl);
|
|
|
+ xcxPlan.setPageUrl(pageUrl);
|
|
|
+ xcxPlan.setRootSourceId(rootSourceId);
|
|
|
+ xcxPlan.setStatus(PlanStatusEnum.NORMAL.getVal());
|
|
|
+ xcxPlan.setCreateAccountId(loginUser.getId());
|
|
|
+ xcxPlan.setCreateTimestamp(now);
|
|
|
+ xcxPlan.setUpdateTimestamp(now);
|
|
|
+ planMapperExt.insertXcxPlanReturnId(xcxPlan);
|
|
|
+ created.add(xcxPlan);
|
|
|
+
|
|
|
+ XcxPlanSaveVideoParam vp = new XcxPlanSaveVideoParam();
|
|
|
+ vp.setVideoId(srcVideo.getVideoId());
|
|
|
+ vp.setTitle(srcVideo.getTitle());
|
|
|
+ vp.setCover(srcVideo.getCover());
|
|
|
+ vp.setVideo(srcVideo.getVideo());
|
|
|
+ vp.setExperimentId(srcVideo.getExperimentId());
|
|
|
+ saveXcxPlanVideo(vp, xcxPlan.getId(), loginUser.getId());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("xcxPlanMultiLink failed at {}/{} for planId={}, rolling back {} created plans",
|
|
|
+ created.size(), param.getCount(), param.getPlanId(), created.size(), e);
|
|
|
+ rollbackXcxPlans(created);
|
|
|
+ throw new CommonException(ExceptionEnum.SYSTEM_ERROR);
|
|
|
+ }
|
|
|
+ return buildXcxPlanItemVOList(created);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void rollbackXcxPlans(List<ContentPlatformXcxPlan> created) {
|
|
|
+ if (CollectionUtils.isEmpty(created)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Long now = System.currentTimeMillis();
|
|
|
+ for (ContentPlatformXcxPlan plan : created) {
|
|
|
+ try {
|
|
|
+ plan.setStatus(PlanStatusEnum.DELETED.getVal());
|
|
|
+ plan.setUpdateTimestamp(now);
|
|
|
+ xcxPlanMapper.updateByPrimaryKeySelective(plan);
|
|
|
+ } catch (Exception ex) {
|
|
|
+ log.error("xcxPlanMultiLink rollback failed for planId={}", plan.getId(), ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @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) {
|
|
|
if (CollectionUtils.isEmpty(planList)) {
|
|
|
return null;
|