qinchaoyue 1 month ago
parent
commit
a46dd93101

+ 2 - 2
src/Hotline.Api/Controllers/Snapshot/PointsController.cs

@@ -15,9 +15,9 @@ namespace Hotline.Api.Controllers.Snapshot;
 [Description("积分管理")]
 [Description("积分管理")]
 public class PointsController : BaseController
 public class PointsController : BaseController
 {
 {
-    private readonly IPointsRecordApplication _pointsRecordApplication;
+    private readonly ISnapshotPointsApplication _pointsRecordApplication;
 
 
-    public PointsController(IPointsRecordApplication pointsRecordApplication)
+    public PointsController(ISnapshotPointsApplication pointsRecordApplication)
     {
     {
         _pointsRecordApplication = pointsRecordApplication;
         _pointsRecordApplication = pointsRecordApplication;
     }
     }

+ 28 - 1
src/Hotline.Api/Controllers/Snapshot/SnapshotController.cs

@@ -103,7 +103,7 @@ public class SnapshotController : BaseController
         order.AcceptTypeCode = industry.AcceptTypeCode;
         order.AcceptTypeCode = industry.AcceptTypeCode;
         order.AcceptType = industry.AcceptType;
         order.AcceptType = industry.AcceptType;
         order.FromGender = EGender.Unknown;
         order.FromGender = EGender.Unknown;
-        order.Title = dto.GetTitle(industry.IndustryType, industry.AcceptType);
+        order.Title = dto.GetTitle(industry.IndustryType, industry.TitleSuffix);
         order.Content = dto.GetContent(industry.IndustryType);
         order.Content = dto.GetContent(industry.IndustryType);
         order.FromPhone = _sessionContext.Phone;
         order.FromPhone = _sessionContext.Phone;
         order.Contact = _sessionContext.Phone;
         order.Contact = _sessionContext.Phone;
@@ -359,6 +359,33 @@ public class SnapshotController : BaseController
             await _snapshotApplication.PostOrderGuiderSystemAsync(orderId, HttpContext.RequestAborted);
             await _snapshotApplication.PostOrderGuiderSystemAsync(orderId, HttpContext.RequestAborted);
         }
         }
     }
     }
+    #region 积分
+    /// <summary>
+    /// 积分榜
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("points/rank")]
+    public async Task<PointsRankOutDto> GetPointsRankAsync()
+        => await _snapshotApplication.GetPointsRankAsync();
+
+    /// <summary>
+    /// 积分详情
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("points")]
+    public async Task<IList<PointItemsOutDto>> GetPointItemsAsync([FromQuery] PointItemsInDto dto)
+        => await _snapshotApplication.GetPointItemsAsync(dto, HttpContext.RequestAborted);
+
+    /// <summary>
+    /// 积分总计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpGet("points/total")]
+    public async Task<int> GetPointsTotalAsync([FromQuery] PointItemsInDto dto)
+        => await _snapshotApplication.GetPointsTotalAsync(dto, HttpContext.RequestAborted);
+    #endregion
 
 
     #region 第三方系统
     #region 第三方系统
     /// <summary>
     /// <summary>

+ 21 - 0
src/Hotline.Application/Snapshot/Contracts/ISnapshotApplication.cs

@@ -212,4 +212,25 @@ public interface ISnapshotApplication
     /// <param name="id"></param>
     /// <param name="id"></param>
     /// <returns></returns>
     /// <returns></returns>
     Task<IList<OrderVisitItemsOutDto>> GetOrderVisitDetailAsync(string id);
     Task<IList<OrderVisitItemsOutDto>> GetOrderVisitDetailAsync(string id);
+
+    /// <summary>
+    /// 积分榜
+    /// </summary>
+    /// <returns></returns>
+    Task<PointsRankOutDto> GetPointsRankAsync();
+
+    /// <summary>
+    /// 积分详情集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    Task<IList<PointItemsOutDto>> GetPointItemsAsync(PointItemsInDto dto, CancellationToken token);
+
+    /// <summary>
+    /// 积分总计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    Task<int> GetPointsTotalAsync(PointItemsInDto dto, CancellationToken requestAborted);
 }
 }

+ 1 - 1
src/Hotline.Application/Snapshot/Contracts/IPointsRecordApplication.cs → src/Hotline.Application/Snapshot/Contracts/ISnapshotPointsApplication.cs

@@ -7,7 +7,7 @@ using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
 namespace Hotline.Application.Snapshot.Contracts;
 namespace Hotline.Application.Snapshot.Contracts;
-public interface IPointsRecordApplication
+public interface ISnapshotPointsApplication
 {
 {
     ISugarQueryable<PointsItemsOutDto> GetPointsItems(PointsItemsInDto dto);
     ISugarQueryable<PointsItemsOutDto> GetPointsItems(PointsItemsInDto dto);
     Task UpdateIsSecurityMaxAsync(UpdateIsSecurityMaxAsync dto, CancellationToken token);
     Task UpdateIsSecurityMaxAsync(UpdateIsSecurityMaxAsync dto, CancellationToken token);

File diff suppressed because it is too large
+ 0 - 0
src/Hotline.Application/Snapshot/DefaultSnapshotApplication.cs


+ 91 - 7
src/Hotline.Application/Snapshot/SnapshotApplicationBase.cs

@@ -35,6 +35,8 @@ using Hotline.Quality.Notifications;
 using XF.Utility.EnumExtensions;
 using XF.Utility.EnumExtensions;
 using Hotline.ThirdAccountDomainServices.Interfaces;
 using Hotline.ThirdAccountDomainServices.Interfaces;
 using Hotline.Snapshot.IRepository;
 using Hotline.Snapshot.IRepository;
+using Hotline.Share.Enums.CallCenter;
+using Hotline.Repository.SqlSugar.Snapshot;
 
 
 namespace Hotline.Application.Snapshot;
 namespace Hotline.Application.Snapshot;
 
 
@@ -78,8 +80,9 @@ public abstract class SnapshotApplicationBase
     private readonly IInviteCodeRecordRepository _inviteCodeRecordRepository;
     private readonly IInviteCodeRecordRepository _inviteCodeRecordRepository;
     private readonly IInviteCodeRepository _inviteCodeRepository;
     private readonly IInviteCodeRepository _inviteCodeRepository;
     private readonly ICitizenRepository _citizenRepository;
     private readonly ICitizenRepository _citizenRepository;
+    private readonly ISnapshotPointsRecordRepository _pointsRecordRepository;
 
 
-    public SnapshotApplicationBase(IThirdIdentiyService thirdLoginService, IIndustryRepository industryRepository, ISnapshotBulletinRepository bulletinRepository, ISessionContext sessionContext, IRepository<RedPackRecord> redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IOrderSnapshotRepository orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISnapshotOrderPublishRepository snapshotOrderPublishRepository, IRepository<WorkflowTrace> workflowTraceRepository, IPractitionerRepository practitionerRepository, IRepository<SystemArea> systemAreaRepository, IVolunteerRepository volunteerRepository, IVolunteerReportRepository volunteerReportRepository, ISystemLogRepository systemLog, IGuiderSystemService guiderSystemService, ICapPublisher capPublisher, Publisher publisher, IFileDomainService fileDomainService, ICommunityInfoRepository communityInfoRepository, IRedPackAuditRepository redPackAuditRepository, IOrderVisitRepository orderVisitRepository, IOrderVisitDetailRepository orderVisitDetailRepository, IRedPackGuiderAuditRepository redPackGuiderAuditRepository, IInviteCodeRecordRepository inviteCodeRecordRepository, IInviteCodeRepository inviteCodeRepository, ICitizenRepository citizenRepository)
+    public SnapshotApplicationBase(IThirdIdentiyService thirdLoginService, IIndustryRepository industryRepository, ISnapshotBulletinRepository bulletinRepository, ISessionContext sessionContext, IRepository<RedPackRecord> redPackRecordRepository, IRepository<Order> orderRepository, IThirdAccountRepository thirdAccountRepository, IOrderSnapshotRepository orderSnapshotRepository, ISystemSettingCacheManager systemSettingCacheManager, ISystemAreaDomainService systemAreaDomainService, IFileRepository fileRepository, ISystemDicDataCacheManager systemDicDataCacheManager, ISnapshotOrderPublishRepository snapshotOrderPublishRepository, IRepository<WorkflowTrace> workflowTraceRepository, IPractitionerRepository practitionerRepository, IRepository<SystemArea> systemAreaRepository, IVolunteerRepository volunteerRepository, IVolunteerReportRepository volunteerReportRepository, ISystemLogRepository systemLog, IGuiderSystemService guiderSystemService, ICapPublisher capPublisher, Publisher publisher, IFileDomainService fileDomainService, ICommunityInfoRepository communityInfoRepository, IRedPackAuditRepository redPackAuditRepository, IOrderVisitRepository orderVisitRepository, IOrderVisitDetailRepository orderVisitDetailRepository, IRedPackGuiderAuditRepository redPackGuiderAuditRepository, IInviteCodeRecordRepository inviteCodeRecordRepository, IInviteCodeRepository inviteCodeRepository, ICitizenRepository citizenRepository, ISnapshotPointsRecordRepository snapshotPointsRecordRepository)
     {
     {
         _thirdLoginService = thirdLoginService;
         _thirdLoginService = thirdLoginService;
         _industryRepository = industryRepository;
         _industryRepository = industryRepository;
@@ -112,6 +115,7 @@ public abstract class SnapshotApplicationBase
         _inviteCodeRecordRepository = inviteCodeRecordRepository;
         _inviteCodeRecordRepository = inviteCodeRecordRepository;
         _inviteCodeRepository = inviteCodeRepository;
         _inviteCodeRepository = inviteCodeRepository;
         _citizenRepository = citizenRepository;
         _citizenRepository = citizenRepository;
+        _pointsRecordRepository = snapshotPointsRecordRepository;
     }
     }
 
 
     #region 小程序
     #region 小程序
@@ -204,10 +208,10 @@ public abstract class SnapshotApplicationBase
         if (indurstry.IndustryType == EIndustryType.Declare)
         if (indurstry.IndustryType == EIndustryType.Declare)
         {
         {
             outDto.AreaTree = (await _systemAreaDomainService.GetAreaTree(parentId: "510300")).Adapt<List<SystemAreaOutDto>>();
             outDto.AreaTree = (await _systemAreaDomainService.GetAreaTree(parentId: "510300")).Adapt<List<SystemAreaOutDto>>();
-            outDto.AreaTree.ToList().ForEach(m => 
+            outDto.AreaTree.ToList().ForEach(m =>
             {
             {
                 if (m.Children.IsNullOrEmpty())
                 if (m.Children.IsNullOrEmpty())
-                    m.Children = new List<SystemAreaOutDto>() { new SystemAreaOutDto { Id = "0",  AreaName = "无"} };
+                    m.Children = new List<SystemAreaOutDto>() { new SystemAreaOutDto { Id = "0", AreaName = "无" } };
             });
             });
             outDto.Files = (await _fileRepository.GetByKeyAsync(indurstry.Id, requestAborted)).Adapt<List<IndustryFileDto>>();
             outDto.Files = (await _fileRepository.GetByKeyAsync(indurstry.Id, requestAborted)).Adapt<List<IndustryFileDto>>();
             outDto.Files.ToList().ForEach(m => m.Url = fileDownloadApi + m.AdditionId);
             outDto.Files.ToList().ForEach(m => m.Url = fileDownloadApi + m.AdditionId);
@@ -349,6 +353,35 @@ public abstract class SnapshotApplicationBase
         return items;
         return items;
     }
     }
 
 
+    /// <summary>
+    /// 积分详情集合
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    public async Task<IList<PointItemsOutDto>> GetPointItemsAsync(PointItemsInDto dto, CancellationToken token)
+    {
+        var items = await _pointsRecordRepository.Queryable()
+            .Where(m => m.UserId == _sessionContext.UserId && dto.Direction == m.Direction)
+            .Select(m => new PointItemsOutDto(), true)
+            .OrderByDescending(m => m.CreationTime)
+            .ToFixedListAsync(dto, token);
+        return items;
+    }
+
+    /// <summary>
+    /// 积分总计
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="requestAborted"></param>
+    /// <returns></returns>
+    public async Task<int> GetPointsTotalAsync(PointItemsInDto dto, CancellationToken token)
+    {
+        return await _pointsRecordRepository.Queryable()
+            .Where(m => m.UserId == _sessionContext.UserId && dto.Direction == m.Direction)
+            .SumAsync(m => m.Points);
+    }
+
+
     /// <summary>
     /// <summary>
     /// 获取工单详情
     /// 获取工单详情
     /// </summary>
     /// </summary>
@@ -409,7 +442,7 @@ public abstract class SnapshotApplicationBase
     /// <param name="id"></param>
     /// <param name="id"></param>
     /// <returns></returns>
     /// <returns></returns>
     public async Task<IList<OrderVisitItemsOutDto>> GetOrderVisitDetailAsync(string id)
     public async Task<IList<OrderVisitItemsOutDto>> GetOrderVisitDetailAsync(string id)
-    { 
+    {
         var orderVisitId = await _orderVisitRepository.Queryable()
         var orderVisitId = await _orderVisitRepository.Queryable()
             .Where(m => m.OrderId == id)
             .Where(m => m.OrderId == id)
             .Select(m => m.Id)
             .Select(m => m.Id)
@@ -427,7 +460,7 @@ public abstract class SnapshotApplicationBase
         }
         }
         var org = orderVisitDetail.Where(m => m.VisitTarget == EVisitTarget.Org).First();
         var org = orderVisitDetail.Where(m => m.VisitTarget == EVisitTarget.Org).First();
         if (org != null)
         if (org != null)
-        { 
+        {
             if (org.OrgProcessingResults != null) item.OrgProcessingResults = org.OrgProcessingResults.Value;
             if (org.OrgProcessingResults != null) item.OrgProcessingResults = org.OrgProcessingResults.Value;
             if (org.OrgHandledAttitude != null) item.OrgHandledAttitude = org.OrgHandledAttitude.Value;
             if (org.OrgHandledAttitude != null) item.OrgHandledAttitude = org.OrgHandledAttitude.Value;
         }
         }
@@ -526,7 +559,7 @@ public abstract class SnapshotApplicationBase
     {
     {
         dto.ValidateObject();
         dto.ValidateObject();
         if (int.TryParse(dto.InvitationCode, out var invitationCode) == false)
         if (int.TryParse(dto.InvitationCode, out var invitationCode) == false)
-        { 
+        {
             throw new UserFriendlyException(200, "邀请码格式错误");
             throw new UserFriendlyException(200, "邀请码格式错误");
         }
         }
         var userInfo = await _citizenRepository.GetAsync(_sessionContext.UserId)
         var userInfo = await _citizenRepository.GetAsync(_sessionContext.UserId)
@@ -833,7 +866,7 @@ public abstract class SnapshotApplicationBase
     {
     {
         var order = await _orderRepository.Queryable()
         var order = await _orderRepository.Queryable()
             .Where(m => m.Id == orderId)
             .Where(m => m.Id == orderId)
-            .Select(m => new { m.Id, m.Status, m.No , m.FromPhone})
+            .Select(m => new { m.Id, m.Status, m.No, m.FromPhone })
             .FirstAsync(cancellationToken) ?? throw new UserFriendlyException($"{orderId} 工单不存在");
             .FirstAsync(cancellationToken) ?? throw new UserFriendlyException($"{orderId} 工单不存在");
         var snapshot = await _orderSnapshotRepository.GetAsync(orderId) ?? throw new UserFriendlyException("工单不存在");
         var snapshot = await _orderSnapshotRepository.GetAsync(orderId) ?? throw new UserFriendlyException("工单不存在");
         if (order.Status != EOrderStatus.Filed) return $"{order.No} 工单状态非 {EOrderStatus.Filed} 不处理;";
         if (order.Status != EOrderStatus.Filed) return $"{order.No} 工单状态非 {EOrderStatus.Filed} 不处理;";
@@ -901,4 +934,55 @@ public abstract class SnapshotApplicationBase
         await _bulletinRepository.UpdateAsync(bulletin);
         await _bulletinRepository.UpdateAsync(bulletin);
     }
     }
     #endregion
     #endregion
+
+    #region 积分
+    public async Task<PointsRankOutDto> GetPointsRankAsync()
+    {
+        var outDto = new PointsRankOutDto();
+        var record = await _pointsRecordRepository.Queryable()
+            .Where(m => m.UserId == _sessionContext.UserId)
+            .Select(m => new
+            {
+                Total = SqlFunc.AggregateSum(m.Points),
+                Out = SqlFunc.AggregateSum(SqlFunc.IIF(m.Direction == EPointsDirection.Out, m.Points, 0))
+            }).FirstAsync();
+        outDto.ValidPoints = record.Total - record.Out;
+        var startTime = new DateTime(DateTime.Now.Year, 1, 1, 0, 0, 0);
+        var endTime = new DateTime(DateTime.Now.Year, 12, 31, 23, 59, 59);
+        var query = _pointsRecordRepository.Queryable()
+            .LeftJoin<Citizen>((points, citizen) => points.UserId == citizen.Id)
+            .Where((points, citizen) => points.CreationTime >= startTime && points.CreationTime <= endTime)
+            .GroupBy((points, citizen) => new { citizen.Id, points.UserId, citizen.IsSecurityMax, citizen.Name, citizen.PhoneNumber })
+            .Select((points, citizen) => new PointsRankUserDto
+            {
+                IsSecurityMax = citizen.IsSecurityMax ?? false,
+                Rank = SqlFunc.MappingColumn<int>($@"
+            CASE 
+                WHEN citizen.""Id"" = '{_sessionContext.UserId}' THEN 1 
+                ELSE DENSE_RANK() OVER (ORDER BY SUM(CASE WHEN ""points"".""Direction"" = 1 THEN ""points"".""Points"" ELSE 0 END) DESC)
+            END"),
+                Points = SqlFunc.AggregateSum(points.Points),
+                UserName = citizen.Name!,
+                PhoneNumber = citizen.PhoneNumber,
+                CitizenId = citizen.Id,
+            }).MergeTable()
+            .OrderByDescending(points => points.Rank)
+            .Take(11);
+
+#if DEBUG
+        var sql = query.ToSqlString();
+#endif
+        var item = await query.ToListAsync();
+
+        item.ForEach(m =>
+        {
+            if (m.IsSecurityMax)
+                m.HeadUrl = _systemDicDataCacheManager.HeaderImages("aqws");
+            else
+                m.HeadUrl = _systemDicDataCacheManager.HeaderImages("default");
+        });
+        outDto.Ranks = item;
+        return outDto;
+    }
+    #endregion
 }
 }

+ 6 - 5
src/Hotline.Application/Snapshot/PointsRecordApplication.cs → src/Hotline.Application/Snapshot/SnapshotPointsApplication.cs

@@ -15,12 +15,12 @@ using XF.Domain.Dependency;
 
 
 namespace Hotline.Application.Snapshot;
 namespace Hotline.Application.Snapshot;
 
 
-public class PointsRecordApplication : IPointsRecordApplication, IScopeDependency
+public class SnapshotPointsApplication : ISnapshotPointsApplication, IScopeDependency
 {
 {
     private readonly ISnapshotPointsRecordRepository _snapshotPointsRecordRepository;
     private readonly ISnapshotPointsRecordRepository _snapshotPointsRecordRepository;
     private readonly ICitizenRepository _citizenRepository;
     private readonly ICitizenRepository _citizenRepository;
 
 
-    public PointsRecordApplication(ISnapshotPointsRecordRepository snapshotPointsRecordRepository, ICitizenRepository citizenRepository)
+    public SnapshotPointsApplication(ISnapshotPointsRecordRepository snapshotPointsRecordRepository, ICitizenRepository citizenRepository)
     {
     {
         _snapshotPointsRecordRepository = snapshotPointsRecordRepository;
         _snapshotPointsRecordRepository = snapshotPointsRecordRepository;
         _citizenRepository = citizenRepository;
         _citizenRepository = citizenRepository;
@@ -30,7 +30,7 @@ public class PointsRecordApplication : IPointsRecordApplication, IScopeDependenc
     {
     {
         var query = _snapshotPointsRecordRepository.Queryable()
         var query = _snapshotPointsRecordRepository.Queryable()
             .LeftJoin<Citizen>((points, citizen) => points.UserId == citizen.Id)
             .LeftJoin<Citizen>((points, citizen) => points.UserId == citizen.Id)
-            .WhereIF(dto.PhoneNumber.NotNullOrEmpty(), (points, citizen) => dto.PhoneNumber == citizen.PhoneNumber)
+            .WhereIF(dto.PhoneNumber.NotNullOrEmpty(), (points, citizen) => citizen.PhoneNumber.Contains(dto.PhoneNumber!))
             .Where((points, citizen) => points.CreationTime >= dto.StartTime && points.CreationTime <= dto.EndTime)
             .Where((points, citizen) => points.CreationTime >= dto.StartTime && points.CreationTime <= dto.EndTime)
             .GroupBy((points, citizen) => new { points.UserId, citizen.IsSecurityMax, citizen.Name, citizen.PhoneNumber })
             .GroupBy((points, citizen) => new { points.UserId, citizen.IsSecurityMax, citizen.Name, citizen.PhoneNumber })
             .Select((points, citizen) => new PointsItemsOutDto
             .Select((points, citizen) => new PointsItemsOutDto
@@ -41,8 +41,9 @@ public class PointsRecordApplication : IPointsRecordApplication, IScopeDependenc
                 OutPoints = SqlFunc.AggregateSum(SqlFunc.IIF(points.Direction == EPointsDirection.Out && points.Source == EPointsSource.Audit, points.Points, 0)),
                 OutPoints = SqlFunc.AggregateSum(SqlFunc.IIF(points.Direction == EPointsDirection.Out && points.Source == EPointsSource.Audit, points.Points, 0)),
                 TotalPoints = SqlFunc.AggregateSum(points.Points),
                 TotalPoints = SqlFunc.AggregateSum(points.Points),
                 InTotalPoint = SqlFunc.AggregateSum(SqlFunc.IIF(points.Direction == EPointsDirection.In, points.Points, 0)),
                 InTotalPoint = SqlFunc.AggregateSum(SqlFunc.IIF(points.Direction == EPointsDirection.In, points.Points, 0)),
-                UserName = citizen.Name,
-                PhoneNumber = citizen.PhoneNumber
+                UserName = citizen.Name!,
+                PhoneNumber = citizen.PhoneNumber,
+                UserId = points.UserId,
             })
             })
             .OrderByPropertyNameIF(dto.SortField.NotNullOrEmpty() && dto.SortRule == 0, dto.SortField, OrderByType.Desc)
             .OrderByPropertyNameIF(dto.SortField.NotNullOrEmpty() && dto.SortRule == 0, dto.SortField, OrderByType.Desc)
             .OrderByPropertyNameIF(dto.SortField.NotNullOrEmpty() && dto.SortRule == 1, dto.SortField, OrderByType.Asc);
             .OrderByPropertyNameIF(dto.SortField.NotNullOrEmpty() && dto.SortRule == 1, dto.SortField, OrderByType.Asc);

File diff suppressed because it is too large
+ 0 - 0
src/Hotline.Application/Snapshot/ZiGongSnapshotApplication.cs


+ 2 - 7
src/Hotline.Share/Dtos/Snapshot/OrderDto.cs

@@ -198,14 +198,9 @@ public class AddSnapshotOrderInDto : Position
         return $"{Description}";
         return $"{Description}";
     }
     }
 
 
-    public string GetTitle(EIndustryType industryType, string acceptType)
+    public string GetTitle(EIndustryType industryType, string titleSuffix)
     {
     {
-        if (industryType == EIndustryType.Declare)
-        {
-            return $"【随手拍】关于{Town}({County})的申报";
-        }
-
-        return $"【随手拍】关于{Town}({County})的" + acceptType;
+        return $"【随手拍】关于{Address}" + titleSuffix;
     }
     }
 }
 }
 
 

+ 101 - 1
src/Hotline.Share/Dtos/Snapshot/PointsDto.cs

@@ -1,4 +1,7 @@
-using Hotline.Share.Requests;
+using Hotline.Share.Enums.CallCenter;
+using Hotline.Share.Enums.Snapshot;
+using Hotline.Share.Requests;
+using Hotline.Share.Tools;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations;
@@ -6,6 +9,7 @@ using System.Linq;
 using System.Text;
 using System.Text;
 using System.Text.Json.Serialization;
 using System.Text.Json.Serialization;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using XF.Utility.EnumExtensions;
 
 
 namespace Hotline.Share.Dtos.Snapshot;
 namespace Hotline.Share.Dtos.Snapshot;
 
 
@@ -83,5 +87,101 @@ public class PointsItemsOutDto
     [JsonIgnore]
     [JsonIgnore]
     [Newtonsoft.Json.JsonIgnore]
     [Newtonsoft.Json.JsonIgnore]
     public int InTotalPoint { get; set; }
     public int InTotalPoint { get; set; }
+
+    /// <summary>
+    /// UserId
+    /// </summary>
+    public string UserId { get; set; }
+}
+
+
+public class PointsRankOutDto
+{
+    /// <summary>
+    /// 当前可用积分
+    /// </summary>
+    public int ValidPoints { get; set; }
+
+    /// <summary>
+    /// 排行
+    /// </summary>
+    public IList<PointsRankUserDto> Ranks { get; set; }
 }
 }
 
 
+public class PointsRankUserDto
+{
+    /// <summary>
+    /// 用户名
+    /// </summary>
+    public string UserName { get; set; }
+
+
+    private string _phoneNumber;
+    /// <summary>
+    /// 联系电话
+    /// </summary>
+    public string PhoneNumber
+    {
+        get
+        {
+            return _phoneNumber.MaskPhoneNumber();
+        }
+        set { _phoneNumber = value; }
+    }
+
+    /// <summary>
+    /// 排名
+    /// </summary>
+    public int Rank { get; set; }
+
+    /// <summary>
+    /// 积分
+    /// </summary>
+    public int Points { get; set; }
+
+    /// <summary>
+    /// UserId
+    /// </summary>
+    public string CitizenId { get; set; }
+
+    /// <summary>
+    /// 是否安全卫士
+    /// </summary>
+    public bool IsSecurityMax { get; set; }
+
+    /// <summary>
+    /// 头像地址
+    /// </summary>
+    public string HeadUrl { get; set; }
+}
+
+public class PointItemsInDto : QueryFixedDto
+{
+    /// <summary>
+    /// 收入或者支出
+    /// </summary>
+    public EPointsDirection Direction { get; set; }
+}
+
+public class PointItemsOutDto
+{
+    /// <summary>
+    /// 创建时间
+    /// </summary>
+    public DateTime CreationTime { get; set; }
+
+    /// <summary>
+    /// 积分来源
+    /// </summary>
+    public EPointsSource Source { get; set; }
+
+    /// <summary>
+    /// 积分来源
+    /// </summary>
+    public string SourceTxt => Source.GetDescription();
+
+    /// <summary>
+    /// 积分
+    /// </summary>
+    public int Points { get; set; }
+}

+ 1 - 0
src/Hotline.Share/Dtos/Snapshot/ThirdTokenDto.cs

@@ -102,3 +102,4 @@ public class SaveInvitationCodeInDto
     [Required]
     [Required]
     public string InvitationCode { get; set; }
     public string InvitationCode { get; set; }
 }
 }
+

+ 1 - 1
src/Hotline.Share/Tools/DataMaskExtensions.cs

@@ -23,7 +23,7 @@ public static class DataMaskExtensions
 
 
     public static string MaskPhoneNumber(this string original)
     public static string MaskPhoneNumber(this string original)
     {
     {
-        if (original.Length != 11) return string.Empty;
+        if (original.Length < 11) return string.Empty;
         return original.Mask(3, 4);
         return original.Mask(3, 4);
     }
     }
 
 

+ 7 - 0
src/Hotline/Caching/Interfaces/ISysDicDataCacheManager.cs

@@ -63,6 +63,13 @@ namespace Hotline.Caching.Interfaces
         /// <returns></returns>
         /// <returns></returns>
         SystemDicDataOutDto GetSnapshotBulletinType(string dicDataValue);
         SystemDicDataOutDto GetSnapshotBulletinType(string dicDataValue);
 
 
+        /// <summary>
+        /// 用户头像
+        /// </summary>
+        /// <param name="v"></param>
+        /// <returns></returns>
+        string HeaderImages(string name);
+
         /// <summary>
         /// <summary>
         /// 红包补充发放类型
         /// 红包补充发放类型
         /// </summary>
         /// </summary>

+ 19 - 0
src/Hotline/Caching/Services/SysDicDataCacheManager.cs

@@ -160,5 +160,24 @@ namespace Hotline.Caching.Services
             _cacheSysDicData.Remove(code);
             _cacheSysDicData.Remove(code);
         }
         }
 
 
+        /// <summary>
+        /// 获取用户头像图片
+        /// </summary>
+        /// <param name="name"></param>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        public string HeaderImages(string value)
+        {
+            var dto = GetOrAdd(SysDicTypeConsts.HeaderImages).Where(m => m.DicDataValue == value).FirstOrDefault() ?? new SystemDicDataOutDto();
+            if (dto.DicDataName == "LocalHeadImageDefault")
+            {
+                return SystemDicDataSeedData.LocalHeadImageDefault;
+            }
+            if (dto.DicDataName == "LocalHeadImageAQWS")
+            {
+                return SystemDicDataSeedData.LocalHeadImageAQWS;
+            }
+            return dto.DicDataName;
+        }
     }
     }
 }
 }

File diff suppressed because it is too large
+ 13 - 0
src/Hotline/SeedData/SystemDicDataSeedData.cs


+ 5 - 0
src/Hotline/Settings/SysDicTypeConsts.cs

@@ -332,6 +332,11 @@ public class SysDicTypeConsts
     /// </summary>
     /// </summary>
     public static string ExtraDeductionPointsType = "ExtraDeductionPointsType";
     public static string ExtraDeductionPointsType = "ExtraDeductionPointsType";
 
 
+    /// <summary>
+    /// 用户头像集合
+    /// </summary>
+    public static string HeaderImages = "HeaderImages";
+
     /// <summary>
     /// <summary>
     /// 政治身份
     /// 政治身份
     /// </summary>
     /// </summary>

+ 15 - 2
test/Hotline.Tests/Application/PointsRecordApplicationTest.cs

@@ -22,10 +22,12 @@ namespace Hotline.Tests.Application;
 
 
 public class PointsRecordApplicationTest : TestBase
 public class PointsRecordApplicationTest : TestBase
 {
 {
-    private readonly IPointsRecordApplication _pointsRecordApplication;
-    public PointsRecordApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, ITypedCache<SystemSetting> cacheSettingData, ThirdAccounSupplierFactory thirdAccountDomainFactory, IPointsRecordApplication pointsRecordApplication) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData, thirdAccountDomainFactory)
+    private readonly ISnapshotPointsApplication _pointsRecordApplication;
+    private readonly ISnapshotApplication _snapshotApplication;
+    public PointsRecordApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, ITypedCache<SystemSetting> cacheSettingData, ThirdAccounSupplierFactory thirdAccountDomainFactory, ISnapshotPointsApplication pointsRecordApplication, ISnapshotApplication snapshotApplication) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData, thirdAccountDomainFactory)
     {
     {
         _pointsRecordApplication = pointsRecordApplication;
         _pointsRecordApplication = pointsRecordApplication;
+        _snapshotApplication = snapshotApplication;
     }
     }
 
 
     [Fact]
     [Fact]
@@ -39,4 +41,15 @@ public class PointsRecordApplicationTest : TestBase
         var items = await _pointsRecordApplication.GetPointsItems(inDto).ToListAsync();
         var items = await _pointsRecordApplication.GetPointsItems(inDto).ToListAsync();
         items.ShouldNotBeNull();
         items.ShouldNotBeNull();
     }
     }
+
+    [Fact]
+    public async Task GetPointsRank_Test()
+    {
+        var item = await _snapshotApplication.GetPointsRankAsync();
+        item.ShouldNotBeNull();
+        foreach (var a in item.Ranks)
+        {
+            var s = a.PhoneNumber;
+        }
+    }
 }
 }

+ 10 - 0
test/Hotline.Tests/Application/SnapshotApplicationTest.cs

@@ -312,6 +312,16 @@ public class SnapshotApplicationTest : TestBase
         detail.Content.ShouldNotBeNullOrEmpty();
         detail.Content.ShouldNotBeNullOrEmpty();
     }
     }
 
 
+    [Fact]
+    public async Task GetPointsItems_Test()
+    {
+        SetWeiXin();
+        var items = await _snapshotApplication.GetPointItemsAsync(new PointItemsInDto(), CancellationToken.None);
+        items.ShouldNotBeNull();
+        var total = await _snapshotApplication.GetPointsTotalAsync(new PointItemsInDto(), CancellationToken.None);
+        total.ShouldNotBe(0);
+    }
+
     /// <summary>
     /// <summary>
     /// 红包列表记录
     /// 红包列表记录
     /// </summary>
     /// </summary>

Some files were not shown because too many files changed in this diff