mi-assessment/server/MiAssessment/src/MiAssessment.Core/Services/ConfigService.cs
zpc 8489b4300c refactor(config): 统一配置读取架构,运营配置从Admin库读取
- Model层新增AdminConfig实体和AdminConfigReadDbContext(只读连接Admin库)
- API项目新增AdminConnection连接字符串,注册AdminConfigReadDbContext
- Core层ConfigService按key路由:运营配置走Admin库,业务配置走业务库
- WechatPayConfigService改为从Admin库读取支付/小程序配置
- WechatService新增AdminConfigReadDbContext注入,配置读取改为Admin库
- Autofac注册同步更新三个服务的依赖注入
- Admin.Business的AdminConfigService改用AdminConfigDbContext连接Admin库
2026-02-20 15:48:16 +08:00

206 lines
6.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Text.Json;
using MiAssessment.Core.Interfaces;
using MiAssessment.Model.Data;
using MiAssessment.Model.Models.Config;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace MiAssessment.Core.Services;
/// <summary>
/// 配置服务实现
/// 运营配置app_setting、base等从 Admin 库读取
/// 业务配置从业务库读取
/// </summary>
public class ConfigService : IConfigService
{
private readonly MiAssessmentDbContext _dbContext;
private readonly AdminConfigReadDbContext _adminConfigDbContext;
private readonly ILogger<ConfigService> _logger;
private readonly IRedisService _redisService;
// 当前版本号
private const string CurrentVersion = "116";
/// <summary>
/// 需要从 Admin 库读取的运营配置键
/// </summary>
private static readonly HashSet<string> AdminConfigKeys = new()
{
"app_setting", "base", "weixinpay_setting", "miniprogram_setting",
"weixinpay", "alipay_setting", "h5_setting", "uploads",
"systemconfig", "sign", "user_config", "infinite_multiple",
"rank_setting", "system_test", "tencent_sms_config"
};
public ConfigService(
MiAssessmentDbContext dbContext,
AdminConfigReadDbContext adminConfigDbContext,
ILogger<ConfigService> logger,
IRedisService redisService)
{
_dbContext = dbContext;
_adminConfigDbContext = adminConfigDbContext;
_logger = logger;
_redisService = redisService;
}
/// <inheritdoc />
public async Task<ConfigResponseDto> GetConfigAsync()
{
var response = new ConfigResponseDto
{
Version = CurrentVersion
};
// 获取应用设置
var appSettingJson = await GetConfigValueAsync("app_setting");
if (!string.IsNullOrEmpty(appSettingJson))
{
try
{
response.AppSetting = JsonSerializer.Deserialize<AppSettingDto>(appSettingJson,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to deserialize app_setting config");
}
}
// 获取基础配置
var baseConfigJson = await GetConfigValueAsync("base");
if (!string.IsNullOrEmpty(baseConfigJson))
{
try
{
var baseConfig = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(baseConfigJson,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
if (baseConfig != null)
{
response.BaseConfig = new BaseConfigDto
{
IsShouTan = GetIntValue(baseConfig, "is_shou_tan"),
JumpAppid = GetStringValue(baseConfig, "jump_appid"),
Corpid = GetStringValue(baseConfig, "corpid"),
WxLink = GetStringValue(baseConfig, "wx_link")
};
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to deserialize base config");
}
}
return response;
}
/// <inheritdoc />
public Task<PlatformConfigDto> GetPlatformConfigAsync(string? platform)
{
// 根据平台返回不同配置
// isWebPay = false 表示直接拉起微信支付true 表示走客服消息支付
var config = new PlatformConfigDto
{
IsWebPay = false // 默认关闭 Web 支付,使用原生微信支付
};
// 可以根据 platform 参数返回不同配置
// 例如: MP-WEIXIN, WEB_H5, APP_ANDROID 等
// 目前所有平台都使用原生支付
return Task.FromResult(config);
}
/// <inheritdoc />
public async Task<string?> GetConfigValueAsync(string key)
{
// 尝试从缓存获取
var cacheKey = $"config:{key}";
try
{
var cachedValue = await _redisService.GetStringAsync(cacheKey);
if (!string.IsNullOrEmpty(cachedValue))
{
return cachedValue;
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to get config from cache: {Key}", key);
}
// 根据配置键决定从哪个库读取
string? config;
if (AdminConfigKeys.Contains(key))
{
// 运营配置从 Admin 库读取
config = await _adminConfigDbContext.AdminConfigs
.Where(c => c.ConfigKey == key)
.Select(c => c.ConfigValue)
.FirstOrDefaultAsync();
}
else
{
// 业务配置从业务库读取
config = await _dbContext.Configs
.Where(c => c.ConfigKey == key)
.Select(c => c.ConfigValue)
.FirstOrDefaultAsync();
}
// 存入缓存10分钟过期
if (!string.IsNullOrEmpty(config))
{
try
{
await _redisService.SetStringAsync(cacheKey, config, TimeSpan.FromMinutes(10));
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to cache config: {Key}", key);
}
}
return config;
}
#region Private Helper Methods
private static int GetIntValue(Dictionary<string, JsonElement> dict, string key)
{
if (dict.TryGetValue(key, out var element))
{
if (element.ValueKind == JsonValueKind.Number)
{
return element.GetInt32();
}
if (element.ValueKind == JsonValueKind.String && int.TryParse(element.GetString(), out var value))
{
return value;
}
}
return 0;
}
private static string? GetStringValue(Dictionary<string, JsonElement> dict, string key)
{
if (dict.TryGetValue(key, out var element))
{
if (element.ValueKind == JsonValueKind.String)
{
return element.GetString();
}
if (element.ValueKind != JsonValueKind.Null)
{
return element.ToString();
}
}
return null;
}
#endregion
}