添加项目文件。
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
using GroupService.Domain.Enums;
|
||||
using GroupService.Domain.Events;
|
||||
using IM.DomainCommons;
|
||||
|
||||
namespace GroupService.Domain.Entities
|
||||
{
|
||||
public class Group : AggregateRootEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 群聊名称
|
||||
/// </summary>
|
||||
public string Name { get; private set; } = "新建群聊";
|
||||
|
||||
/// <summary>
|
||||
/// 群主
|
||||
/// </summary>
|
||||
public Guid GroupMaster { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 群权限
|
||||
/// (0:需管理员同意,1:任意人可加群,2:不允许任何人加入)
|
||||
/// </summary>
|
||||
public GroupAuthorityType Authority { get; private set; } = GroupAuthorityType.REQUIRE_CONSENT;
|
||||
|
||||
/// <summary>
|
||||
/// 全员禁言(false允许发言,true全员禁言)
|
||||
/// </summary>
|
||||
public bool AllMembersBanned { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 群聊状态
|
||||
/// (1:正常,2:封禁)
|
||||
/// </summary>
|
||||
public GroupState Status { get; private set; } = GroupState.Normal;
|
||||
|
||||
/// <summary>
|
||||
/// 群公告
|
||||
/// </summary>
|
||||
public string Announcement { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 群头像
|
||||
/// </summary>
|
||||
public string? Avatar { get; private set; } = "https://ts1.tc.mm.bing.net/th/id/OIP-C.XiB9NHwI57WPmotCbXuwawAAAA?rs=1&pid=ImgDetMain&o=7&rm=3";
|
||||
public long MaxSequenceId { get; private set; } = 0;
|
||||
public string LastMessage { get; private set; } = string.Empty;
|
||||
public string LastSenderName { get; private set; } = string.Empty;
|
||||
|
||||
private Group() { }
|
||||
|
||||
public Group(Guid groupMaster, string name = "新建群聊")
|
||||
{
|
||||
Name = name;
|
||||
GroupMaster = groupMaster;
|
||||
AddDomainEvent(new GroupCreateDomainEvent(this));
|
||||
}
|
||||
|
||||
public void setAllMembersBanned(bool isBanned)
|
||||
{
|
||||
if (isBanned == AllMembersBanned) return;
|
||||
|
||||
AllMembersBanned = isBanned;
|
||||
|
||||
AddDomainEvent(new AllMembersBannedDomainEvent(this));
|
||||
}
|
||||
|
||||
public void Ban()
|
||||
{
|
||||
Status = GroupState.Blocked;
|
||||
ModificationTime = DateTime.Now;
|
||||
AddDomainEvent(new GroupBlockedDomainEvent(this));
|
||||
}
|
||||
|
||||
public void Update(string? name, GroupAuthorityType? groupAuthority, string? announcement, string? avatar)
|
||||
{
|
||||
bool isChanged = false;
|
||||
if (name != null)
|
||||
{
|
||||
Name = name;
|
||||
isChanged = true;
|
||||
}
|
||||
|
||||
if (groupAuthority != null)
|
||||
{
|
||||
Authority = groupAuthority.Value;
|
||||
isChanged = true;
|
||||
}
|
||||
|
||||
if (announcement != null)
|
||||
{
|
||||
Announcement = announcement;
|
||||
isChanged = true;
|
||||
}
|
||||
if (avatar != null)
|
||||
{
|
||||
Avatar = avatar;
|
||||
isChanged = true;
|
||||
}
|
||||
|
||||
if (isChanged)
|
||||
{
|
||||
ModificationTime = DateTime.Now;
|
||||
AddDomainEvent(new GroupUpdateDomainEvent(this));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateLastMsg(long maxSequenceId, string lastMsg, string lastSenderName)
|
||||
{
|
||||
MaxSequenceId = maxSequenceId;
|
||||
LastMessage = lastMsg;
|
||||
LastSenderName = lastSenderName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using GroupService.Domain.Enums;
|
||||
using GroupService.Domain.Events;
|
||||
using GroupService.Domain.ValueObjects;
|
||||
using IM.DomainCommons;
|
||||
|
||||
namespace GroupService.Domain.Entities
|
||||
{
|
||||
public class GroupInvitation : AggregateRootEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 群聊编号
|
||||
/// </summary>
|
||||
public Guid GroupId { get; private set; }
|
||||
public GroupProfile GroupProfile { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 被邀请用户
|
||||
/// </summary>
|
||||
public Guid UserId { get; private set; }
|
||||
public UserProfile UserProfile { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 邀请用户
|
||||
/// </summary>
|
||||
public Guid OperatorId { get; private set; }
|
||||
public UserProfile OperatorProfile { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前状态(0:待被邀请人同意
|
||||
/// 1:被邀请人已同意)
|
||||
/// </summary>
|
||||
public GroupInvitationState State { get; private set; } = GroupInvitationState.Pending;
|
||||
|
||||
|
||||
private GroupInvitation() { }
|
||||
public GroupInvitation(Guid groupId, GroupProfile groupProfile, Guid userId, UserProfile userProfile, Guid operatorId, UserProfile operatorProfile)
|
||||
{
|
||||
GroupId = groupId;
|
||||
GroupProfile = groupProfile;
|
||||
UserId = userId;
|
||||
UserProfile = userProfile;
|
||||
OperatorId = operatorId;
|
||||
OperatorProfile = operatorProfile;
|
||||
AddDomainEvent(new GroupInvitationCreateDomainEvent(this));
|
||||
}
|
||||
|
||||
public void Accept()
|
||||
{
|
||||
if (State != GroupInvitationState.Pending) return;
|
||||
State = GroupInvitationState.Passed;
|
||||
ModificationTime = DateTime.Now;
|
||||
AddDomainEvent(new GroupInvitationAcceptDomainEvent(this));
|
||||
}
|
||||
|
||||
public void Reject()
|
||||
{
|
||||
if (State != GroupInvitationState.Pending) return;
|
||||
State = GroupInvitationState.Reject;
|
||||
ModificationTime = DateTime.Now;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using GroupService.Domain.Enums;
|
||||
using GroupService.Domain.Events;
|
||||
using GroupService.Domain.ValueObjects;
|
||||
using IM.DomainCommons;
|
||||
|
||||
namespace GroupService.Domain.Entities
|
||||
{
|
||||
public class GroupJoinRequest : AggregateRootEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 群聊编号
|
||||
///
|
||||
/// </summary>
|
||||
public Guid GroupId { get; private set; }
|
||||
public GroupProfile GroupProfile { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 申请人
|
||||
/// </summary>
|
||||
public Guid UserId { get; private set; }
|
||||
public UserProfile UserProfile { get; private set; }
|
||||
|
||||
public Guid? OperatorId { get; private set; }
|
||||
public string? OperatorName { get; private set; }
|
||||
public string? OperatorAvatar { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 申请状态(0:待管理员同意,1:已拒绝,2:已同意)
|
||||
/// </summary>
|
||||
public GroupJoinRequestState State { get; private set; } = GroupJoinRequestState.Pending;
|
||||
|
||||
/// <summary>
|
||||
/// 入群附言
|
||||
/// </summary>
|
||||
public string Description { get; private set; } = "申请入群";
|
||||
|
||||
private GroupJoinRequest() { }
|
||||
|
||||
public GroupJoinRequest(Guid userId, UserProfile user, Guid groupId, GroupProfile group, string? desc)
|
||||
{
|
||||
UserId = userId;
|
||||
GroupId = groupId;
|
||||
GroupProfile = group;
|
||||
UserProfile = user;
|
||||
if (desc is not null && desc.Length > 20)
|
||||
{
|
||||
throw new DomainException("入群描述不可超过20字符");
|
||||
}
|
||||
Description = desc ?? Description;
|
||||
}
|
||||
|
||||
public void Approve(Guid id, string nickName, string avatar)
|
||||
{
|
||||
if (State != GroupJoinRequestState.Pending) return;
|
||||
State = GroupJoinRequestState.Passed;
|
||||
OperatorAvatar = avatar;
|
||||
OperatorId = id;
|
||||
OperatorName = nickName;
|
||||
ModificationTime = DateTime.Now;
|
||||
AddDomainEvent(new GroupJoinRequestPassedDomainEvent(this));
|
||||
}
|
||||
|
||||
public void Decline(Guid id, string nickName, string avatar)
|
||||
{
|
||||
if (State != GroupJoinRequestState.Pending) return;
|
||||
State = GroupJoinRequestState.Declined;
|
||||
OperatorAvatar = avatar;
|
||||
OperatorId = id;
|
||||
OperatorName = nickName;
|
||||
ModificationTime = DateTime.Now;
|
||||
AddDomainEvent(new GroupJoinRequestDeclinedDomainEvent(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using GroupService.Domain.Enums;
|
||||
using GroupService.Domain.Events;
|
||||
using IM.DomainCommons;
|
||||
|
||||
namespace GroupService.Domain.Entities
|
||||
{
|
||||
public class GroupMember : AggregateRootEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户编号
|
||||
/// </summary>
|
||||
public Guid UserId { get; private set; }
|
||||
public string GroupNickName { get; private set; }
|
||||
public string? Avatar { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 群聊编号
|
||||
/// </summary>
|
||||
public Guid GroupId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 成员角色(0:普通成员,1:管理员,2:群主)
|
||||
/// </summary>
|
||||
public GroupMemberRole Role { get; private set; }
|
||||
|
||||
private GroupMember() { }
|
||||
|
||||
public GroupMember(Guid userId, Guid groupId, string groupNickname, string? avatar, GroupMemberRole role = GroupMemberRole.Normal)
|
||||
{
|
||||
UserId = userId;
|
||||
GroupId = groupId;
|
||||
Role = role;
|
||||
GroupNickName = groupNickname;
|
||||
Avatar = avatar;
|
||||
AddDomainEvent(new GroupMemberJoinedDomainEvent(this));
|
||||
}
|
||||
|
||||
public void UpdateRole(GroupMemberRole role)
|
||||
{
|
||||
if (role == Role) return;
|
||||
Role = role;
|
||||
}
|
||||
|
||||
public void UpdateAvatar(string avatar)
|
||||
{
|
||||
Avatar = avatar;
|
||||
}
|
||||
public void UpdateGroupNickname(string nickname)
|
||||
{
|
||||
GroupNickName = nickname;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace GroupService.Domain.Enums
|
||||
{
|
||||
public enum GroupAuthorityType
|
||||
{
|
||||
/// <summary>
|
||||
/// 需管理员同意
|
||||
/// </summary>
|
||||
REQUIRE_CONSENT = 0,
|
||||
/// <summary>
|
||||
/// 任何人可加入
|
||||
/// </summary>
|
||||
ANYONE_CAN_JOIN = 1,
|
||||
/// <summary>
|
||||
/// 不允许加入
|
||||
/// </summary>
|
||||
NOT_ALLOWED_TO_JOIN = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace GroupService.Domain.Enums
|
||||
{
|
||||
public enum GroupInvitationState
|
||||
{
|
||||
/// <summary>
|
||||
/// 待处理
|
||||
/// </summary>
|
||||
Pending = 0,
|
||||
/// <summary>
|
||||
/// 已同意
|
||||
/// </summary>
|
||||
Passed = 1,
|
||||
/// <summary>
|
||||
/// 拒绝
|
||||
/// </summary>
|
||||
Reject = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace GroupService.Domain.Enums
|
||||
{
|
||||
public enum GroupJoinRequestState
|
||||
{
|
||||
/// <summary>
|
||||
/// 待管理员处理
|
||||
/// </summary>
|
||||
Pending = 0,
|
||||
/// <summary>
|
||||
/// 已拒绝
|
||||
/// </summary>
|
||||
Declined = 1,
|
||||
/// <summary>
|
||||
/// 已同意
|
||||
/// </summary>
|
||||
Passed = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace GroupService.Domain.Enums
|
||||
{
|
||||
public enum GroupMemberRole
|
||||
{
|
||||
/// <summary>
|
||||
/// 普通成员
|
||||
/// </summary>
|
||||
Normal = 0,
|
||||
/// <summary>
|
||||
/// 管理员
|
||||
/// </summary>
|
||||
Administrator = 1,
|
||||
/// <summary>
|
||||
/// 群主
|
||||
/// </summary>
|
||||
Master = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace GroupService.Domain.Enums
|
||||
{
|
||||
public enum GroupState
|
||||
{
|
||||
/// <summary>
|
||||
/// 正常
|
||||
/// </summary>
|
||||
Normal = 1,
|
||||
/// <summary>
|
||||
/// 封禁
|
||||
/// </summary>
|
||||
Blocked = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using GroupService.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace GroupService.Domain.Events
|
||||
{
|
||||
public record AllMembersBannedDomainEvent(Group Group) : INotification;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using GroupService.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace GroupService.Domain.Events
|
||||
{
|
||||
public record GroupBlockedDomainEvent(Group Group) : INotification;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
using MediatR;
|
||||
|
||||
namespace GroupService.Domain.Events
|
||||
{
|
||||
public record GroupCreateDomainEvent(Domain.Entities.Group Group) : INotification;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using GroupService.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace GroupService.Domain.Events
|
||||
{
|
||||
public record GroupInvitationAcceptDomainEvent(GroupInvitation Invitation) : INotification;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using GroupService.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace GroupService.Domain.Events
|
||||
{
|
||||
public record GroupInvitationCreateDomainEvent(GroupInvitation Invitation) : INotification;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using GroupService.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace GroupService.Domain.Events
|
||||
{
|
||||
public record GroupJoinRequestDeclinedDomainEvent(GroupJoinRequest Request) : INotification;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using GroupService.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace GroupService.Domain.Events
|
||||
{
|
||||
public record GroupJoinRequestPassedDomainEvent(GroupJoinRequest Request) : INotification;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using GroupService.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace GroupService.Domain.Events
|
||||
{
|
||||
public record GroupMemberJoinedDomainEvent(GroupMember Member) : INotification;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using GroupService.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace GroupService.Domain.Events
|
||||
{
|
||||
public record GroupUpdateDomainEvent(Group Group) : INotification;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using GroupService.Domain.Entities;
|
||||
using GroupService.Domain.Enums;
|
||||
using GroupService.Domain.IReposities;
|
||||
using IM.Commons;
|
||||
|
||||
namespace GroupService.Domain
|
||||
{
|
||||
public class GroupMemberDomainService
|
||||
{
|
||||
private readonly IGroupMemberReposity reposity;
|
||||
|
||||
public GroupMemberDomainService(IGroupMemberReposity reposity)
|
||||
{
|
||||
this.reposity = reposity;
|
||||
}
|
||||
|
||||
public async Task<Result<GroupMember>> CreateAsync(
|
||||
Guid userId, Guid groupId, string nickName, string? avatar, GroupMemberRole role = GroupMemberRole.Normal)
|
||||
{
|
||||
var exist = await reposity.CheckMemberExistAsync(groupId, userId);
|
||||
if (exist)
|
||||
{
|
||||
return Result<GroupMember>.Fail(ResultCode.ALREADY_IN_GROUP);
|
||||
}
|
||||
var groupMember = new GroupMember(userId, groupId, nickName, avatar, role);
|
||||
groupMember = reposity.Create(groupMember);
|
||||
return Result<GroupMember>.Success(groupMember);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IM.Commons\IM.Commons.csproj" />
|
||||
<ProjectReference Include="..\DomainCommons\IM.DomainCommons.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
using GroupService.Domain.Entities;
|
||||
|
||||
namespace GroupService.Domain.IReposities
|
||||
{
|
||||
public interface IGroupInvitationReposity
|
||||
{
|
||||
void Create(GroupInvitation invitation);
|
||||
Task<GroupInvitation?> FindByIdAsync(Guid id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using GroupService.Domain.Entities;
|
||||
|
||||
namespace GroupService.Domain.IReposities
|
||||
{
|
||||
public interface IGroupMemberReposity
|
||||
{
|
||||
/// <summary>
|
||||
/// 通过群ID查询群成员
|
||||
/// </summary>
|
||||
/// <param name="groupId"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<GroupMember>> FindByGroupIdAsync(Guid groupId);
|
||||
/// <summary>
|
||||
/// 通过用户ID查询
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<GroupMember>> FindByUserIdAsync(Guid userId);
|
||||
/// <summary>
|
||||
/// 通过群ID和用户ID查询
|
||||
/// </summary>
|
||||
/// <param name="groupId"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
Task<GroupMember?> FindOneByGroupIdAndUserIdAsync(Guid groupId, Guid userId);
|
||||
/// <summary>
|
||||
/// 新增群成员
|
||||
/// </summary>
|
||||
/// <param name="member"></param>
|
||||
/// <returns></returns>
|
||||
GroupMember Create(GroupMember member);
|
||||
/// <summary>
|
||||
/// 检查成员是否存在
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns>存在返回true,否则返回false</returns>
|
||||
Task<bool> CheckMemberExistAsync(Guid groupId, Guid userId);
|
||||
Task<GroupMember?> FindByIdAsync(Guid id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using GroupService.Domain.Entities;
|
||||
|
||||
namespace GroupService.Domain.IReposities
|
||||
{
|
||||
public interface IGroupReposity
|
||||
{
|
||||
/// <summary>
|
||||
/// 通过群ID查询
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
Task<Group?> FindByIdAsync(Guid id);
|
||||
/// <summary>
|
||||
/// 通过群名查询
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<Group>> FindByNameAsync(string name);
|
||||
/// <summary>
|
||||
/// 通过群主ID查询
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<Group>> FindByMasterIdAsync(Guid userId);
|
||||
/// <summary>
|
||||
/// 创建群聊
|
||||
/// </summary>
|
||||
/// <param name="group"></param>
|
||||
/// <returns></returns>
|
||||
Group Create(Group group);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using GroupService.Domain.Entities;
|
||||
|
||||
namespace GroupService.Domain.IReposities
|
||||
{
|
||||
public interface IGroupRequestReposity
|
||||
{
|
||||
void Create(GroupJoinRequest request);
|
||||
Task<GroupJoinRequest> FindByIdAsync(Guid id);
|
||||
Task<IEnumerable<GroupJoinRequest?>> FindByGroupIdAsync(Guid groupId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace GroupService.Domain.ValueObjects
|
||||
{
|
||||
public class GroupProfile
|
||||
{
|
||||
public string GroupName { get; set; }
|
||||
public string Avatar { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace GroupService.Domain.ValueObjects
|
||||
{
|
||||
public class UserProfile
|
||||
{
|
||||
public string NickName { get; set; }
|
||||
public string? Avatar { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user