|
@@ -165,7 +165,7 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
dto = new MarketEmailsDTO();
|
|
dto = new MarketEmailsDTO();
|
|
|
}
|
|
}
|
|
|
// 打开邮件的客户 = hasReader=1 且 recipient 不为空
|
|
// 打开邮件的客户 = hasReader=1 且 recipient 不为空
|
|
|
- // 策略:单活动下打开邮件的邮件数通常几百~几千,先查全集在内存里按 recipient 分组 + 分页
|
|
|
|
|
|
|
+ // 字段都可直接从 market_emails 查出,无需聚合,直接 DB 分页
|
|
|
LambdaQueryWrapper<MarketEmailsEntity> wrapper = new LambdaQueryWrapper<>();
|
|
LambdaQueryWrapper<MarketEmailsEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
wrapper.eq(MarketEmailsEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
|
|
|
wrapper.eq(MarketEmailsEntity::getHasReader, 1);
|
|
wrapper.eq(MarketEmailsEntity::getHasReader, 1);
|
|
@@ -177,98 +177,56 @@ public class MarketEmailsServiceImpl extends MyBaseServiceImpl<MarketEmailsMappe
|
|
|
}
|
|
}
|
|
|
wrapper.isNotNull(MarketEmailsEntity::getRecipient);
|
|
wrapper.isNotNull(MarketEmailsEntity::getRecipient);
|
|
|
wrapper.ne(MarketEmailsEntity::getRecipient, "");
|
|
wrapper.ne(MarketEmailsEntity::getRecipient, "");
|
|
|
- // 只查需要的列,减少数据传输
|
|
|
|
|
-// wrapper.select(MarketEmailsEntity::getRecipient,
|
|
|
|
|
-// MarketEmailsEntity::getId,
|
|
|
|
|
-// MarketEmailsEntity::getCustomerId,
|
|
|
|
|
-// MarketEmailsEntity::getFirstOpenTime,
|
|
|
|
|
-// MarketEmailsEntity::getHasProtect,
|
|
|
|
|
-// MarketEmailsEntity::getHasSuspend);
|
|
|
|
|
- List<MarketEmailsEntity> all = this.list(wrapper);
|
|
|
|
|
- // 按 recipient 聚合
|
|
|
|
|
- Map<String, MarketEmailsOpenVO> aggMap = new HashMap<>();
|
|
|
|
|
- if (!CollectionUtils.isEmpty(all)) {
|
|
|
|
|
- for (MarketEmailsEntity e : all) {
|
|
|
|
|
- String r = e.getRecipient();
|
|
|
|
|
- if (r == null || r.isEmpty()) {
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- MarketEmailsOpenVO vo = aggMap.computeIfAbsent(r, k -> {
|
|
|
|
|
- MarketEmailsOpenVO v = new MarketEmailsOpenVO();
|
|
|
|
|
- v.setRecipient(k);
|
|
|
|
|
- v.setClickCount(0L);
|
|
|
|
|
- v.setId(e.getId());
|
|
|
|
|
- v.setOpenCount(e.getOpenCount());
|
|
|
|
|
- return v;
|
|
|
|
|
- });
|
|
|
|
|
- vo.setClickCount(vo.getClickCount() + 1);
|
|
|
|
|
- // 取最早首次打开时间,同时记下该条记录所属的 customerId
|
|
|
|
|
- if (e.getFirstOpenTime() != null) {
|
|
|
|
|
- if (vo.getFirstOpenTime() == null || e.getFirstOpenTime().before(vo.getFirstOpenTime())) {
|
|
|
|
|
- vo.setFirstOpenTime(e.getFirstOpenTime());
|
|
|
|
|
- vo.setCustomerId(e.getCustomerId());
|
|
|
|
|
- vo.setId(e.getId());
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- // MAX(has_protect) / MAX(has_suspend) 语义
|
|
|
|
|
- if (e.getHasProtect() != null && e.getHasProtect() == 1) {
|
|
|
|
|
- vo.setHasProtect(1);
|
|
|
|
|
- }
|
|
|
|
|
- if (e.getHasSuspend() != null && e.getHasSuspend() == 1) {
|
|
|
|
|
- vo.setHasSuspend(1);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // DB 层直接分页 + 按首次打开时间倒序
|
|
|
|
|
+ wrapper.orderByDesc(MarketEmailsEntity::getFirstOpenTime);
|
|
|
|
|
+ Page<MarketEmailsEntity> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
|
|
|
|
|
+ IPage<MarketEmailsEntity> entityPage = this.page(page, wrapper);
|
|
|
|
|
+
|
|
|
|
|
+ // 实体 → VO(字段直接映射,openCount 来自 entity.openCount,无需 clickCount)
|
|
|
|
|
+ List<MarketEmailsOpenVO> voList = entityPage.getRecords().stream().map(e -> {
|
|
|
|
|
+ MarketEmailsOpenVO vo = new MarketEmailsOpenVO();
|
|
|
|
|
+ vo.setRecipient(e.getRecipient());
|
|
|
|
|
+ vo.setId(e.getId());
|
|
|
|
|
+ vo.setCustomerId(e.getCustomerId());
|
|
|
|
|
+ vo.setOpenCount(e.getOpenCount());
|
|
|
|
|
+ vo.setFirstOpenTime(e.getFirstOpenTime());
|
|
|
|
|
+ vo.setHasProtect(e.getHasProtect());
|
|
|
|
|
+ vo.setHasSuspend(e.getHasSuspend());
|
|
|
|
|
+ return vo;
|
|
|
|
|
+ }).collect(Collectors.toList());
|
|
|
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- // 按首次打开时间倒序
|
|
|
|
|
- List<MarketEmailsOpenVO> sorted = new ArrayList<>(aggMap.values());
|
|
|
|
|
- sorted.sort((a, b) -> {
|
|
|
|
|
- if (a.getFirstOpenTime() == null && b.getFirstOpenTime() == null) return 0;
|
|
|
|
|
- if (a.getFirstOpenTime() == null) return 1;
|
|
|
|
|
- if (b.getFirstOpenTime() == null) return -1;
|
|
|
|
|
- return b.getFirstOpenTime().compareTo(a.getFirstOpenTime());
|
|
|
|
|
- });
|
|
|
|
|
- // 内存分页
|
|
|
|
|
- long pageIndex = dto.getPageIndex() != null && dto.getPageIndex() > 0 ? dto.getPageIndex() : 1L;
|
|
|
|
|
- long pageSize = dto.getPageSize() != null && dto.getPageSize() > 0 ? dto.getPageSize() : 50L;
|
|
|
|
|
- long total = sorted.size();
|
|
|
|
|
- long from = Math.min((pageIndex - 1) * pageSize, total);
|
|
|
|
|
- long to = Math.min(from + pageSize, total);
|
|
|
|
|
- List<MarketEmailsOpenVO> pageList = sorted.subList((int) from, (int) to);
|
|
|
|
|
- IPage<MarketEmailsOpenVO> page =
|
|
|
|
|
- new Page<>(pageIndex, pageSize, total);
|
|
|
|
|
- page.setRecords(pageList);
|
|
|
|
|
// 回填客户名称(批量查 customer 表)
|
|
// 回填客户名称(批量查 customer 表)
|
|
|
- if (pageList != null && !pageList.isEmpty()) {
|
|
|
|
|
- Set<Long> customerIdSet = new LinkedHashSet<>();
|
|
|
|
|
- for (MarketEmailsOpenVO v : pageList) {
|
|
|
|
|
- if (v.getCustomerId() != null) {
|
|
|
|
|
- customerIdSet.add(v.getCustomerId());
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ Set<Long> customerIdSet = new LinkedHashSet<>();
|
|
|
|
|
+ for (MarketEmailsOpenVO v : voList) {
|
|
|
|
|
+ if (v.getCustomerId() != null) {
|
|
|
|
|
+ customerIdSet.add(v.getCustomerId());
|
|
|
}
|
|
}
|
|
|
- if (!customerIdSet.isEmpty()) {
|
|
|
|
|
- try {
|
|
|
|
|
- List<CustomerEntity> customers =
|
|
|
|
|
- customerTradeService.listByIds(new ArrayList<>(customerIdSet));
|
|
|
|
|
- if (!CollectionUtils.isEmpty(customers)) {
|
|
|
|
|
- Map<Long, String> idToName = new HashMap<>(customers.size());
|
|
|
|
|
- for (CustomerEntity c : customers) {
|
|
|
|
|
- if (c.getId() != null) {
|
|
|
|
|
- idToName.put(c.getId(), c.getCustomerName());
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!customerIdSet.isEmpty()) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ List<CustomerEntity> customers =
|
|
|
|
|
+ customerTradeService.listByIds(new ArrayList<>(customerIdSet));
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(customers)) {
|
|
|
|
|
+ Map<Long, String> idToName = new HashMap<>(customers.size());
|
|
|
|
|
+ for (CustomerEntity c : customers) {
|
|
|
|
|
+ if (c.getId() != null) {
|
|
|
|
|
+ idToName.put(c.getId(), c.getCustomerName());
|
|
|
}
|
|
}
|
|
|
- for (com.storlead.trade.vo.MarketEmailsOpenVO v : pageList) {
|
|
|
|
|
- if (v.getCustomerId() != null) {
|
|
|
|
|
- v.setCustomerName(idToName.get(v.getCustomerId()));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ for (MarketEmailsOpenVO v : voList) {
|
|
|
|
|
+ if (v.getCustomerId() != null) {
|
|
|
|
|
+ v.setCustomerName(idToName.get(v.getCustomerId()));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- } catch (Exception ex) {
|
|
|
|
|
- log.warn("查询客户名称失败,customerIds={} err={}", customerIdSet, ex.getMessage());
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ log.warn("查询客户名称失败,customerIds={} err={}", customerIdSet, ex.getMessage());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- return Result.result(page);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ IPage<MarketEmailsOpenVO> voPage = new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal());
|
|
|
|
|
+ voPage.setRecords(voList);
|
|
|
|
|
+ return Result.result(voPage);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|