using Microsoft.Extensions.Configuration; using SqlSugar; using System.Text.Json; using YY.Admin.Core; using YY.Admin.Services.Service.Jeecg; namespace YY.Admin.Services.Service; public class JeecgDictSyncService : IJeecgDictSyncService, ISingletonDependency { private readonly ISqlSugarClient _dbContext; private readonly IConfiguration _configuration; private readonly IJeecgBackendGateway _jeecgGateway; public JeecgDictSyncService( ISqlSugarClient dbContext, IConfiguration configuration, IJeecgBackendGateway jeecgGateway) { _dbContext = dbContext; _configuration = configuration; _jeecgGateway = jeecgGateway; } public async Task> PageAsync(PageJeecgDictItemInput input) { var statusFilter = input.Status.HasValue ? (int?)input.Status.Value : null; var query = _dbContext.Queryable().ClearFilter() .WhereIF(!string.IsNullOrWhiteSpace(input.DictCode), x => x.DictCode != null && x.DictCode == input.DictCode) .WhereIF(!string.IsNullOrWhiteSpace(input.DictName), x => x.DictName != null && x.DictName.Contains(input.DictName)) .WhereIF(!string.IsNullOrWhiteSpace(input.ItemText), x => x.ItemText != null && x.ItemText.Contains(input.ItemText)) .WhereIF(!string.IsNullOrWhiteSpace(input.ItemValue), x => x.ItemValue != null && x.ItemValue.Contains(input.ItemValue)); if (statusFilter.HasValue) { var statusValue = statusFilter.Value; query = query.Where(x => x.Status == statusValue); } query = query.OrderBy(x => SqlFunc.Asc(x.DictCode)) .OrderBy(x => SqlFunc.Asc(x.SortOrder)) .OrderBy(x => SqlFunc.Desc(x.CreateTime)); RefAsync total = 0; var list = await query.ToPageListAsync(input.Page, input.PageSize, total); var items = list.Select(x => new JeecgDictItemOutput { Id = x.Id, DictCode = x.DictCode, DictName = x.DictName, ItemText = x.ItemText, ItemValue = x.ItemValue, ItemDescription = x.ItemDescription, SortOrder = x.SortOrder, Status = x.Status == 1 ? StatusEnum.Enable : StatusEnum.Disable, ItemColor = x.ItemColor, CreateTime = x.CreateTime, UpdateTime = x.UpdateTime }).ToList(); return new SqlSugarPagedList { Page = input.Page, PageSize = input.PageSize, Total = total, TotalPages = input.PageSize > 0 ? (int)Math.Ceiling(total / (double)input.PageSize) : 0, HasNextPage = input.PageSize > 0 && input.Page < (int)Math.Ceiling(total / (double)input.PageSize), HasPrevPage = input.Page > 1, Items = items }; } public async Task SyncFromJeecgAsync() { var baseUrl = _configuration.GetValue("JeecgIntegration:BaseUrl")?.TrimEnd('/'); if (string.IsNullOrWhiteSpace(baseUrl)) { return 0; } var dictPath = _configuration.GetValue("JeecgIntegration:DictListPath") ?? "/sys/dict/scada/queryDictItem"; const int pageSize = 500; var pageNo = 1; var synced = 0; var seenIds = new HashSet(StringComparer.OrdinalIgnoreCase); while (true) { var requestUrl = $"{baseUrl}{dictPath}?pageNo={pageNo}&pageSize={pageSize}"; var json = await _jeecgGateway.ExecuteGetStringAsync(requestUrl); if (string.IsNullOrWhiteSpace(json)) { break; } using var doc = JsonDocument.Parse(json); var root = doc.RootElement; if (!(root.TryGetProperty("success", out var successEl) && successEl.GetBoolean())) { break; } if (!root.TryGetProperty("result", out var recordsEl) || recordsEl.ValueKind != JsonValueKind.Array) { break; } var currentBatch = 0; foreach (var row in recordsEl.EnumerateArray()) { var id = GetString(row, "id"); if (string.IsNullOrWhiteSpace(id)) { continue; } seenIds.Add(id); var existing = await _dbContext.Queryable() .ClearFilter() .Where(x => x.Id == id) .FirstAsync(); if (existing == null) { existing = new JeecgSysDictItem { Id = id }; } existing.DictId = GetString(row, "dictId"); existing.DictName = GetString(row, "dictName"); existing.DictCode = GetString(row, "dictCode"); existing.DictType = GetInt(row, "dictType"); existing.DictDescription = GetString(row, "dictDescription"); existing.ItemText = GetString(row, "itemText"); existing.ItemValue = GetString(row, "itemValue"); existing.ItemDescription = GetString(row, "itemDescription"); existing.SortOrder = GetInt(row, "sortOrder"); existing.Status = GetInt(row, "status"); existing.ItemColor = GetString(row, "itemColor"); existing.CreateBy = GetString(row, "createBy"); existing.CreateTime = GetDateTime(row, "createTime"); existing.UpdateBy = GetString(row, "updateBy"); existing.UpdateTime = GetDateTime(row, "updateTime"); var existsCount = await _dbContext.Queryable() .ClearFilter() .Where(x => x.Id == existing.Id) .CountAsync(); if (existsCount > 0) { await _dbContext.Updateable(existing).ExecuteCommandAsync(); } else { await _dbContext.Insertable(existing).ExecuteCommandAsync(); } currentBatch++; } synced += currentBatch; if (currentBatch < pageSize) { break; } pageNo++; } // 删除本地存在但后端已移除的字典项(如后端删除重建导致 ID 变化) if (seenIds.Count > 0) { var seenList = seenIds.ToList(); await _dbContext.Deleteable() .Where(x => !seenList.Contains(x.Id)) .ExecuteCommandAsync(); } return synced; } public async Task>> GetDictGroupsAsync() { var rows = await _dbContext.Queryable() .ClearFilter() .Where(x => x.DictCode != null) .OrderBy(x => x.DictCode) .Select(x => new JeecgSysDictItem { DictCode = x.DictCode, DictName = x.DictName }) .ToListAsync(); return rows .Where(x => !string.IsNullOrWhiteSpace(x.DictCode)) .DistinctBy(x => x.DictCode) .Select(x => new KeyValuePair(x.DictCode!, x.DictName ?? x.DictCode!)) .ToList(); } public async Task>> GetDictOptionsAsync(string dictCode, bool includeAll = false) { var result = new List>(); if (includeAll) { result.Add(new KeyValuePair("全部", "")); } if (string.IsNullOrWhiteSpace(dictCode)) { return result; } var rows = await _dbContext.Queryable() .ClearFilter() .Where(x => x.DictCode == dictCode) .Where(x => x.Status == null || x.Status == 1) .OrderBy(x => SqlFunc.IsNull(x.SortOrder, 0)) .OrderBy(x => SqlFunc.Asc(x.ItemValue)) .ToListAsync(); foreach (var row in rows) { if (string.IsNullOrWhiteSpace(row.ItemValue)) { continue; } result.Add(new KeyValuePair(row.ItemText ?? row.ItemValue, row.ItemValue)); } return result; } private static string? GetString(JsonElement row, string propertyName) { if (!row.TryGetProperty(propertyName, out var el)) { return null; } if (el.ValueKind == JsonValueKind.String) { return el.GetString(); } return el.ToString(); } private static int? GetInt(JsonElement row, string propertyName) { if (!row.TryGetProperty(propertyName, out var el)) { return null; } if (el.ValueKind == JsonValueKind.Number && el.TryGetInt32(out var intVal)) { return intVal; } if (el.ValueKind == JsonValueKind.String && int.TryParse(el.GetString(), out var intStr)) { return intStr; } return null; } private static DateTime? GetDateTime(JsonElement row, string propertyName) { if (!row.TryGetProperty(propertyName, out var el)) { return null; } if (el.ValueKind == JsonValueKind.String && DateTime.TryParse(el.GetString(), out var dt)) { return dt; } return null; } }