feat: 优化公告通知接收人过滤与客户删除同步

feat: 优化公告通知接收人过滤与客户删除同步
This commit is contained in:
biybuy 2026-07-11 11:23:55 +08:00 committed by GitHub
commit e15b4d4079
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 85 additions and 15 deletions

View File

@ -15,11 +15,10 @@ public class NoticeCreateInput
public string NoticeType { get; set; } = string.Empty;
/// <summary>
/// 标题。
/// 标题(公告必填;站内信可空)。
/// </summary>
[Required]
[StringLength(128)]
public string Title { get; set; } = string.Empty;
public string? Title { get; set; }
/// <summary>
/// 正文内容。

View File

@ -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<Guid?> GetRbacUserGuidByMapIdAsync(int mapId)
{
return await RbacDbContext.Database.SqlQuery<Guid?>(
$"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
{
// 子客户角色清理失败不阻断客户删除
}
}
/// <summary>

View File

@ -49,7 +49,17 @@ public class NoticeService : ApplicationService
[HttpGet("/system/notice/list")]
public async Task<OmsPageResult<NoticeOutput>> GetListAsync([FromQuery] NoticeListInput input)
{
var predicate = BuildListPredicate(input);
var receiverUserId = CurrentUser.GetId<int>();
if (receiverUserId <= 0)
{
return new OmsPageResult<NoticeOutput> { 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<List<int>>(notice.ReceiverIds) ?? [];
var currentReceiverType = ReceiverTypeUser;
var currentReceiverType = NormalizeReceiverType(notice.ReceiverType);
var currentReceiverId = CurrentUser.GetId<int>();
if (currentReceiverId <= 0)
{
@ -314,17 +326,26 @@ public class NoticeService : ApplicationService
return result;
}
private static Expression<Func<Notice, bool>> BuildListPredicate(NoticeListInput input)
private static Expression<Func<Notice, bool>> 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<Notice> 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<int> receiverSelectionIds)
{
var receiverIds = OmsDocHelper.DeserializeJson<List<int>>(entity.ReceiverIds) ?? [];