Files
qhmes/yy-admin-master/YY.Admin.Services/Service/Print/PrintBizTemplateBindService.cs

173 lines
6.2 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.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Http;
using YY.Admin.Core.Entity;
using YY.Admin.Core.Services;
namespace YY.Admin.Services.Service.Print;
/// <summary>业务打印绑定:免密列表 + 本地缓存(只读)</summary>
public class PrintBizTemplateBindService : IPrintBizTemplateBindService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly IConfiguration _configuration;
private readonly object _cacheLock = new();
private List<PrintBizTemplateBind> _localCache = new();
private readonly string _cacheFilePath;
private static readonly JsonSerializerOptions JsonOpts = new()
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters = { new NullableDateTimeJsonConverter() }
};
private string BaseUrl =>
(_configuration.GetValue<string>("JeecgIntegration:BaseUrl") ?? "http://localhost:8080/jeecg-boot").TrimEnd('/');
public PrintBizTemplateBindService(IHttpClientFactory httpClientFactory, IConfiguration configuration)
{
_httpClientFactory = httpClientFactory;
_configuration = configuration;
var appDataDir = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"YY.Admin", "sync-cache");
Directory.CreateDirectory(appDataDir);
_cacheFilePath = Path.Combine(appDataDir, "print-biz-bind-cache.json");
LoadCacheFromDisk();
}
public IReadOnlyList<PrintBizTemplateBind> GetCached()
{
lock (_cacheLock)
{
return _localCache.AsReadOnly();
}
}
public async Task<IReadOnlyList<PrintBizTemplateBind>> ListAsync(CancellationToken ct = default)
{
try
{
return await RefreshCacheAsync(ct).ConfigureAwait(false);
}
catch
{
return GetCached();
}
}
public async Task<IReadOnlyList<PrintBizTemplateBind>> RefreshCacheAsync(CancellationToken ct = default)
{
var client = _httpClientFactory.CreateClient("JeecgApi");
var url = $"{BaseUrl}/print/bizTemplateBind/anon/list?pageSize=500&pageNo=1";
var response = await client.GetAsync(url, ct).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<JeecgResult<JeecgPage<PrintBizTemplateBind>>>(JsonOpts, ct).ConfigureAwait(false);
if (result?.Success != true)
throw new InvalidOperationException(result?.Message ?? "后端返回失败");
var records = result.Result?.Records ?? new List<PrintBizTemplateBind>();
lock (_cacheLock)
{
_localCache = records;
SaveCacheToDiskUnsafe();
}
return records.AsReadOnly();
}
public async Task<PrintBizTemplateBind?> GetByIdAsync(string id, CancellationToken ct = default)
{
if (string.IsNullOrWhiteSpace(id)) return null;
try
{
var client = _httpClientFactory.CreateClient("JeecgApi");
var url = $"{BaseUrl}/print/bizTemplateBind/anon/queryById?id={Uri.EscapeDataString(id)}";
var response = await client.GetAsync(url, ct).ConfigureAwait(false);
if (!response.IsSuccessStatusCode) return GetCachedById(id);
var result = await response.Content.ReadFromJsonAsync<JeecgResult<PrintBizTemplateBind>>(JsonOpts, ct).ConfigureAwait(false);
return result?.Success == true ? result.Result : GetCachedById(id);
}
catch
{
return GetCachedById(id);
}
}
private PrintBizTemplateBind? GetCachedById(string id)
{
lock (_cacheLock)
{
return _localCache.FirstOrDefault(x => string.Equals(x.Id, id, StringComparison.OrdinalIgnoreCase));
}
}
private void LoadCacheFromDisk()
{
try
{
if (!File.Exists(_cacheFilePath)) return;
var json = File.ReadAllText(_cacheFilePath);
var data = JsonSerializer.Deserialize<List<PrintBizTemplateBind>>(json, JsonOpts);
_localCache = data ?? new List<PrintBizTemplateBind>();
}
catch
{
_localCache = new List<PrintBizTemplateBind>();
}
}
private void SaveCacheToDiskUnsafe()
{
try
{
var json = JsonSerializer.Serialize(_localCache, JsonOpts);
File.WriteAllText(_cacheFilePath, json);
}
catch { /* 离线或磁盘异常时忽略 */ }
}
private record JeecgResult<T>(bool Success, T? Result, string? Message);
private record JeecgPage<T>(List<T> Records, long Total);
private sealed class NullableDateTimeJsonConverter : JsonConverter<DateTime?>
{
private static readonly string[] Formats =
[
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd HH:mm:ss.fff",
"yyyy-MM-ddTHH:mm:ss",
"yyyy-MM-ddTHH:mm:ss.fff",
"yyyy-MM-ddTHH:mm:ssZ",
"yyyy-MM-ddTHH:mm:ss.fffZ"
];
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null) return null;
if (reader.TokenType == JsonTokenType.String)
{
var raw = reader.GetString();
if (string.IsNullOrWhiteSpace(raw)) return null;
if (DateTime.TryParseExact(raw, Formats, System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.AssumeLocal, out var exact))
return exact;
if (DateTime.TryParse(raw, out var fallback)) return fallback;
}
throw new JsonException($"无法将 JSON 值转换为 DateTime?token={reader.TokenType}");
}
public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options)
{
if (value.HasValue) writer.WriteStringValue(value.Value.ToString("yyyy-MM-dd HH:mm:ss"));
else writer.WriteNullValue();
}
}
}