using System; using System.Linq; using System.Threading.Tasks; using NCC.Common.Const; using NCC.Common.Core.Manager; using NCC.Dependency; using NCC.Extend.Entitys.lq_user_profile_version; using NCC.Extend.Interfaces.UserProfileVersion; using NCC.Extend.Models; using NCC.System.Entitys.Permission; using Newtonsoft.Json; using SqlSugar; using Yitter.IdGenerator; namespace NCC.Extend { /// /// 用户主档时点全量版本写入(R-004)。 /// public class LqUserProfileVersionAppenderService : IUserProfileVersionAppender, ITransient { private static readonly JsonSerializerSettings FullSnapshotJsonSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include, DateFormatString = "yyyy-MM-dd HH:mm:ss", DateTimeZoneHandling = DateTimeZoneHandling.Local }; private readonly ISqlSugarClient _db; public LqUserProfileVersionAppenderService(ISqlSugarClient db) { _db = db; } /// public async Task AfterUserProfilePersistedAsync(string targetUserId, string changeTrigger, bool forceNewVersion = false) { if (string.IsNullOrWhiteSpace(targetUserId)) { return; } var row = await _db.Queryable() .Where(x => x.Id == targetUserId) .FirstAsync(); if (row == null) { return; } var sanitized = BuildSanitizedUserSnapshot(row); var fullPayload = new LqUserProfileFullSnapshotDto { SchemaVersion = LqUserProfileSnapshotConstants.FullUserSchemaVersion, User = sanitized }; var fullJson = JsonConvert.SerializeObject(fullPayload, FullSnapshotJsonSettings); var lastRows = await _db.Queryable() .Where(x => x.TargetUserId == targetUserId) .OrderBy(x => x.VersionNo, OrderByType.Desc) .Take(1) .ToListAsync(); var last = lastRows.FirstOrDefault(); if (!forceNewVersion && last != null && string.Equals(last.FullSnapshotJson ?? string.Empty, fullJson, StringComparison.Ordinal)) { return; } var now = DateTime.Now; if (last != null) { await _db.Updateable() .SetColumns(x => new LqUserProfileVersionEntity { ValidTo = now }) .Where(x => x.Id == last.Id) .ExecuteCommandAsync(); } var (opId, opName) = ResolveOperatorFromClaims(); var ver = new LqUserProfileVersionEntity { Id = YitIdHelper.NextId().ToString(), TargetUserId = row.Id, VersionNo = (last?.VersionNo ?? 0) + 1, ValidFrom = now, ValidTo = null, OperatorUserId = opId, OperatorUserName = opName, ChangeTrigger = changeTrigger, Mdid = row.Mdid, Gw = row.Gw, OrganizeId = row.OrganizeId, FullSnapshotJson = fullJson }; await _db.Insertable(ver).ExecuteCommandAsync(); } private static UserEntity BuildSanitizedUserSnapshot(UserEntity src) { var c = UserProfileAuditAppenderService.CloneUser(src); if (c == null) { return null; } c.Password = null; c.Secretkey = null; return c; } private static (string opId, string opName) ResolveOperatorFromClaims() { var ctx = App.HttpContext; if (ctx?.User?.Identity?.IsAuthenticated != true) { return (null, "系统"); } var uid = ctx.User.FindFirst(ClaimConst.CLAINM_USERID)?.Value?.Trim(); var name = ctx.User.FindFirst(ClaimConst.CLAINM_REALNAME)?.Value?.Trim(); if (string.IsNullOrWhiteSpace(name)) { name = ctx.User.FindFirst(ClaimConst.CLAINM_ACCOUNT)?.Value?.Trim(); } if (string.IsNullOrWhiteSpace(name)) { name = "系统"; } return (uid, name); } } }