| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- using System.Data;
- using System.Text.Json;
- using Admin.NET.Plugin.AiDOP.Entity.S8;
- using Microsoft.Extensions.Logging;
- using SqlSugar;
- namespace Admin.NET.Plugin.AiDOP.Service.S8.Rules;
- /// <summary>
- /// S8 规则取数:SQL 走 SqlSugarScope;API 走 HTTP GET(endpoint=完整 URL)。
- /// </summary>
- public class S8DataSourceRowLoader : ITransient
- {
- public const string SqlType = "SQL";
- public const string ApiType = "API";
- private readonly S8SqlSugarScopeFactory _scopeFactory;
- private readonly ILogger<S8DataSourceRowLoader> _logger;
- public S8DataSourceRowLoader(S8SqlSugarScopeFactory scopeFactory, ILogger<S8DataSourceRowLoader> logger)
- {
- _scopeFactory = scopeFactory;
- _logger = logger;
- }
- public async Task<DataTable> LoadAsync(
- AdoS8DataSource dataSource,
- string expression,
- SqlSugar.DbType dbType,
- int timeoutSeconds,
- CancellationToken cancellationToken = default)
- {
- var type = dataSource.Type?.Trim() ?? SqlType;
- if (string.Equals(type, SqlType, StringComparison.OrdinalIgnoreCase))
- {
- using var db = _scopeFactory.CreateScope(dataSource.Endpoint!, dbType, timeoutSeconds);
- return await db.Ado.GetDataTableAsync(expression);
- }
- if (string.Equals(type, ApiType, StringComparison.OrdinalIgnoreCase))
- return await LoadFromApiAsync(dataSource, expression, timeoutSeconds, cancellationToken);
- throw new InvalidOperationException($"不支持的数据源类型:{type}");
- }
- public static bool IsSupportedType(string? type) =>
- string.Equals(type?.Trim(), SqlType, StringComparison.OrdinalIgnoreCase)
- || string.Equals(type?.Trim(), ApiType, StringComparison.OrdinalIgnoreCase);
- private async Task<DataTable> LoadFromApiAsync(
- AdoS8DataSource dataSource,
- string expression,
- int timeoutSeconds,
- CancellationToken cancellationToken)
- {
- if (string.IsNullOrWhiteSpace(dataSource.Endpoint))
- throw new InvalidOperationException("API 数据源 endpoint 为空");
- var url = dataSource.Endpoint.Trim();
- if (!string.IsNullOrWhiteSpace(expression)
- && !expression.TrimStart().StartsWith("SELECT", StringComparison.OrdinalIgnoreCase))
- {
- if (expression.StartsWith('?'))
- url = url.Contains('?') ? url + "&" + expression.TrimStart('?') : url + expression;
- else if (expression.StartsWith('/'))
- url = url.TrimEnd('/') + expression;
- }
- _logger.LogDebug("S8 API 取数 url={Url} authType={AuthType}", url, dataSource.AuthType);
- using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(Math.Max(5, timeoutSeconds)) };
- using var resp = await http.GetAsync(url, cancellationToken);
- resp.EnsureSuccessStatusCode();
- var json = await resp.Content.ReadAsStringAsync(cancellationToken);
- return JsonToDataTable(json);
- }
- /// <summary>支持 {data:{list:[...]}} / {list:[...]} / [...] 。</summary>
- internal static DataTable JsonToDataTable(string json)
- {
- using var doc = JsonDocument.Parse(json);
- JsonElement arr;
- var root = doc.RootElement;
- if (root.ValueKind == JsonValueKind.Array)
- arr = root;
- else if (root.TryGetProperty("data", out var data) && data.TryGetProperty("list", out var list) && list.ValueKind == JsonValueKind.Array)
- arr = list;
- else if (root.TryGetProperty("list", out var list2) && list2.ValueKind == JsonValueKind.Array)
- arr = list2;
- else
- throw new InvalidOperationException("API 响应不是可识别的行数组(期望 data.list / list / [])");
- var table = new DataTable();
- foreach (var item in arr.EnumerateArray())
- {
- if (item.ValueKind != JsonValueKind.Object) continue;
- foreach (var prop in item.EnumerateObject())
- {
- if (!table.Columns.Contains(prop.Name))
- table.Columns.Add(prop.Name, typeof(string));
- }
- }
- foreach (var item in arr.EnumerateArray())
- {
- if (item.ValueKind != JsonValueKind.Object) continue;
- var row = table.NewRow();
- foreach (DataColumn col in table.Columns)
- {
- if (item.TryGetProperty(col.ColumnName, out var v))
- row[col.ColumnName] = v.ValueKind is JsonValueKind.Null or JsonValueKind.Undefined
- ? DBNull.Value
- : v.ToString();
- }
- table.Rows.Add(row);
- }
- return table;
- }
- }
|