package com.ruoyi.satisfaction.config; import com.ruoyi.common.core.service.IConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * 满意度模块总开关:值存放在 {@code sys_config} 参数配置表中,运行时读取、可热切换。 * *
* 参数键名:satisfaction.enabled * 参数键值:true = 启用(默认) * false = 关闭 ** 位置:系统管理 → 参数设置 → 新增/修改。 *
* insert into sys_config (config_name, config_key, config_value, config_type, create_by, create_time, remark)
* values ('满意度模块开关', 'satisfaction.enabled', 'true', 'Y', 'admin', sysdate(), 'true启用,false关闭(默认true)');
*
*
* * 值取 {@link com.ruoyi.satisfaction.service.strategy.SatisfactionSites} 的标识: *
* 用 {@code ObjectProvider} 惰性取:本模块只依赖 ruoyi-common,
* 在单元测试/独立部署等"容器里没有实现"的场景下不能因此启动失败。
*/
private final ObjectProvider
* ⚠️ 必须显式标注 {@code @Autowired}:本类有两个公开构造器
* (另一个给测试/非 Spring 环境用),不标注的话 Spring 会因"构造器不唯一"
* 退回查找无参构造器,启动即报 {@code No default constructor found}。
*/
@Autowired
public SatisfactionSwitch(SatisfactionProperties satisfactionProperties,
ObjectProvider
* 未配置时返回 {@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 = readConfig(CONFIG_KEY);
if (value != null) {
if (!"true".equalsIgnoreCase(value) && !"false".equalsIgnoreCase(value)) {
log.warn("【满意度】sys_config 中 {} 的值不是 true/false(实际=「{}」),将按「不是 false 即启用」处理",
CONFIG_KEY, value);
}
boolean enabled = !"false".equalsIgnoreCase(value);
log.debug("【满意度】开关取自 sys_config:{}={} -> enabled={}", CONFIG_KEY, value, enabled);
return enabled;
}
boolean enabled = satisfactionProperties.isEnabled();
log.debug("【满意度】sys_config 中未配置 {},回落 satisfaction.enabled={}", CONFIG_KEY, enabled);
return enabled;
}
/**
* 读 sys_config 的原始键值;没有实现、没有这一行、或读库失败都返回 {@code null}
*/
private String readConfig(String key) {
if (configServiceProvider == null) {
return null;
}
try {
IConfigService configService = configServiceProvider.stream().findFirst().orElse(null);
if (configService == null) {
return null;
}
String value = configService.selectConfigByKey(key);
if (value == null || value.trim().isEmpty()) {
return null;
}
return value.trim();
} catch (Exception e) {
// 容器没有实现、数据源异常、SQL 报错……一律按"参数缺失"处理(fail-open),绝不影响主流程
log.warn("【满意度】读取 sys_config 的 {} 失败,本次按未配置处理(fail-open):{}",
key, e.toString());
return null;
}
}
/**
* 固定值的 {@code ObjectProvider}:只用于非 Spring 环境/测试
*/
private static final class FixedProvider implements ObjectProvider