添加配置管理功能,包括获取和设置配置值的接口及实现
This commit is contained in:
77
Service/ConfigService.cs
Normal file
77
Service/ConfigService.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
namespace Service;
|
||||
|
||||
public interface IConfigService
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据Key获取配置值
|
||||
/// </summary>
|
||||
Task<T?> GetConfigByKeyAsync<T>(string key);
|
||||
|
||||
/// <summary>
|
||||
/// 设置配置值
|
||||
/// </summary>
|
||||
Task<bool> SetConfigByKeyAsync<T>(string key, T value);
|
||||
}
|
||||
|
||||
public class ConfigService(IConfigRepository configRepository) : IConfigService
|
||||
{
|
||||
public async Task<T?> GetConfigByKeyAsync<T>(string key)
|
||||
{
|
||||
var config = await configRepository.GetByKeyAsync(key);
|
||||
if (config == null || string.IsNullOrEmpty(config.Value))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return config.Type switch
|
||||
{
|
||||
ConfigType.Boolean => (T)(object)bool.Parse(config.Value),
|
||||
ConfigType.String => (T)(object)config.Value,
|
||||
ConfigType.Number => (T)Convert.ChangeType(config.Value, typeof(T)),
|
||||
ConfigType.Json => JsonSerializer.Deserialize<T>(config.Value) ?? default,
|
||||
_ => default
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<bool> SetConfigByKeyAsync<T>(string key, T value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var config = await configRepository.GetByKeyAsync(key);
|
||||
var type = typeof(T) switch
|
||||
{
|
||||
Type t when t == typeof(bool) => ConfigType.Boolean,
|
||||
Type t when t == typeof(int)
|
||||
|| t == typeof(double)
|
||||
|| t == typeof(float)
|
||||
|| t == typeof(decimal) => ConfigType.Number,
|
||||
Type t when t == typeof(string) => ConfigType.String,
|
||||
_ => ConfigType.Json
|
||||
};
|
||||
var valueStr = type switch
|
||||
{
|
||||
ConfigType.Boolean => value.ToString()!.ToLower(),
|
||||
ConfigType.Number => value.ToString()!,
|
||||
ConfigType.String => value as string ?? string.Empty,
|
||||
ConfigType.Json => JsonSerializer.Serialize(value),
|
||||
_ => throw new InvalidOperationException("Unsupported config type")
|
||||
};
|
||||
if (config == null)
|
||||
{
|
||||
config = new ConfigEntity
|
||||
{
|
||||
Key = key,
|
||||
Type = type,
|
||||
|
||||
};
|
||||
return await configRepository.AddAsync(config);
|
||||
}
|
||||
|
||||
config.Value = valueStr;
|
||||
config.Type = type;
|
||||
return await configRepository.UpdateAsync(config);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,8 @@ public class SmartHandleService(
|
||||
ITextSegmentService textSegmentService,
|
||||
ILogger<SmartHandleService> logger,
|
||||
ITransactionCategoryRepository categoryRepository,
|
||||
IOpenAiService openAiService
|
||||
IOpenAiService openAiService,
|
||||
IConfigService configService
|
||||
) : ISmartHandleService
|
||||
{
|
||||
public async Task SmartClassifyAsync(long[] transactionIds, Action<(string, string)> chunkAction)
|
||||
@@ -258,9 +259,9 @@ public class SmartHandleService(
|
||||
{
|
||||
// 第一步:使用AI生成聚合SQL查询
|
||||
var now = DateTime.Now;
|
||||
var sqlPrompt = $"""
|
||||
当前日期:{now:yyyy年M月d日}({now:yyyy-MM-dd})
|
||||
用户问题:{userInput}
|
||||
var sqlPrompt = $$"""
|
||||
当前日期:{{now:yyyy年M月d日}}({{now:yyyy-MM-dd}})
|
||||
用户问题:{{userInput}}
|
||||
|
||||
数据库类型:SQLite
|
||||
数据库表名:TransactionRecord
|
||||
@@ -291,22 +292,27 @@ public class SmartHandleService(
|
||||
- 提取日期:strftime('%Y-%m-%d', OccurredAt)
|
||||
- 不要使用 YEAR()、MONTH()、DAY() 函数,SQLite不支持
|
||||
|
||||
示例1(按分类统计):
|
||||
用户:这三个月坐车花了多少钱?
|
||||
返回:SELECT Classify, COUNT(*) as TransactionCount, SUM(ABS(Amount)) as TotalAmount, AVG(ABS(Amount)) as AvgAmount FROM TransactionRecord WHERE Type = 0 AND OccurredAt >= '2025-10-01' AND OccurredAt < '2026-01-01' AND (Classify LIKE '%交通%' OR Reason LIKE '%打车%' OR Reason LIKE '%公交%' OR Reason LIKE '%地铁%') GROUP BY Classify ORDER BY TotalAmount DESC
|
||||
|
||||
示例2(按月统计):
|
||||
用户:最近半年每月支出情况
|
||||
返回:SELECT strftime('%Y', OccurredAt) as Year, strftime('%m', OccurredAt) as Month, COUNT(*) as TransactionCount, SUM(ABS(Amount)) as TotalAmount FROM TransactionRecord WHERE Type = 0 AND OccurredAt >= '2025-06-01' GROUP BY strftime('%Y', OccurredAt), strftime('%m', OccurredAt) ORDER BY Year, Month
|
||||
|
||||
示例3(总体统计):
|
||||
用户:本月花了多少钱?
|
||||
返回:SELECT COUNT(*) as TransactionCount, SUM(ABS(Amount)) as TotalAmount, AVG(ABS(Amount)) as AvgAmount, MAX(ABS(Amount)) as MaxAmount FROM TransactionRecord WHERE Type = 0 AND OccurredAt >= '2025-12-01' AND OccurredAt < '2026-01-01'
|
||||
|
||||
示例4(详细记录 - 仅在用户明确要求详情时使用):
|
||||
用户:单笔超过1000元的支出有哪些?
|
||||
返回:SELECT OccurredAt, Classify, Reason, ABS(Amount) as Amount FROM TransactionRecord WHERE Type = 0 AND ABS(Amount) > 1000 ORDER BY Amount DESC LIMIT 50
|
||||
|
||||
【重要】最终的SQL会被一下DOTNET代码执行, 请确保你生成的代码可执行,不报错
|
||||
```C#
|
||||
public async Task<List<dynamic>> ExecuteDynamicSqlAsync(string completeSql)
|
||||
{
|
||||
var dt = await FreeSql.Ado.ExecuteDataTableAsync(completeSql);
|
||||
var result = new List<dynamic>();
|
||||
|
||||
foreach (System.Data.DataRow row in dt.Rows)
|
||||
{
|
||||
var expando = new System.Dynamic.ExpandoObject() as IDictionary<string, object>;
|
||||
foreach (System.Data.DataColumn column in dt.Columns)
|
||||
{
|
||||
expando[column.ColumnName] = row[column];
|
||||
}
|
||||
result.Add(expando);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
只返回SQL语句。
|
||||
""";
|
||||
|
||||
@@ -344,10 +350,15 @@ public class SmartHandleService(
|
||||
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||
});
|
||||
|
||||
var userPromptExtra = await configService.GetConfigByKeyAsync<string>("BillAnalysisPrompt");
|
||||
|
||||
var dataPrompt = $"""
|
||||
当前日期:{DateTime.Now:yyyy年M月d日}
|
||||
用户问题:{userInput}
|
||||
|
||||
【用户要求(重要)】
|
||||
{userInput}
|
||||
|
||||
查询结果数据(JSON格式):
|
||||
{dataJson}
|
||||
|
||||
@@ -375,6 +386,9 @@ public class SmartHandleService(
|
||||
13. 提供洞察分析:根据数据给出有价值的发现和趋势分析
|
||||
14. 给出实用建议:基于数据提供合理的财务建议
|
||||
15. 语言专业、清晰、简洁
|
||||
|
||||
【用户补充(重要)】
|
||||
{userPromptExtra}
|
||||
|
||||
直接输出纯净的HTML内容,不要markdown代码块标记。
|
||||
""";
|
||||
|
||||
Reference in New Issue
Block a user