package com.yunhai.userhome.service; import com.yunhai.platform.openapi.core.YschOpenCall; import com.yunhai.userhome.model.AppIconEntryVo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; /** * 应用矢量图标映射补拉(AppIcon 资产库 P2/P3 数据通道)。
* UserBase 的 {@code GET /oapi/app/icon-map} 返回全量已配置行 [{id, iconKey, iconColor}], * 本服务拉取后建 id 索引供各出参组装点合并注入(BoaApp 属 SDK 本期不动,矢量字段走本通道)。
* */ @Service public class AppIconKeyService { private static final Logger log = LoggerFactory.getLogger(AppIconKeyService.class); /** 服务目录目标名:userbase(与 UserController.TARGET_USERBASE 同口径) */ private static final String TARGET_USERBASE = "userbase"; private static final String PATH_ICON_MAP = "/oapi/app/icon-map"; /** 成功结果缓存时长 */ private static final long TTL_MS = 60_000L; /** 拉取失败后的静默期 */ private static final long FAIL_BACKOFF_MS = 10_000L; @Autowired private YschOpenCall openCall; private volatile Map cached = Collections.emptyMap(); private volatile long fetchedAt = Long.MIN_VALUE; /** * id → 矢量图标条目 映射(含缓存与降级)。空映射 = 无任何应用配置矢量键或通道不可达。 */ public Map iconMap() { long now = System.currentTimeMillis(); if (now - fetchedAt < TTL_MS) { return cached; } try { List list = openCall.getList(TARGET_USERBASE, PATH_ICON_MAP, null, AppIconEntryVo.class); Map map = (list == null) ? Collections.emptyMap() : list.stream() .filter(v -> v != null && v.getId() != null && v.getIconKey() != null) .collect(Collectors.toMap(AppIconEntryVo::getId, Function.identity(), (a, b) -> a)); cached = Collections.unmodifiableMap(map); fetchedAt = now; return cached; } catch (Exception e) { // 降级:沿用上次值;10 秒内不再重试。应用列表主链路绝不因此报错 fetchedAt = now - TTL_MS + FAIL_BACKOFF_MS; log.warn("[appicon] icon-map 拉取失败,按空映射降级:{}", e.toString()); return cached; } } /** 按 id 取单条;无配置返回 null。 */ public AppIconEntryVo byId(Integer appId) { return (appId == null) ? null : iconMap().get(appId); } }