From 8ac7e6487c592f0fece9aa5c1b68ba56745a974e Mon Sep 17 00:00:00 2001 From: zzh <1368735060@qq.com> Date: Sat, 11 Jul 2026 11:22:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E5=85=AC=E5=91=8A?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E6=8E=A5=E6=94=B6=E4=BA=BA=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E4=B8=8E=E5=AE=A2=E6=88=B7=E5=88=A0=E9=99=A4=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- .../Dtos/System/NoticeCreateInput.cs | 5 +- .../Services/Customers/CustomerService.cs | 47 ++++++++++++++++++ .../Services/System/NoticeService.cs | 48 ++++++++++++++----- 3 files changed, 85 insertions(+), 15 deletions(-) diff --git a/src/Oms.Application/Dtos/System/NoticeCreateInput.cs b/src/Oms.Application/Dtos/System/NoticeCreateInput.cs index f7b4503..c9742ac 100644 --- a/src/Oms.Application/Dtos/System/NoticeCreateInput.cs +++ b/src/Oms.Application/Dtos/System/NoticeCreateInput.cs @@ -15,11 +15,10 @@ public class NoticeCreateInput public string NoticeType { get; set; } = string.Empty; /// - /// 标题。 + /// 标题(公告必填;站内信可空)。 /// - [Required] [StringLength(128)] - public string Title { get; set; } = string.Empty; + public string? Title { get; set; } /// /// 正文内容。 diff --git a/src/Oms.Application/Services/Customers/CustomerService.cs b/src/Oms.Application/Services/Customers/CustomerService.cs index a4c8cb3..5af5acc 100644 --- a/src/Oms.Application/Services/Customers/CustomerService.cs +++ b/src/Oms.Application/Services/Customers/CustomerService.cs @@ -227,7 +227,54 @@ public class CustomerService : ApplicationService public async Task DeleteAsync(IdInput input) { var entity = await GetCustomerOrThrowAsync(input.Id); + + if (!entity.ParentCustomerId.HasValue + && await CustomerRepository.AnyAsync(x => x.ParentCustomerId == entity.Id)) + { + throw new BusinessException("存在子客户,请先删除子客户"); + } + await CustomerRepository.DeleteAsync(entity); + await DeleteLinkedRbacUserAsync(entity); + } + + private async Task DeleteLinkedRbacUserAsync(Customer entity) + { + var userGuid = await GetRbacUserGuidByMapIdAsync(entity.UserId); + if (userGuid.HasValue && userGuid.Value != Guid.Empty) + { + await UserService.DeleteAsync(userGuid.Value); + } + + if (entity.ParentCustomerId.HasValue) + { + await TryDeleteSubCustomerRoleAsync(entity.UserId); + } + } + + private async Task GetRbacUserGuidByMapIdAsync(int mapId) + { + return await RbacDbContext.Database.SqlQuery( + $"select `Id` as `Value` from `user` where `userid` = {mapId} and `IsDeleted` = 0") + .FirstOrDefaultAsync(); + } + + private async Task TryDeleteSubCustomerRoleAsync(int userId) + { + try + { + var roles = await RoleService.GetAllRolesAsync(); + var role = roles.FirstOrDefault(x => + string.Equals(x.Code, $"CustomerSub_{userId}", StringComparison.OrdinalIgnoreCase)); + if (role != null) + { + await RoleService.DeleteAsync(role.Id); + } + } + catch + { + // 子客户角色清理失败不阻断客户删除 + } } /// diff --git a/src/Oms.Application/Services/System/NoticeService.cs b/src/Oms.Application/Services/System/NoticeService.cs index 9393413..5b50b99 100644 --- a/src/Oms.Application/Services/System/NoticeService.cs +++ b/src/Oms.Application/Services/System/NoticeService.cs @@ -49,7 +49,17 @@ public class NoticeService : ApplicationService [HttpGet("/system/notice/list")] public async Task> GetListAsync([FromQuery] NoticeListInput input) { - var predicate = BuildListPredicate(input); + var receiverUserId = CurrentUser.GetId(); + if (receiverUserId <= 0) + { + return new OmsPageResult { Items = [], Total = 0 }; + } + + var expectedReceiverType = OmsSessionHelper.IsCustomerLogin(CurrentUser) + ? ReceiverTypeCustomer + : ReceiverTypeUser; + + var predicate = BuildListPredicate(input, receiverUserId, expectedReceiverType); var pageIndex = OmsDocHelper.NormalizePage(input.Page); var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize); var notices = await NoticeRepository.GetPagedListAsync( @@ -106,12 +116,13 @@ public class NoticeService : ApplicationService [HttpPost("/system/notice/create")] public async Task CreateAsync(NoticeCreateInput input) { - ValidateNoticeText(input.Title, input.Content); + var noticeType = NormalizeNoticeType(input.NoticeType); + ValidateNoticeText(noticeType, input.Title, input.Content); var receiverIds = await NormalizeAndValidateReceiverIdsAsync(input.ReceiverType, input.ReceiverIds); await NoticeRepository.InsertAsync(new Notice { - NoticeType = NormalizeNoticeType(input.NoticeType), - Title = input.Title.Trim(), + NoticeType = noticeType, + Title = NormalizeTitle(input.Title), Content = input.Content.Trim(), IsPopup = NormalizePopupValue(input.IsPopup), ReceiverType = NormalizeReceiverType(input.ReceiverType), @@ -126,10 +137,11 @@ public class NoticeService : ApplicationService public async Task UpdateAsync(NoticeUpdateInput input) { var entity = await GetNoticeOrThrowAsync(input.Id); - ValidateNoticeText(input.Title, input.Content); + var noticeType = NormalizeNoticeType(input.NoticeType); + ValidateNoticeText(noticeType, input.Title, input.Content); var receiverIds = await NormalizeAndValidateReceiverIdsAsync(input.ReceiverType, input.ReceiverIds); - entity.NoticeType = NormalizeNoticeType(input.NoticeType); - entity.Title = input.Title.Trim(); + entity.NoticeType = noticeType; + entity.Title = NormalizeTitle(input.Title); entity.Content = input.Content.Trim(); entity.IsPopup = NormalizePopupValue(input.IsPopup); entity.ReceiverType = NormalizeReceiverType(input.ReceiverType); @@ -162,7 +174,7 @@ public class NoticeService : ApplicationService { var notice = await GetNoticeOrThrowAsync(input.Id); var receiverIds = OmsDocHelper.DeserializeJson>(notice.ReceiverIds) ?? []; - var currentReceiverType = ReceiverTypeUser; + var currentReceiverType = NormalizeReceiverType(notice.ReceiverType); var currentReceiverId = CurrentUser.GetId(); if (currentReceiverId <= 0) { @@ -314,17 +326,26 @@ public class NoticeService : ApplicationService return result; } - private static Expression> BuildListPredicate(NoticeListInput input) + private static Expression> BuildListPredicate( + NoticeListInput input, + int receiverUserId, + string expectedReceiverType) { var noticeType = input.NoticeType?.Trim(); var receiverType = input.ReceiverType?.Trim(); var keyword = input.Keyword?.Trim(); + var receiverIdToken = receiverUserId.ToString(); return x => (string.IsNullOrWhiteSpace(noticeType) || x.NoticeType == noticeType) && (string.IsNullOrWhiteSpace(receiverType) || x.ReceiverType == receiverType) && (string.IsNullOrWhiteSpace(keyword) || x.Title.Contains(keyword) || - x.Content.Contains(keyword)); + x.Content.Contains(keyword)) && + x.ReceiverType == expectedReceiverType && + (x.ReceiverIds == $"[{receiverIdToken}]" || + x.ReceiverIds.StartsWith($"[{receiverIdToken},") || + x.ReceiverIds.Contains($",{receiverIdToken},") || + x.ReceiverIds.EndsWith($",{receiverIdToken}]")); } private async Task GetNoticeOrThrowAsync(int id) @@ -397,9 +418,9 @@ public class NoticeService : ApplicationService .ToListAsync(); } - private static void ValidateNoticeText(string title, string content) + private static void ValidateNoticeText(string noticeType, string? title, string content) { - if (string.IsNullOrWhiteSpace(title)) + if (noticeType == NoticeTypeNotice && string.IsNullOrWhiteSpace(title)) { throw new BusinessException("通知标题不能为空"); } @@ -410,6 +431,9 @@ public class NoticeService : ApplicationService } } + private static string NormalizeTitle(string? title) => + string.IsNullOrWhiteSpace(title) ? string.Empty : title.Trim(); + private static NoticeOutput MapNoticeOutput(Notice entity, int readCount, List receiverSelectionIds) { var receiverIds = OmsDocHelper.DeserializeJson>(entity.ReceiverIds) ?? [];