LqUserProfileVersionAppenderService.cs 4.49 KB
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
{
    /// <summary>
    /// 用户主档时点全量版本写入(R-004)。
    /// </summary>
    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;
        }

        /// <inheritdoc />
        public async Task AfterUserProfilePersistedAsync(string targetUserId, string changeTrigger, bool forceNewVersion = false)
        {
            if (string.IsNullOrWhiteSpace(targetUserId))
            {
                return;
            }

            var row = await _db.Queryable<UserEntity>()
                .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<LqUserProfileVersionEntity>()
                .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<LqUserProfileVersionEntity>()
                    .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);
        }
    }
}