| | |
| | | public static final String CONFIG_KEY = "satisfaction.enabled"; |
| | | |
| | | /** |
| | | * 满意度「综合得分口径」站点参数键名。 |
| | | * <p> |
| | | * 值取 {@link com.ruoyi.satisfaction.service.strategy.SatisfactionSites} 的标识: |
| | | * <ul> |
| | | * <li>{@code sltd}(默认)—— 省立同德口径:按选项文案判五档加权;</li> |
| | | * <li>{@code common}(别名 {@code nanhua})—— 通用/南华口径:按明细 score 求平均。</li> |
| | | * </ul> |
| | | * 本参数是 2026-10-21 新增的:{@code /smartor/serviceSubtaskDetail/sltdMydTotalByScore} |
| | | * 原来把口径写死成 SLTD,南华调用时五档文案一条都匹配不上,综合得分恒为 0.00。 |
| | | */ |
| | | public static final String SITE_CONFIG_KEY = "satisfaction.site"; |
| | | |
| | | /** |
| | | * 未配置站点时的默认口径:保持历史行为(SLTD 口径) |
| | | */ |
| | | private static final String DEFAULT_SITE = com.ruoyi.satisfaction.service.strategy.SatisfactionSites.SLTD; |
| | | |
| | | /** |
| | | * 进程内缓存有效期(毫秒) |
| | | */ |
| | | private static final long CACHE_TTL_MILLIS = 10_000L; |
| | |
| | | private volatile long cachedAt; |
| | | |
| | | /** |
| | | * 最近一次解析到的「综合得分口径」站点 |
| | | */ |
| | | private volatile String cachedSite; |
| | | |
| | | /** |
| | | * 最近一次解析站点的时间戳 |
| | | */ |
| | | private volatile long cachedSiteAt; |
| | | |
| | | /** |
| | | * Spring 使用的构造器。 |
| | | * <p> |
| | | * ⚠️ <b>必须显式标注 {@code @Autowired}</b>:本类有两个公开构造器 |
| | |
| | | // 非 Spring 环境下没有"改配置后等 10 秒"的概念,直接禁用缓存,保证断言即时可见 |
| | | this.cachedEnabled = resolve(); |
| | | this.cachedAt = System.currentTimeMillis() + CACHE_TTL_MILLIS * 1000L; |
| | | // 测试用的 FixedProvider 对任何 key 都返回同一个值,这里不要误把它当成站点配置 |
| | | this.cachedSite = DEFAULT_SITE; |
| | | this.cachedSiteAt = System.currentTimeMillis() + CACHE_TTL_MILLIS * 1000L; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public void invalidateCache() { |
| | | this.cachedEnabled = null; |
| | | this.cachedSite = null; |
| | | } |
| | | |
| | | /** |
| | | * 当前的<b>综合得分口径站点</b>({@code sys_config: satisfaction.site},运行时热读,最多 10 秒延迟) |
| | | * <p> |
| | | * 未配置时返回 {@link #DEFAULT_SITE}({@code sltd}),保持历史行为不变; |
| | | * 南华部署请把该参数配成 {@code common}(别名 {@code nanhua})。 |
| | | * |
| | | * @return 归一化后的站点标识(见 {@link com.ruoyi.satisfaction.service.strategy.SatisfactionSites}) |
| | | */ |
| | | public String site() { |
| | | long now = System.currentTimeMillis(); |
| | | String cached = this.cachedSite; |
| | | if (cached != null && now - this.cachedSiteAt < CACHE_TTL_MILLIS) { |
| | | return cached; |
| | | } |
| | | String site = resolveSite(); |
| | | this.cachedSite = site; |
| | | this.cachedSiteAt = now; |
| | | return site; |
| | | } |
| | | |
| | | /** |
| | | * 解析站点口径:sys_config 优先,缺省用 {@link #DEFAULT_SITE} |
| | | */ |
| | | private String resolveSite() { |
| | | String value = readConfig(SITE_CONFIG_KEY); |
| | | if (value != null) { |
| | | String site = com.ruoyi.satisfaction.service.strategy.SatisfactionSites.normalize(value); |
| | | log.debug("【满意度】综合得分口径取自 sys_config:{}={} -> site={}", SITE_CONFIG_KEY, value, site); |
| | | return site; |
| | | } |
| | | log.debug("【满意度】sys_config 中未配置 {},回落默认站点 {}(同德口径)", SITE_CONFIG_KEY, DEFAULT_SITE); |
| | | return DEFAULT_SITE; |
| | | } |
| | | |
| | | /** |
| | | * 解析当前开关值:sys_config 优先,其次 yml 兜底 |
| | | */ |
| | | private boolean resolve() { |
| | | String value = readFromSysConfig(); |
| | | String value = readConfig(CONFIG_KEY); |
| | | if (value != null) { |
| | | if (!"true".equalsIgnoreCase(value) && !"false".equalsIgnoreCase(value)) { |
| | | log.warn("【满意度】sys_config 中 {} 的值不是 true/false(实际=「{}」),将按「不是 false 即启用」处理", |
| | |
| | | /** |
| | | * 读 sys_config 的原始键值;没有实现、没有这一行、或读库失败都返回 {@code null} |
| | | */ |
| | | private String readFromSysConfig() { |
| | | private String readConfig(String key) { |
| | | if (configServiceProvider == null) { |
| | | return null; |
| | | } |
| | |
| | | if (configService == null) { |
| | | return null; |
| | | } |
| | | String value = configService.selectConfigByKey(CONFIG_KEY); |
| | | String value = configService.selectConfigByKey(key); |
| | | if (value == null || value.trim().isEmpty()) { |
| | | return null; |
| | | } |
| | |
| | | } catch (Exception e) { |
| | | // 容器没有实现、数据源异常、SQL 报错……一律按"参数缺失"处理(fail-open),绝不影响主流程 |
| | | log.warn("【满意度】读取 sys_config 的 {} 失败,本次按未配置处理(fail-open):{}", |
| | | CONFIG_KEY, e.toString()); |
| | | key, e.toString()); |
| | | return null; |
| | | } |
| | | } |