|
|
@@ -1,42 +1,138 @@
|
|
|
package com.tzld.piaoquan.recommend.server.service.tab;
|
|
|
|
|
|
+import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
|
|
|
+import com.google.common.collect.Sets;
|
|
|
+import com.tzld.piaoquan.recommend.server.common.enums.TabSource;
|
|
|
+import com.tzld.piaoquan.recommend.server.common.enums.TabType;
|
|
|
import com.tzld.piaoquan.recommend.server.gen.common.Result;
|
|
|
import com.tzld.piaoquan.recommend.server.gen.common.TabProto;
|
|
|
import com.tzld.piaoquan.recommend.server.gen.tab.TabRequest;
|
|
|
import com.tzld.piaoquan.recommend.server.gen.tab.TabResponse;
|
|
|
import com.tzld.piaoquan.recommend.server.model.TabParam;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.collections4.CollectionUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.HashSet;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Set;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
public class TabService {
|
|
|
|
|
|
+
|
|
|
@Autowired
|
|
|
@Qualifier("redisTemplate")
|
|
|
protected RedisTemplate<String, String> redisTemplate;
|
|
|
|
|
|
+ @ApolloJsonValue("${homepage.default.tab:[]}")
|
|
|
+ private List<String> homepageDefaultTab;
|
|
|
+
|
|
|
+ @ApolloJsonValue("${personalization.tab.size:2}")
|
|
|
+ private Integer personalizationTabSize;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 中国行政区划代码(GB/T 2260)省級前缀,前2位。
|
|
|
+ * 11-15 华北, 21-23 东北, 31-37 华东, 41-46 中南, 50-54 西南, 61-65 西北,
|
|
|
+ * 71 台湾, 81-82 香港/澳门
|
|
|
+ */
|
|
|
+ private static final Set<String> CHINA_PROVINCE_CODE_PREFIXES = Sets.newHashSet(
|
|
|
+ "11", "12", "13", "14", "15",
|
|
|
+ "21", "22", "23",
|
|
|
+ "31", "32", "33", "34", "35", "36", "37",
|
|
|
+ "41", "42", "43", "44", "45", "46",
|
|
|
+ "50", "51", "52", "53", "54",
|
|
|
+ "61", "62", "63", "64", "65",
|
|
|
+ "71", "81", "82"
|
|
|
+ );
|
|
|
+
|
|
|
+ private static final String redisKeyPrefox = "personalized_tab_candidate:";
|
|
|
+
|
|
|
+ private static final String PERSONALIZATION_TAB_SEPARATOR = "&";
|
|
|
+
|
|
|
public TabResponse homepageTab(TabRequest request) {
|
|
|
TabParam tabParam = this.requestCoverToParam(request);
|
|
|
|
|
|
List<TabProto> tabProtos = new ArrayList<>();
|
|
|
- tabProtos.add(TabProto.newBuilder().setKey(request.getProvince()).setTitle(request.getProvince()).setSource("").setType("territory").build());
|
|
|
- tabProtos.add(TabProto.newBuilder().setKey("祝福").setTitle("祝福").setSource("share").setType("personalization").build());
|
|
|
- tabProtos.add(TabProto.newBuilder().setKey("春节").setTitle("春节").setSource("share").setType("personalization").build());
|
|
|
+ tabProtos.addAll(this.territoryTab(tabParam));
|
|
|
+ tabProtos.addAll(this.personalizationTab(tabParam));
|
|
|
+
|
|
|
return TabResponse.newBuilder()
|
|
|
.setResult(Result.newBuilder().setCode(1).setMessage("success"))
|
|
|
.addAllTab(tabProtos)
|
|
|
.build();
|
|
|
}
|
|
|
|
|
|
+ private List<TabProto> territoryTab(TabParam tabParam) {
|
|
|
+ List<TabProto> tabProtos = new ArrayList<>();
|
|
|
+ // 非中国地域不返回地域Tab
|
|
|
+ if (isChinaRegion(tabParam.getProvinceCode())) {
|
|
|
+ tabProtos.add(TabProto.newBuilder().setKey(tabParam.getProvince()).setTitle(tabParam.getProvince()).setSource("").setType(TabType.territory.getType()).build());
|
|
|
+ }
|
|
|
+ return tabProtos;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<TabProto> personalizationTab(TabParam tabParam) {
|
|
|
+ List<TabProto> defaultTab = this.buildTabProto(homepageDefaultTab, TabSource.default_hot, TabType.personalization);
|
|
|
+ List<TabProto> tabProtos = new ArrayList<>(defaultTab);
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(tabParam.getUnionId())) {
|
|
|
+ log.error("unionId is empty");
|
|
|
+ return tabProtos;
|
|
|
+ }
|
|
|
+
|
|
|
+ String key = redisKeyPrefox + tabParam.getUnionId();
|
|
|
+ String value = redisTemplate.opsForValue().get(key);
|
|
|
+ if (StringUtils.isBlank(value)) {
|
|
|
+ log.error("unionId is not exist");
|
|
|
+ return tabProtos;
|
|
|
+ }
|
|
|
+ List<List<String>> tabCollect = Arrays.stream(value.split("\t"))
|
|
|
+ .map(i -> Arrays.asList(i.split(PERSONALIZATION_TAB_SEPARATOR)))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (tabCollect.size() != 4) {
|
|
|
+ log.error("redis value size nq 4, {}", value);
|
|
|
+ return tabProtos;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<TabProto> profileTab = this.buildTabProto(tabCollect.get(0), TabSource.profile, TabType.personalization);
|
|
|
+ List<TabProto> shareCate2Tab = this.buildTabProto(tabCollect.get(0), TabSource.share_cate2, TabType.personalization);
|
|
|
+ List<TabProto> returnCate2Tab = this.buildTabProto(tabCollect.get(0), TabSource.return_cate2, TabType.personalization);
|
|
|
+ List<TabProto> defaultHotTab = this.buildTabProto(tabCollect.get(0), TabSource.default_hot, TabType.personalization);
|
|
|
+
|
|
|
+ // 默认兜底Tab
|
|
|
+ tabProtos.addAll(0, defaultHotTab);
|
|
|
+ tabProtos.addAll(0, returnCate2Tab);
|
|
|
+ tabProtos.addAll(0, shareCate2Tab);
|
|
|
+ tabProtos.addAll(0, profileTab);
|
|
|
+ return tabProtos.subList(0, Math.min(tabProtos.size(), personalizationTabSize));
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<TabProto> buildTabProto(List<String> tabNames, TabSource source, TabType type) {
|
|
|
+ if (CollectionUtils.isEmpty(tabNames)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ List<TabProto> tabProtos = new ArrayList<>();
|
|
|
+ for (String tabName : tabNames) {
|
|
|
+ if (StringUtils.isBlank(tabName)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ tabProtos.add(
|
|
|
+ TabProto.newBuilder()
|
|
|
+ .setKey(tabName)
|
|
|
+ .setTitle(tabName)
|
|
|
+ .setSource(source.getSource())
|
|
|
+ .setType(type.getType())
|
|
|
+ .build()
|
|
|
+ );
|
|
|
+ }
|
|
|
+ return tabProtos;
|
|
|
+ }
|
|
|
+
|
|
|
private TabParam requestCoverToParam(TabRequest request) {
|
|
|
TabParam param = new TabParam();
|
|
|
param.setRequestId(request.getRequestId());
|
|
|
@@ -61,4 +157,18 @@ public class TabService {
|
|
|
return param;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 判断行政区划代码是否属于中国。
|
|
|
+ * 通过省份代码前2位匹配 GB/T 2260 中的中国省级前缀来校验。
|
|
|
+ *
|
|
|
+ * @param provinceCode 省份代码(2位或6位均可)
|
|
|
+ * @return true 表示是中国地域
|
|
|
+ */
|
|
|
+ private boolean isChinaRegion(String provinceCode) {
|
|
|
+ if (StringUtils.isBlank(provinceCode) || provinceCode.length() < 2) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return CHINA_PROVINCE_CODE_PREFIXES.contains(provinceCode.substring(0, 2));
|
|
|
+ }
|
|
|
+
|
|
|
}
|