From 8a49331b43673731054ff2c5aebac215e30c3d8d Mon Sep 17 00:00:00 2001 From: cKey <35512826+colinin@users.noreply.github.com> Date: Tue, 2 Jun 2020 22:15:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84IM=E9=A1=B9=E7=9B=AE;?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=80=E4=BA=9B=E4=B8=8D=E5=90=88=E7=90=86?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.en.md | 14 +- README.md | 14 +- ...34027_Add-Chat-Message-Entites.Designer.cs | 494 ++++++++++++++++++ ...20200602134027_Add-Chat-Message-Entites.cs | 281 ++++++++++ ...iceHostMigrationsDbContextModelSnapshot.cs | 368 ++++++++++++- .../LINGYUN/Abp/IM/SignalR/Hubs/MessageHub.cs | 10 +- .../SignalR/Messages/SignalRMessageSender.cs | 72 +-- .../LINGYUN.Abp.IM/LINGYUN.Abp.IM.csproj | 2 +- .../LINGYUN/Abp/IM/Group/Group.cs | 26 + .../LINGYUN/Abp/IM/Group/GroupChat.cs | 8 - .../LINGYUN/Abp/IM/Group/IUserGroupStore.cs | 4 +- .../LINGYUN/Abp/IM/Group/UserGroup.cs | 2 + .../LINGYUN/Abp/IM/Messages/ChatMessage.cs | 18 +- .../LINGYUN/Abp/IM/Messages/IMessageStore.cs | 5 +- .../Abp/IM/Messages/MessageSendState.cs} | 4 +- .../Abp/Notifications/NotificationInfo.cs | 2 + .../Localization/Resources/en.json | 3 +- .../Localization/Resources/zh-Hans.json | 3 +- .../Clients/ClientAppService.cs | 9 +- .../MessageServiceErrorCodes.cs | 30 ++ .../Messages/ChatGroupConsts.cs | 15 + .../MessageService/Messages/MessageConsts.cs | 10 + .../Notifications/NotificationConsts.cs | 0 .../Subscriptions/SubscribeConsts.cs | 0 .../LINGYUN.Abp.MessageService.Domain.csproj | 11 + .../EventBus/UserCreateEventHandler.cs | 48 ++ .../Localization/Resources/en.json | 11 + .../Localization/Resources/zh-Hans.json | 11 + .../MessageServiceDomainAutoMapperProfile.cs | 26 +- .../Abp/MessageService/Messages/ChatGroup.cs | 76 +++ .../MessageService/Messages/ChatGroupAdmin.cs | 69 +++ .../MessageService/Messages/ChatMessage.cs | 30 -- .../MessageService/Messages/GroupChatBlack.cs | 32 ++ .../MessageService/Messages/GroupMessage.cs | 24 + .../Messages/IGroupRepository.cs | 22 + .../Messages/IMessageRepository.cs | 24 + .../Messages/IUserChatGroupRepository.cs | 25 + .../Messages/IUserChatSettingRepository.cs | 20 + .../Abp/MessageService/Messages/Message.cs | 50 ++ .../MessageService/Messages/MessageStore.cs | 132 +++++ .../MessageService/Messages/UserChatBlack.cs | 32 ++ .../MessageService/Messages/UserChatGroup.cs | 27 + .../Messages/UserChatSetting.cs | 54 ++ .../MessageService/Messages/UserGroupStore.cs | 86 +++ .../MessageService/Messages/UserMessage.cs | 25 + .../Messages/UserSpecialFocus.cs | 32 ++ ...MessageServiceEntityFrameworkCoreModule.cs | 7 +- ...ServiceDbContextModelCreatingExtensions.cs | 102 +++- .../Messages/EfCoreGroupRepository.cs | 43 ++ .../Messages/EfCoreMessageRepository.cs | 114 ++++ .../Messages/EfCoreUserChatGroupRepository.cs | 86 +++ .../EfCoreUserChatSettingRepository.cs | 39 ++ .../SettingManagement/SettingAppService.cs | 6 + vueJs/images/aggregate.png | Bin 0 -> 47986 bytes vueJs/images/client.png | Bin 0 -> 52915 bytes vueJs/images/im-notifications.png | Bin 0 -> 63710 bytes vueJs/images/tenant.png | Bin 0 -> 34253 bytes vueJs/src/components/TenantBox/index.vue | 3 +- 58 files changed, 2558 insertions(+), 103 deletions(-) create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.Designer.cs create mode 100644 aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/Group.cs delete mode 100644 aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/GroupChat.cs rename aspnet-core/modules/{message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/SendStatus.cs => common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageSendState.cs} (84%) create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceErrorCodes.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/ChatGroupConsts.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/MessageConsts.cs rename aspnet-core/modules/message/{LINGYUN.Abp.MessageService.Domain => LINGYUN.Abp.MessageService.Domain.Shared}/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs (100%) rename aspnet-core/modules/message/{LINGYUN.Abp.MessageService.Domain => LINGYUN.Abp.MessageService.Domain.Shared}/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs (100%) create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/UserCreateEventHandler.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/en.json create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/zh-Hans.json create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroup.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroupAdmin.cs delete mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupChatBlack.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupMessage.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IGroupRepository.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IMessageRepository.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatGroupRepository.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatSettingRepository.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/Message.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/MessageStore.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatBlack.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatGroup.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatSetting.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserGroupStore.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserMessage.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserSpecialFocus.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreGroupRepository.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreMessageRepository.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatGroupRepository.cs create mode 100644 aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatSettingRepository.cs create mode 100644 vueJs/images/aggregate.png create mode 100644 vueJs/images/client.png create mode 100644 vueJs/images/im-notifications.png create mode 100644 vueJs/images/tenant.png diff --git a/README.en.md b/README.en.md index 85dd66395..f4edfe568 100644 --- a/README.en.md +++ b/README.en.md @@ -41,7 +41,19 @@ If you want to get started with a minimal template code instead of integration s ## Screenshots -![dashboard](./demo/dashboard.png) +![Login](./vueJs/images/userLogin.png) + +![Tenants](./vueJs/images/tenant.png) + +![Roles](./vueJs/images/userRoles.png) + +![Permissions](./vueJs/images/userPermissions.png) + +![IM](./vueJs/images/im-notifications.png) + +![Clients](./vueJs/images/client.png) + +![Aggregate route](./vueJs/images/aggregate.png) ## Related Projects diff --git a/README.md b/README.md index f5b5cd661..7c4f53eac 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,19 @@ ## 截图 -![登录页](./images/userLogin.png) +![登录页](./vueJs/images/userLogin.png) -![角色页](./images/userRoles.png) +![租户管理](./vueJs/images/tenant.png) -![权限页](./images/userPermissions.png) +![角色页](./vueJs/images/userRoles.png) + +![权限页](./vueJs/images/userPermissions.png) + +![即时通讯](./vueJs/images/im-notifications.png) + +![客户端管理](./vueJs/images/client.png) + +![聚合路由](./vueJs/images/aggregate.png) ## 相关项目 diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.Designer.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.Designer.cs new file mode 100644 index 000000000..6b90f18d7 --- /dev/null +++ b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.Designer.cs @@ -0,0 +1,494 @@ +// +using System; +using LINGYUN.Abp.MessageService.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace LINGYUN.Abp.MessageService.Migrations +{ + [DbContext(typeof(MessageServiceHostMigrationsDbContext))] + [Migration("20200602134027_Add-Chat-Message-Entites")] + partial class AddChatMessageEntites + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Address") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("AllowAnonymous") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSendMessage") + .HasColumnType("tinyint(1)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime(6)"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("char(36)"); + + b.Property("MaxUserCount") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(20) CHARACTER SET utf8mb4") + .HasMaxLength(20); + + b.Property("Notice") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("Tag") + .HasColumnType("varchar(512) CHARACTER SET utf8mb4") + .HasMaxLength(512); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name"); + + b.ToTable("AppChatGroups"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroupAdmin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("AllowAddPeople") + .HasColumnType("tinyint(1)"); + + b.Property("AllowDissolveGroup") + .HasColumnType("tinyint(1)"); + + b.Property("AllowKickPeople") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSendNotice") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSilence") + .HasColumnType("tinyint(1)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("IsSuperAdmin") + .HasColumnType("tinyint(1)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)"); + + b.Property("LastModifierId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppChatGroupAdmins"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupChatBlack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("ShieldUserId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppGroupChatBlacks"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(1048576); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("SendState") + .HasColumnType("tinyint"); + + b.Property("SendUserName") + .IsRequired() + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppGroupMessages"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatBlack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("ShieldUserId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserChatBlacks"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId", "UserId"); + + b.ToTable("AppUserChatGroups"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("AllowAddFriend") + .HasColumnType("tinyint(1)"); + + b.Property("AllowAnonymous") + .HasColumnType("tinyint(1)"); + + b.Property("AllowReceiveMessage") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSendMessage") + .HasColumnType("tinyint(1)"); + + b.Property("RequireAddFriendValition") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserChatSettings"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(1048576); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("ReceiveUserId") + .HasColumnType("char(36)"); + + b.Property("SendState") + .HasColumnType("tinyint"); + + b.Property("SendUserName") + .IsRequired() + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ReceiveUserId"); + + b.ToTable("AppUserMessages"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserSpecialFocus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("FocusUserId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserSpecialFocuss"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("ExpirationTime") + .HasColumnType("datetime(6)"); + + b.Property("NotificationData") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(1048576); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("NotificationName") + .IsRequired() + .HasColumnType("varchar(100) CHARACTER SET utf8mb4") + .HasMaxLength(100); + + b.Property("NotificationTypeName") + .IsRequired() + .HasColumnType("varchar(512) CHARACTER SET utf8mb4") + .HasMaxLength(512); + + b.Property("Severity") + .HasColumnType("tinyint"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NotificationName"); + + b.ToTable("AppNotifications"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("NotificationId") + .HasColumnType("bigint"); + + b.Property("ReadStatus") + .HasColumnType("int"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId", "NotificationId") + .HasName("IX_Tenant_User_Notification_Id"); + + b.ToTable("AppUserNotifications"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Subscriptions.UserSubscribe", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("NotificationName") + .IsRequired() + .HasColumnType("varchar(100) CHARACTER SET utf8mb4") + .HasMaxLength(100); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId", "NotificationName") + .IsUnique() + .HasName("IX_Tenant_User_Notification_Name"); + + b.ToTable("AppUserSubscribes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.cs new file mode 100644 index 000000000..c11cb75b4 --- /dev/null +++ b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/20200602134027_Add-Chat-Message-Entites.cs @@ -0,0 +1,281 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace LINGYUN.Abp.MessageService.Migrations +{ + public partial class AddChatMessageEntites : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "ReadStatus", + table: "AppUserNotifications", + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint"); + + migrationBuilder.CreateTable( + name: "AppChatGroupAdmins", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + GroupId = table.Column(nullable: false), + UserId = table.Column(nullable: false), + IsSuperAdmin = table.Column(nullable: false), + AllowSilence = table.Column(nullable: false), + AllowKickPeople = table.Column(nullable: false), + AllowAddPeople = table.Column(nullable: false), + AllowSendNotice = table.Column(nullable: false), + AllowDissolveGroup = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppChatGroupAdmins", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppChatGroups", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + LastModificationTime = table.Column(nullable: true), + LastModifierId = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + GroupId = table.Column(nullable: false), + Name = table.Column(maxLength: 20, nullable: false), + Tag = table.Column(maxLength: 512, nullable: true), + Address = table.Column(maxLength: 256, nullable: true), + Notice = table.Column(maxLength: 64, nullable: true), + MaxUserCount = table.Column(nullable: false), + AllowAnonymous = table.Column(nullable: false), + AllowSendMessage = table.Column(nullable: false), + Description = table.Column(maxLength: 128, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppChatGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppGroupChatBlacks", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + GroupId = table.Column(nullable: false), + ShieldUserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppGroupChatBlacks", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppGroupMessages", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + MessageId = table.Column(nullable: false), + SendUserName = table.Column(maxLength: 64, nullable: false), + Content = table.Column(maxLength: 1048576, nullable: false), + Type = table.Column(nullable: false), + SendState = table.Column(nullable: false), + GroupId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppGroupMessages", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserChatBlacks", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + UserId = table.Column(nullable: false), + ShieldUserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserChatBlacks", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserChatGroups", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + UserId = table.Column(nullable: false), + GroupId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserChatGroups", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserChatSettings", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TenantId = table.Column(nullable: true), + UserId = table.Column(nullable: false), + AllowAnonymous = table.Column(nullable: false), + AllowAddFriend = table.Column(nullable: false), + RequireAddFriendValition = table.Column(nullable: false), + AllowReceiveMessage = table.Column(nullable: false), + AllowSendMessage = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserChatSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserMessages", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + MessageId = table.Column(nullable: false), + SendUserName = table.Column(maxLength: 64, nullable: false), + Content = table.Column(maxLength: 1048576, nullable: false), + Type = table.Column(nullable: false), + SendState = table.Column(nullable: false), + ReceiveUserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserMessages", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AppUserSpecialFocuss", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreationTime = table.Column(nullable: false), + CreatorId = table.Column(nullable: true), + TenantId = table.Column(nullable: true), + UserId = table.Column(nullable: false), + FocusUserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AppUserSpecialFocuss", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_AppChatGroupAdmins_TenantId_GroupId", + table: "AppChatGroupAdmins", + columns: new[] { "TenantId", "GroupId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppChatGroups_TenantId_Name", + table: "AppChatGroups", + columns: new[] { "TenantId", "Name" }); + + migrationBuilder.CreateIndex( + name: "IX_AppGroupChatBlacks_TenantId_GroupId", + table: "AppGroupChatBlacks", + columns: new[] { "TenantId", "GroupId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppGroupMessages_TenantId_GroupId", + table: "AppGroupMessages", + columns: new[] { "TenantId", "GroupId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserChatBlacks_TenantId_UserId", + table: "AppUserChatBlacks", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserChatGroups_TenantId_GroupId_UserId", + table: "AppUserChatGroups", + columns: new[] { "TenantId", "GroupId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserChatSettings_TenantId_UserId", + table: "AppUserChatSettings", + columns: new[] { "TenantId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserMessages_TenantId_ReceiveUserId", + table: "AppUserMessages", + columns: new[] { "TenantId", "ReceiveUserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppUserSpecialFocuss_TenantId_UserId", + table: "AppUserSpecialFocuss", + columns: new[] { "TenantId", "UserId" }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AppChatGroupAdmins"); + + migrationBuilder.DropTable( + name: "AppChatGroups"); + + migrationBuilder.DropTable( + name: "AppGroupChatBlacks"); + + migrationBuilder.DropTable( + name: "AppGroupMessages"); + + migrationBuilder.DropTable( + name: "AppUserChatBlacks"); + + migrationBuilder.DropTable( + name: "AppUserChatGroups"); + + migrationBuilder.DropTable( + name: "AppUserChatSettings"); + + migrationBuilder.DropTable( + name: "AppUserMessages"); + + migrationBuilder.DropTable( + name: "AppUserSpecialFocuss"); + + migrationBuilder.AlterColumn( + name: "ReadStatus", + table: "AppUserNotifications", + type: "tinyint", + nullable: false, + oldClrType: typeof(int)); + } + } +} diff --git a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs index 8e253493d..8704b41fc 100644 --- a/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs +++ b/aspnet-core/LINGYUN.Abp.MessageService.HttpApi.Host/Migrations/MessageServiceHostMigrationsDbContextModelSnapshot.cs @@ -17,6 +17,370 @@ namespace LINGYUN.Abp.MessageService.Migrations .HasAnnotation("ProductVersion", "3.1.3") .HasAnnotation("Relational:MaxIdentifierLength", 64); + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Address") + .HasColumnType("varchar(256) CHARACTER SET utf8mb4") + .HasMaxLength(256); + + b.Property("AllowAnonymous") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSendMessage") + .HasColumnType("tinyint(1)"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("char(36)"); + + b.Property("Description") + .HasColumnType("varchar(128) CHARACTER SET utf8mb4") + .HasMaxLength(128); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime") + .HasColumnType("datetime(6)"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId") + .HasColumnType("char(36)"); + + b.Property("MaxUserCount") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("varchar(20) CHARACTER SET utf8mb4") + .HasMaxLength(20); + + b.Property("Notice") + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("Tag") + .HasColumnType("varchar(512) CHARACTER SET utf8mb4") + .HasMaxLength(512); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name"); + + b.ToTable("AppChatGroups"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.ChatGroupAdmin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("AllowAddPeople") + .HasColumnType("tinyint(1)"); + + b.Property("AllowDissolveGroup") + .HasColumnType("tinyint(1)"); + + b.Property("AllowKickPeople") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSendNotice") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSilence") + .HasColumnType("tinyint(1)"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("IsSuperAdmin") + .HasColumnType("tinyint(1)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)"); + + b.Property("LastModifierId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppChatGroupAdmins"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupChatBlack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("ShieldUserId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppGroupChatBlacks"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.GroupMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(1048576); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("SendState") + .HasColumnType("tinyint"); + + b.Property("SendUserName") + .IsRequired() + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId"); + + b.ToTable("AppGroupMessages"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatBlack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("ShieldUserId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserChatBlacks"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnName("CreatorId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("bigint"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "GroupId", "UserId"); + + b.ToTable("AppUserChatGroups"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserChatSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("AllowAddFriend") + .HasColumnType("tinyint(1)"); + + b.Property("AllowAnonymous") + .HasColumnType("tinyint(1)"); + + b.Property("AllowReceiveMessage") + .HasColumnType("tinyint(1)"); + + b.Property("AllowSendMessage") + .HasColumnType("tinyint(1)"); + + b.Property("RequireAddFriendValition") + .HasColumnType("tinyint(1)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserChatSettings"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4") + .HasMaxLength(1048576); + + b.Property("CreationTime") + .HasColumnName("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("ReceiveUserId") + .HasColumnType("char(36)"); + + b.Property("SendState") + .HasColumnType("tinyint"); + + b.Property("SendUserName") + .IsRequired() + .HasColumnType("varchar(64) CHARACTER SET utf8mb4") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ReceiveUserId"); + + b.ToTable("AppUserMessages"); + }); + + modelBuilder.Entity("LINGYUN.Abp.MessageService.Messages.UserSpecialFocus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)"); + + b.Property("CreatorId") + .HasColumnType("char(36)"); + + b.Property("FocusUserId") + .HasColumnType("char(36)"); + + b.Property("TenantId") + .HasColumnName("TenantId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AppUserSpecialFocuss"); + }); + modelBuilder.Entity("LINGYUN.Abp.MessageService.Notifications.Notification", b => { b.Property("Id") @@ -74,8 +438,8 @@ namespace LINGYUN.Abp.MessageService.Migrations b.Property("NotificationId") .HasColumnType("bigint"); - b.Property("ReadStatus") - .HasColumnType("tinyint"); + b.Property("ReadStatus") + .HasColumnType("int"); b.Property("TenantId") .HasColumnName("TenantId") diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/MessageHub.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/MessageHub.cs index df413d9aa..9e4856d84 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/MessageHub.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/MessageHub.cs @@ -30,14 +30,14 @@ namespace LINGYUN.Abp.IM.SignalR.Hubs // 持久化 await _messageStore.StoreMessageAsync(chatMessage); - if (!chatMessage.GroupName.IsNullOrWhiteSpace()) + if (!chatMessage.GroupId.IsNullOrWhiteSpace()) { try { - var signalRClient = Clients.Group(chatMessage.GroupName); + var signalRClient = Clients.Group(chatMessage.GroupId); if (signalRClient == null) { - Logger.LogDebug("Can not get group " + chatMessage.GroupName + " from SignalR hub!"); + Logger.LogDebug("Can not get group " + chatMessage.GroupId + " from SignalR hub!"); return; } @@ -45,13 +45,13 @@ namespace LINGYUN.Abp.IM.SignalR.Hubs } catch (Exception ex) { - Logger.LogWarning("Could not send message to group: {0}", chatMessage.GroupName); + Logger.LogWarning("Could not send message to group: {0}", chatMessage.GroupId); Logger.LogWarning("Send group message error: {0}", ex.Message); } } else { - var onlineClientContext = new OnlineClientContext(chatMessage.TenantId, chatMessage.ToUserId); + var onlineClientContext = new OnlineClientContext(chatMessage.TenantId, chatMessage.ToUserId.GetValueOrDefault()); var onlineClients = OnlineClientManager.GetAllByContext(onlineClientContext); foreach (var onlineClient in onlineClients) { diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Messages/SignalRMessageSender.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Messages/SignalRMessageSender.cs index 069d5f199..380c90669 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Messages/SignalRMessageSender.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Messages/SignalRMessageSender.cs @@ -41,47 +41,59 @@ namespace LINGYUN.Abp.IM.SignalR.Messages // 持久化 await _messageStore.StoreMessageAsync(chatMessage); - if (!chatMessage.GroupName.IsNullOrWhiteSpace()) + try + { + if (!chatMessage.GroupId.IsNullOrWhiteSpace()) + { + await SendMessageToGroupAsync(chatMessage); + } + else + { + await SendMessageToUserAsync(chatMessage); + } + } + catch (Exception ex) + { + Logger.LogWarning("Could not send message, group: {0}, formUser: {1}, toUser: {2}", + chatMessage.GroupId, chatMessage.FormUserName, + chatMessage.ToUserId.HasValue ? chatMessage.ToUserId.ToString() : "None"); + Logger.LogWarning("Send group message error: {0}", ex.Message); + } + } + + protected virtual async Task SendMessageToGroupAsync(ChatMessage chatMessage) + { + var signalRClient = _hubContext.Clients.Group(chatMessage.GroupId); + if (signalRClient == null) + { + Logger.LogDebug("Can not get group " + chatMessage.GroupId + " from SignalR hub!"); + return; + } + + await signalRClient.SendAsync("getChatMessage", chatMessage); + } + + protected virtual async Task SendMessageToUserAsync(ChatMessage chatMessage) + { + var onlineClientContext = new OnlineClientContext(chatMessage.TenantId, chatMessage.ToUserId.Value); + var onlineClients = _onlineClientManager.GetAllByContext(onlineClientContext); + foreach (var onlineClient in onlineClients) { try { - var signalRClient = _hubContext.Clients.Group(chatMessage.GroupName); + var signalRClient = _hubContext.Clients.Client(onlineClient.ConnectionId); if (signalRClient == null) { - Logger.LogDebug("Can not get group " + chatMessage.GroupName + " from SignalR hub!"); - return; + Logger.LogDebug("Can not get user " + onlineClientContext.UserId + " with connectionId " + onlineClient.ConnectionId + " from SignalR hub!"); + continue; } await signalRClient.SendAsync("getChatMessage", chatMessage); } catch (Exception ex) { - Logger.LogWarning("Could not send message to group: {0}", chatMessage.GroupName); - Logger.LogWarning("Send group message error: {0}", ex.Message); - } - } - else - { - var onlineClientContext = new OnlineClientContext(chatMessage.TenantId, chatMessage.ToUserId); - var onlineClients = _onlineClientManager.GetAllByContext(onlineClientContext); - foreach (var onlineClient in onlineClients) - { - try - { - var signalRClient = _hubContext.Clients.Client(onlineClient.ConnectionId); - if (signalRClient == null) - { - Logger.LogDebug("Can not get user " + onlineClientContext.UserId + " with connectionId " + onlineClient.ConnectionId + " from SignalR hub!"); - continue; - } - - await signalRClient.SendAsync("getChatMessage", chatMessage); - } - catch (Exception ex) - { - Logger.LogWarning("Could not send message to user: {0}", chatMessage.ToUserId); - Logger.LogWarning("Send to user message error: {0}", ex.Message); - } + Logger.LogWarning("Could not send message to user: {0}", chatMessage.ToUserId); + Logger.LogWarning("Send to user message error: {0}", ex.Message); } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN.Abp.IM.csproj b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN.Abp.IM.csproj index 76ce15181..db4635ca9 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN.Abp.IM.csproj +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN.Abp.IM.csproj @@ -6,7 +6,7 @@ - + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/Group.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/Group.cs new file mode 100644 index 000000000..4618778ab --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/Group.cs @@ -0,0 +1,26 @@ +namespace LINGYUN.Abp.IM.Group +{ + public class Group + { + /// + /// 群组名称 + /// + public string Name { get; set; } + /// + /// 允许匿名聊天 + /// + public bool AllowAnonymous { get; set; } + /// + /// 允许发送消息 + /// + public bool AllowSendMessage { get; set; } + /// + /// 最大用户数 + /// + public int MaxUserLength { get; set; } + /// + /// 群组用户数 + /// + public int GroupUserCount { get; set; } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/GroupChat.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/GroupChat.cs deleted file mode 100644 index 4927ae723..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/GroupChat.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace LINGYUN.Abp.IM.Group -{ - public class GroupChat - { - public string Name { get; set; } - public int MaxUserLength { get; set; } - } -} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/IUserGroupStore.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/IUserGroupStore.cs index 800ca41b6..85f5f620e 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/IUserGroupStore.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/IUserGroupStore.cs @@ -12,7 +12,7 @@ namespace LINGYUN.Abp.IM.Group /// /// /// - Task> GetUserGroupsAsync(Guid? tenantId, Guid userId); + Task> GetUserGroupsAsync(Guid? tenantId, Guid userId); /// /// 获取通讯组所有用户 /// @@ -27,7 +27,7 @@ namespace LINGYUN.Abp.IM.Group /// /// /// - Task AddUserToGroupAsync(Guid? tenantId, Guid userId, long groupId); + Task AddUserToGroupAsync(Guid? tenantId, Guid userId, long groupId, Guid acceptUserId); /// /// 用户退出通讯组 /// diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/UserGroup.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/UserGroup.cs index d008896d5..120b13aa0 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/UserGroup.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Group/UserGroup.cs @@ -7,5 +7,7 @@ namespace LINGYUN.Abp.IM.Group public Guid? TenantId { get; set; } public Guid UserId { get; set; } public long GroupId { get; set; } + public bool IsAdmin { get; set; } + public bool IsSuperAdmin { get; set; } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/ChatMessage.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/ChatMessage.cs index 33f9c7624..e5b51f37e 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/ChatMessage.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/ChatMessage.cs @@ -1,15 +1,29 @@ using System; +using Volo.Abp.Auditing; namespace LINGYUN.Abp.IM.Messages { public class ChatMessage { public Guid? TenantId { get; set; } - public string GroupName { get; set; } + + public string GroupId { get; set; } + + public string MessageId { get; set; } + public Guid FormUserId { get; set; } - public Guid ToUserId { get; set; } + + public string FormUserName { get; set; } + + public Guid? ToUserId { get; set; } + + [DisableAuditing] public string Content { get; set; } + public DateTime SendTime { get; set; } + + public bool IsAnonymous { get; set; } = false; + public MessageType MessageType { get; set; } = MessageType.Text; } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageStore.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageStore.cs index 7ca433a90..b8be51000 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageStore.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/IMessageStore.cs @@ -21,7 +21,7 @@ namespace LINGYUN.Abp.IM.Messages /// /// /// - Task> GetGroupMessageAsync(Guid tenantId, string groupName, int maxResultCount = 10); + Task> GetGroupMessageAsync(Guid? tenantId, long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10); /// /// 获取与某个用户的聊天记录 /// @@ -29,6 +29,7 @@ namespace LINGYUN.Abp.IM.Messages /// /// /// - Task> GetChatMessageAsync(Guid tenantId, Guid userId, int maxResultCount = 10); + Task> GetChatMessageAsync(Guid? tenantId, Guid sendUserId, Guid receiveUserId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10); + } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/SendStatus.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageSendState.cs similarity index 84% rename from aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/SendStatus.cs rename to aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageSendState.cs index 7795118ab..3fbbfafe1 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/SendStatus.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM/LINGYUN/Abp/IM/Messages/MessageSendState.cs @@ -1,9 +1,9 @@ -namespace LINGYUN.Abp.MessageService +namespace LINGYUN.Abp.IM.Messages { /// /// 消息状态 /// - public enum SendStatus : sbyte + public enum MessageSendState : sbyte { /// /// 已发送 diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs index 62c39d11b..6b0b5bc98 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/NotificationInfo.cs @@ -18,6 +18,8 @@ namespace LINGYUN.Abp.Notifications Data = new NotificationData(); NotificationType = NotificationType.Application; NotificationSeverity = NotificationSeverity.Info; + + CreationTime = DateTime.Now; } } } diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json index 81c9ce62b..2b174ebd2 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/en.json @@ -25,6 +25,7 @@ "ClientClaimNotFound": "Client claim: {0} not found!", "ClientSecretNotFound": "Client secret: {0} not found!", "ClientPropertyNotFound": "Client property: {0} not found!", - "IdentityResourcePropertyNotFound": "Identity resource property: {0} not found!" + "IdentityResourcePropertyNotFound": "Identity resource property: {0} not found!", + "EncryptionNotImplemented": "Encryption type: {0} not implemented!" } } \ No newline at end of file diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json index db3ae18ee..9b2fe7010 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application.Contracts/LINGYUN/Abp/IdentityServer/Localization/Resources/zh-Hans.json @@ -25,6 +25,7 @@ "ClientClaimNotFound": "客户端声明: {0} 不存在!", "ClientSecretNotFound": "客户端密钥: {0} 不存在!", "ClientPropertyNotFound": "客户端属性: {0} 不存在!", - "IdentityResourcePropertyNotFound": "身份资源属性: {0} 不存在!" + "IdentityResourcePropertyNotFound": "身份资源属性: {0} 不存在!", + "EncryptionNotImplemented": "加密类型: {0} 未实现!" } } \ No newline at end of file diff --git a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs index 8dd96466d..455c83798 100644 --- a/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs +++ b/aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.Application/LINGYUN/Abp/IdentityServer/Clients/ClientAppService.cs @@ -7,7 +7,6 @@ using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Application.Dtos; using Volo.Abp.IdentityServer.Clients; -using Volo.Abp.Security.Encryption; using Client = Volo.Abp.IdentityServer.Clients.Client; namespace LINGYUN.Abp.IdentityServer.Clients @@ -15,9 +14,6 @@ namespace LINGYUN.Abp.IdentityServer.Clients [Authorize(AbpIdentityServerPermissions.Clients.Default)] public class ClientAppService : AbpIdentityServerAppServiceBase, IClientAppService { - private IStringEncryptionService _encryptionService; - protected IStringEncryptionService EncryptionService => LazyGetRequiredService(ref _encryptionService); - protected IClientRepository ClientRepository { get; } public ClientAppService(IClientRepository clientRepository) @@ -69,7 +65,8 @@ namespace LINGYUN.Abp.IdentityServer.Clients } else { - clientSecretValue = EncryptionService.Encrypt(clientSecretCreate.Value); + // 其他类型的服务器加密方式暂时不提供 + throw new UserFriendlyException(L["EncryptionNotImplemented", clientSecretCreate.Type]); } client.AddSecret(clientSecretValue, clientSecretCreate.Expiration, clientSecretCreate.Type, clientSecretCreate.Description); @@ -461,7 +458,7 @@ namespace LINGYUN.Abp.IdentityServer.Clients } else { - clientSecretValue = EncryptionService.Encrypt(clientSecretUpdate.Value); + throw new UserFriendlyException(L["EncryptionNotImplemented", clientSecretUpdate.Type]); } clientSecret.Value = clientSecretValue; diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceErrorCodes.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceErrorCodes.cs new file mode 100644 index 000000000..0ddb5ae88 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/MessageServiceErrorCodes.cs @@ -0,0 +1,30 @@ +namespace LINGYUN.Abp.MessageService +{ + public class MessageServiceErrorCodes + { + /// + /// 管理员已开启全员禁言 + /// + public const string GroupNotAllowedToSpeak = "Messages:Group:1001"; + /// + /// 管理员不允许匿名发言 + /// + public const string GroupNotAllowedToSpeakAnonymously = "Messages:Group:1002"; + /// + /// 管理员已禁止用户发言 + /// + public const string GroupUserHasBlack = "Messages:Group:1003"; + /// + /// 用户已将发信人拉黑 + /// + public const string UserHasBlack = "Messages:User:1003"; + /// + /// 用户已拒接所有消息 + /// + public const string UserHasRejectAllMessage = "Messages:User:1001"; + /// + /// 用户不允许匿名发言 + /// + public const string UserNotAllowedToSpeakAnonymously = "Messages:User:1002"; + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/ChatGroupConsts.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/ChatGroupConsts.cs new file mode 100644 index 000000000..7c015a16c --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/ChatGroupConsts.cs @@ -0,0 +1,15 @@ +namespace LINGYUN.Abp.MessageService.Messages +{ + public class ChatGroupConsts + { + public const int MaxNameLength = 20; + + public const int MaxTagLength = 512; + + public const int MaxAddressLength = 256; + + public const int MaxNoticeLength = 64; + + public const int MaxDescriptionLength = 128; + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/MessageConsts.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/MessageConsts.cs new file mode 100644 index 000000000..6708d9bfa --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Messages/MessageConsts.cs @@ -0,0 +1,10 @@ +namespace LINGYUN.Abp.MessageService.Messages +{ + public class MessageConsts + { + public const int MaxSendUserNameLength = 64; + + // 1 MB + public const int MaxContentLength = 1024 * 1024; + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs similarity index 100% rename from aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs rename to aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Notifications/NotificationConsts.cs diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs similarity index 100% rename from aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs rename to aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain.Shared/LINGYUN/Abp/MessageService/Subscriptions/SubscribeConsts.cs diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj index 4ca8aa840..30ef08749 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN.Abp.MessageService.Domain.csproj @@ -5,10 +5,21 @@ + + + + + + + + + + + diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/UserCreateEventHandler.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/UserCreateEventHandler.cs new file mode 100644 index 000000000..30e0cead3 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/EventBus/UserCreateEventHandler.cs @@ -0,0 +1,48 @@ +using LINGYUN.Abp.MessageService.Messages; +using System.Threading.Tasks; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; +using Volo.Abp.Users; + +namespace LINGYUN.Abp.MessageService.EventBus +{ + public class UserCreateEventHandler : IDistributedEventHandler> + { + private readonly ICurrentTenant _currentTenant; + private readonly IUnitOfWorkManager _unitOfWorkManager; + private readonly IUserChatSettingRepository _userChatSettingRepository; + public UserCreateEventHandler( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + IUserChatSettingRepository userChatSettingRepository) + { + _currentTenant = currentTenant; + _unitOfWorkManager = unitOfWorkManager; + _userChatSettingRepository = userChatSettingRepository; + } + /// + /// 接收添加用户事件,启用IM模块时增加用户配置 + /// + /// + /// + public async Task HandleEventAsync(EntityCreatedEto eventData) + { + using (var unitOfWork = _unitOfWorkManager.Begin()) + { + using (_currentTenant.Change(eventData.Entity.TenantId)) + { + var userHasOpendIm = await _userChatSettingRepository.UserHasOpendImAsync(eventData.Entity.Id); + if (!userHasOpendIm) + { + var userChatSetting = new UserChatSetting(eventData.Entity.Id, eventData.Entity.TenantId); + await _userChatSettingRepository.InsertAsync(userChatSetting); + + await unitOfWork.SaveChangesAsync(); + } + } + } + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/en.json b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/en.json new file mode 100644 index 000000000..948b35c47 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/en.json @@ -0,0 +1,11 @@ +{ + "culture": "en", + "texts": { + "Messages:Group:1001": "The current group is not allowed to speak", + "Messages:Group:1002": "The current group is not allowed to speak anonymously", + "Messages:Group:1003": "The administrator has banned you from speaking!", + "Messages:User:1001": "Users do not receive anonymous comments!", + "Messages:User:1002": "The user has rejected all messages!", + "Messages:User:1003": "The user rejects the message you sent!" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/zh-Hans.json b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..0041a0ce4 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Localization/Resources/zh-Hans.json @@ -0,0 +1,11 @@ +{ + "culture": "zh-Hans", + "texts": { + "Messages:Group:1001": "管理员已开启全员禁言!", + "Messages:Group:1002": "管理员不允许匿名发言!", + "Messages:Group:1003": "管理员已禁止您发言!", + "Messages:User:1001": "用户不接收匿名发言!", + "Messages:User:1002": "用户已拒接所有消息!", + "Messages:User:1003": "用户拒绝您发送的消息!" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Mapper/MessageServiceDomainAutoMapperProfile.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Mapper/MessageServiceDomainAutoMapperProfile.cs index f49e6d8a3..631b50e39 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Mapper/MessageServiceDomainAutoMapperProfile.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Mapper/MessageServiceDomainAutoMapperProfile.cs @@ -1,11 +1,11 @@ using AutoMapper; +using LINGYUN.Abp.IM.Messages; +using LINGYUN.Abp.MessageService.Messages; using LINGYUN.Abp.MessageService.Notifications; using LINGYUN.Abp.MessageService.Subscriptions; using LINGYUN.Abp.Notifications; using Newtonsoft.Json; using System; -using System.Collections.Generic; -using System.Text; namespace LINGYUN.Abp.MessageService.Mapper { @@ -30,6 +30,28 @@ namespace LINGYUN.Abp.MessageService.Mapper })); CreateMap(); + + CreateMap() + .ForMember(dto => dto.Content, map => map.MapFrom(src => src.Content)) + .ForMember(dto => dto.GroupId, map => map.MapFrom(src => src.GroupId.ToString())) + .ForMember(dto => dto.MessageId, map => map.MapFrom(src => src.MessageId.ToString())) + .ForMember(dto => dto.FormUserId, map => map.MapFrom(src => src.CreatorId)) + .ForMember(dto => dto.FormUserName, map => map.MapFrom(src => src.SendUserName)) + .ForMember(dto => dto.SendTime, map => map.MapFrom(src => src.CreationTime)) + .ForMember(dto => dto.MessageType, map => map.MapFrom(src => src.Type)) + .ForMember(dto => dto.IsAnonymous, map => map.Ignore()) + .ForMember(dto => dto.ToUserId, map => map.Ignore()); + + CreateMap() + .ForMember(dto => dto.Content, map => map.MapFrom(src => src.Content)) + .ForMember(dto => dto.ToUserId, map => map.MapFrom(src => src.ReceiveUserId)) + .ForMember(dto => dto.MessageId, map => map.MapFrom(src => src.MessageId.ToString())) + .ForMember(dto => dto.FormUserId, map => map.MapFrom(src => src.CreatorId)) + .ForMember(dto => dto.FormUserName, map => map.MapFrom(src => src.SendUserName)) + .ForMember(dto => dto.SendTime, map => map.MapFrom(src => src.CreationTime)) + .ForMember(dto => dto.MessageType, map => map.MapFrom(src => src.Type)) + .ForMember(dto => dto.IsAnonymous, map => map.Ignore()) + .ForMember(dto => dto.GroupId, map => map.Ignore()); } } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroup.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroup.cs new file mode 100644 index 000000000..defe140e0 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroup.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MessageService.Messages +{ + /// + /// 聊天群组 + /// + public class ChatGroup : AuditedEntity, IMultiTenant + { + /// + /// 租户 + /// + public virtual Guid? TenantId { get; protected set; } + /// + /// 群组标识 + /// + public virtual long GroupId { get; protected set; } + /// + /// 群组名称 + /// + public virtual string Name { get; protected set; } + /// + /// 群组标记 + /// + public virtual string Tag { get; protected set; } + /// + /// 群组地址 + /// + public virtual string Address { get; protected set; } + /// + /// 群组公告 + /// + public virtual string Notice { get; protected set; } + /// + /// 最大用户数量 + /// + public virtual int MaxUserCount { get; protected set; } + /// + /// 允许匿名聊天 + /// + public virtual bool AllowAnonymous { get; set; } + /// + /// 允许发送消息 + /// + public virtual bool AllowSendMessage { get; set; } + /// + /// 群组说明 + /// + public virtual string Description { get; set; } + protected ChatGroup() + { + } + public ChatGroup(long id, string name, string tag = "", string address = "", int maxUserCount = 200) + { + GroupId = id; + Name = name; + Tag = tag; + Address = address; + MaxUserCount = maxUserCount; + } + + public void ChangeAddress(string address) + { + Address = address; + } + + public void SetNotice(string notice) + { + Notice = notice; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroupAdmin.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroupAdmin.cs new file mode 100644 index 000000000..6c31cff0f --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatGroupAdmin.cs @@ -0,0 +1,69 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MessageService.Messages +{ + /// + /// 群管理员 + /// + public class ChatGroupAdmin : AuditedEntity, IMultiTenant + { + /// + /// 租户 + /// + public virtual Guid? TenantId { get; protected set; } + /// + /// 群组标识 + /// + public virtual long GroupId { get; protected set; } + /// + /// 管理员用户 + /// + public virtual Guid UserId { get; protected set; } + /// + /// 是否群主 + /// + public virtual bool IsSuperAdmin { get; protected set; } + /// + /// 允许禁言 + /// + public virtual bool AllowSilence { get; set; } + /// + /// 允许踢人 + /// + public virtual bool AllowKickPeople { get; set; } + /// + /// 允许加人 + /// + public virtual bool AllowAddPeople { get; set; } + /// + /// 允许发送群公告 + /// + public virtual bool AllowSendNotice { get; set; } + /// + /// 允许解散群组 + /// + public virtual bool AllowDissolveGroup { get; set; } + protected ChatGroupAdmin() { } + public ChatGroupAdmin(long groupId, Guid userId, bool isSuperAdmin = false) + { + GroupId = groupId; + UserId = userId; + AllowSilence = true; + AllowKickPeople = true; + AllowAddPeople = true; + AllowSendNotice = true; + SetSuperAdmin(isSuperAdmin); + } + + public void SetSuperAdmin(bool isSuperAdmin = false) + { + IsSuperAdmin = isSuperAdmin; + if (isSuperAdmin) + { + AllowDissolveGroup = true; + } + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs deleted file mode 100644 index fb4ac32b3..000000000 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/ChatMessage.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using Volo.Abp.Domain.Entities; -using Volo.Abp.MultiTenancy; - -namespace LINGYUN.Abp.MessageService.Messages -{ - public abstract class ChatMessage : Entity, IMultiTenant - { - /// - /// 租户 - /// - public virtual Guid? TenantId { get; protected set; } - /// - /// 发送用户标识 - /// - public virtual Guid SendUserId { get; protected set; } - /// - /// 接收用户标识 - /// - public virtual Guid ReceiveUserId { get; set; } - /// - /// 内容 - /// - public virtual string Content { get; protected set; } - /// - /// 发送状态 - /// - public virtual SendStatus SendStatus { get; protected set; } - } -} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupChatBlack.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupChatBlack.cs new file mode 100644 index 000000000..8c95ec396 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupChatBlack.cs @@ -0,0 +1,32 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MessageService.Messages +{ + /// + /// 用户黑名单 + /// + public class GroupChatBlack : CreationAuditedEntity, IMultiTenant + { + /// + /// 租户 + /// + public virtual Guid? TenantId { get; protected set; } + /// + /// 群组标识 + /// + public virtual long GroupId { get; protected set; } + /// + /// 拉黑的用户 + /// + public virtual Guid ShieldUserId { get; protected set; } + protected GroupChatBlack() { } + public GroupChatBlack(long groupId, Guid shieldUserId, Guid? tenantId) + { + GroupId = groupId; + ShieldUserId = shieldUserId; + TenantId = tenantId; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupMessage.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupMessage.cs new file mode 100644 index 000000000..8897e4fcf --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/GroupMessage.cs @@ -0,0 +1,24 @@ +using LINGYUN.Abp.IM.Messages; +using System; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public class GroupMessage : Message + { + /// + /// 群组标识 + /// + public virtual long GroupId { get; protected set; } + + protected GroupMessage() { } + public GroupMessage(long id, Guid sendUserId, string sendUserName, string content, MessageType type = MessageType.Text) + : base(id, sendUserId, sendUserName, content, type) + { + + } + public void SendToGroup(long groupId) + { + GroupId = groupId; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IGroupRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IGroupRepository.cs new file mode 100644 index 000000000..864e5170e --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IGroupRepository.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public interface IGroupRepository : IBasicRepository + { + /// + /// 用户是否已被拉黑 + /// + /// + /// + /// + Task UserHasBlackedAsync(long id, Guid formUserId); + + Task GetByIdAsync(long id); + + Task> GetGroupAdminAsync(long id); + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IMessageRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IMessageRepository.cs new file mode 100644 index 000000000..825e96b9e --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IMessageRepository.cs @@ -0,0 +1,24 @@ +using LINGYUN.Abp.IM.Messages; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public interface IMessageRepository + { + Task InsertUserMessageAsync(UserMessage userMessage, bool saveChangs = false); + + Task InsertGroupMessageAsync(GroupMessage groupMessage, bool saveChangs = false); + + Task GetUserMessageAsync(long id); + + Task GetGroupMessageAsync(long id); + + Task> GetUserMessagesAsync(Guid sendUserId, Guid receiveUserId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10); + + Task> GetGroupMessagesAsync(long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10); + + Task> GetUserGroupMessagesAsync(Guid sendUserId, long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10); + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatGroupRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatGroupRepository.cs new file mode 100644 index 000000000..2772adaff --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatGroupRepository.cs @@ -0,0 +1,25 @@ +using LINGYUN.Abp.IM.Group; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public interface IUserChatGroupRepository : IBasicRepository + { + /// + /// 用户是否在组里 + /// + /// + /// + /// + Task UserHasInGroupAsync(long groupId, Guid userId); + + Task GetUserGroupAsync(long groupId, Guid userId); + + Task> GetGroupUsersAsync(long groupId); + + Task> GetUserGroupsAsync(Guid userId); + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatSettingRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatSettingRepository.cs new file mode 100644 index 000000000..a091c38c4 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/IUserChatSettingRepository.cs @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public interface IUserChatSettingRepository : IBasicRepository + { + Task UserHasOpendImAsync(Guid userId); + /// + /// 用户是否已被拉黑 + /// + /// + /// + /// + Task UserHasBlackedAsync(Guid formUserId, Guid toUserId); + + Task GetByUserIdAsync(Guid userId); + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/Message.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/Message.cs new file mode 100644 index 000000000..3bb474be0 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/Message.cs @@ -0,0 +1,50 @@ +using LINGYUN.Abp.IM.Messages; +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public abstract class Message : CreationAuditedEntity, IMultiTenant + { + /// + /// 租户 + /// + public virtual Guid? TenantId { get; protected set; } + /// + /// 消息标识 + /// + public virtual long MessageId { get; protected set; } + /// + /// 发送用户名称 + /// + public virtual string SendUserName { get; protected set; } + /// + /// 内容 + /// + public virtual string Content { get; protected set; } + /// + /// 消息类型 + /// + public virtual MessageType Type { get; protected set; } + /// + /// 发送状态 + /// + public virtual MessageSendState SendState { get; protected set; } + protected Message() { } + public Message(long id, Guid sendUserId, string sendUserName, string content, MessageType type = MessageType.Text) + { + MessageId = id; + CreatorId = sendUserId; + SendUserName = sendUserName; + Content = content; + Type = type; + CreationTime = DateTime.Now; + } + + public void ChangeSendState(MessageSendState state = MessageSendState.Send) + { + SendState = state; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/MessageStore.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/MessageStore.cs new file mode 100644 index 000000000..46d4cf74e --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/MessageStore.cs @@ -0,0 +1,132 @@ +using LINGYUN.Abp.IM.Messages; +using LINGYUN.Abp.MessageService.Utils; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Domain.Services; +using Volo.Abp.ObjectMapping; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public class MessageStore : DomainService, IMessageStore + { + private IObjectMapper _objectMapper; + protected IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper); + + private IUnitOfWorkManager _unitOfWorkManager; + protected IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); + protected IUserChatSettingRepository UserChatSettingRepository { get; } + protected IMessageRepository MessageRepository { get; } + protected IGroupRepository GroupRepository { get; } + protected ISnowflakeIdGenerator SnowflakeIdGenerator { get; } + public MessageStore( + IGroupRepository groupRepository, + IMessageRepository messageRepository, + ISnowflakeIdGenerator snowflakeIdGenerator, + IUserChatSettingRepository userChatSettingRepository) + { + GroupRepository = groupRepository; + MessageRepository = messageRepository; + SnowflakeIdGenerator = snowflakeIdGenerator; + UserChatSettingRepository = userChatSettingRepository; + } + + [UnitOfWork] + public async Task StoreMessageAsync(ChatMessage chatMessage) + { + using (var unitOfWork = UnitOfWorkManager.Begin()) + { + using (CurrentTenant.Change(chatMessage.TenantId)) + { + if (!chatMessage.GroupId.IsNullOrWhiteSpace()) + { + long groupId = long.Parse(chatMessage.GroupId); + await StoreGroupMessageAsync(chatMessage, groupId); + } + else + { + await StoreUserMessageAsync(chatMessage); + } + await unitOfWork.SaveChangesAsync(); + } + } + } + + public async Task> GetGroupMessageAsync(Guid? tenantId, long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10) + { + using (CurrentTenant.Change(tenantId)) + { + var groupMessages = await MessageRepository.GetGroupMessagesAsync(groupId, filter, type, skipCount, maxResultCount); + var chatMessages = ObjectMapper.Map, List>(groupMessages); + + return chatMessages; + } + } + + public async Task> GetChatMessageAsync(Guid? tenantId, Guid sendUserId, Guid receiveUserId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10) + { + using (CurrentTenant.Change(tenantId)) + { + var userMessages = await MessageRepository.GetUserMessagesAsync(sendUserId, receiveUserId, filter, type, skipCount, maxResultCount); + var chatMessages = ObjectMapper.Map, List>(userMessages); + + return chatMessages; + } + } + + protected virtual async Task StoreUserMessageAsync(ChatMessage chatMessage) + { + var userHasBlacked = await UserChatSettingRepository + .UserHasBlackedAsync(chatMessage.ToUserId.Value, chatMessage.FormUserId); + if (userHasBlacked) + { + // 当前发送的用户已被拉黑 + throw new BusinessException(MessageServiceErrorCodes.UserHasBlack); + } + var userChatSetting = await UserChatSettingRepository.GetByUserIdAsync(chatMessage.ToUserId.Value); + if (!userChatSetting.AllowReceiveMessage) + { + // 当前发送的用户不接收消息 + throw new BusinessException(MessageServiceErrorCodes.UserHasRejectAllMessage); + } + if (chatMessage.IsAnonymous && !userChatSetting.AllowAnonymous) + { + // 当前用户不允许匿名发言 + throw new BusinessException(MessageServiceErrorCodes.UserNotAllowedToSpeakAnonymously); + } + var messageId = SnowflakeIdGenerator.Create(); + var message = new UserMessage(messageId, chatMessage.FormUserId, chatMessage.FormUserName, chatMessage.Content, chatMessage.MessageType); + message.SendToUser(chatMessage.ToUserId.Value); + await MessageRepository.InsertUserMessageAsync(message); + } + + protected virtual async Task StoreGroupMessageAsync(ChatMessage chatMessage, long groupId) + { + var userHasBlacked = await GroupRepository + .UserHasBlackedAsync(groupId, chatMessage.FormUserId); + if (userHasBlacked) + { + // 当前发送的用户已被拉黑 + throw new BusinessException(MessageServiceErrorCodes.GroupUserHasBlack); + } + var group = await GroupRepository.GetByIdAsync(groupId); + if (!group.AllowSendMessage) + { + // 当前群组不允许发言 + throw new BusinessException(MessageServiceErrorCodes.GroupNotAllowedToSpeak); + } + if (chatMessage.IsAnonymous && !group.AllowAnonymous) + { + // 当前群组不允许匿名发言 + throw new BusinessException(MessageServiceErrorCodes.GroupNotAllowedToSpeakAnonymously); + } + var messageId = SnowflakeIdGenerator.Create(); + var message = new GroupMessage(messageId, chatMessage.FormUserId, chatMessage.FormUserName, chatMessage.Content, chatMessage.MessageType); + // TODO: 需要压测 高并发场景下的装箱性能影响 + message.SendToGroup(groupId); + await MessageRepository.InsertGroupMessageAsync(message); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatBlack.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatBlack.cs new file mode 100644 index 000000000..4dc1267b6 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatBlack.cs @@ -0,0 +1,32 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MessageService.Messages +{ + /// + /// 用户黑名单 + /// + public class UserChatBlack : CreationAuditedEntity, IMultiTenant + { + /// + /// 租户 + /// + public virtual Guid? TenantId { get; protected set; } + /// + /// 用户标识 + /// + public virtual Guid UserId { get; protected set; } + /// + /// 拉黑的用户 + /// + public virtual Guid ShieldUserId { get; protected set; } + protected UserChatBlack() { } + public UserChatBlack(Guid userId, Guid shieldUserId, Guid? tenantId) + { + UserId = userId; + ShieldUserId = shieldUserId; + TenantId = tenantId; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatGroup.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatGroup.cs new file mode 100644 index 000000000..b4b49bc59 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatGroup.cs @@ -0,0 +1,27 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MessageService.Messages +{ + /// + /// 用户群组 + /// + public class UserChatGroup : CreationAuditedEntity, IMultiTenant + { + /// + /// 租户 + /// + public virtual Guid? TenantId { get; protected set; } + public virtual Guid UserId { get; protected set; } + public virtual long GroupId { get; protected set; } + protected UserChatGroup() { } + public UserChatGroup(long groupId, Guid userId, Guid acceptUserId, Guid? tenantId = null) + { + UserId = userId; + GroupId = groupId; + CreatorId = acceptUserId; + TenantId = tenantId; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatSetting.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatSetting.cs new file mode 100644 index 000000000..926884807 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserChatSetting.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Volo.Abp.Domain.Entities; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public class UserChatSetting : Entity, IMultiTenant + { + /// + /// 租户 + /// + public virtual Guid? TenantId { get; protected set; } + /// + /// 用户标识 + /// + public virtual Guid UserId { get; protected set; } + /// + /// 允许匿名聊天 + /// + public virtual bool AllowAnonymous { get; set; } + /// + /// 允许添加好友 + /// + public virtual bool AllowAddFriend { get; set; } + /// + /// 添加好友需要验证 + /// + public virtual bool RequireAddFriendValition { get; set; } + /// + /// 允许接收消息 + /// + public virtual bool AllowReceiveMessage { get; set; } + /// + /// 允许发送消息 + /// + public virtual bool AllowSendMessage { get; set; } + protected UserChatSetting() + { + } + public UserChatSetting(Guid userId, Guid? tenantId) + : this() + { + UserId = userId; + TenantId = tenantId; + AllowAnonymous = false; + AllowAddFriend = true; + AllowReceiveMessage = true; + AllowSendMessage = true; + RequireAddFriendValition = true; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserGroupStore.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserGroupStore.cs new file mode 100644 index 000000000..a94ad250f --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserGroupStore.cs @@ -0,0 +1,86 @@ +using LINGYUN.Abp.IM.Group; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Domain.Services; +using Volo.Abp.ObjectMapping; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public class UserGroupStore : DomainService, IUserGroupStore + { + private IObjectMapper _objectMapper; + protected IObjectMapper ObjectMapper => LazyGetRequiredService(ref _objectMapper); + + private IUnitOfWorkManager _unitOfWorkManager; + protected IUnitOfWorkManager UnitOfWorkManager => LazyGetRequiredService(ref _unitOfWorkManager); + + protected IUserChatGroupRepository UserChatGroupRepository { get; } + + public UserGroupStore( + IUserChatGroupRepository userChatGroupRepository) + { + UserChatGroupRepository = userChatGroupRepository; + } + + [UnitOfWork] + public async Task AddUserToGroupAsync(Guid? tenantId, Guid userId, long groupId, Guid acceptUserId) + { + using (var unitOfWork = UnitOfWorkManager.Begin()) + { + using (CurrentTenant.Change(tenantId)) + { + var userHasInGroup = await UserChatGroupRepository.UserHasInGroupAsync(groupId, userId); + if (!userHasInGroup) + { + var userGroup = new UserChatGroup(groupId, userId, acceptUserId, tenantId); + + await UserChatGroupRepository.InsertAsync(userGroup); + + await unitOfWork.SaveChangesAsync(); + } + } + } + } + + public async Task> GetGroupUsersAsync(Guid? tenantId, long groupId) + { + using (CurrentTenant.Change(tenantId)) + { + var userGroups = await UserChatGroupRepository.GetGroupUsersAsync(groupId); + + return userGroups; + } + } + + public async Task> GetUserGroupsAsync(Guid? tenantId, Guid userId) + { + using (CurrentTenant.Change(tenantId)) + { + var groups = await UserChatGroupRepository.GetUserGroupsAsync(userId); + + return groups; + } + } + + [UnitOfWork] + public async Task RemoveUserFormGroupAsync(Guid? tenantId, Guid userId, long groupId) + { + using (var unitOfWork = UnitOfWorkManager.Begin()) + { + using (CurrentTenant.Change(tenantId)) + { + var userGroup = await UserChatGroupRepository.GetUserGroupAsync(groupId, userId); + + if(userGroup != null) + { + await UserChatGroupRepository.DeleteAsync(userGroup); + + await unitOfWork.SaveChangesAsync(); + } + } + } + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserMessage.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserMessage.cs new file mode 100644 index 000000000..540f4a06b --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserMessage.cs @@ -0,0 +1,25 @@ +using LINGYUN.Abp.IM.Messages; +using System; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public class UserMessage : Message + { + /// + /// 接收用户标识 + /// + public virtual Guid ReceiveUserId { get; set; } + + protected UserMessage() { } + public UserMessage(long id, Guid sendUserId, string sendUserName, string content, MessageType type = MessageType.Text) + : base(id, sendUserId, sendUserName, content, type) + { + + } + + public void SendToUser(Guid receiveUserId) + { + ReceiveUserId = receiveUserId; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserSpecialFocus.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserSpecialFocus.cs new file mode 100644 index 000000000..b7835f920 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.Domain/LINGYUN/Abp/MessageService/Messages/UserSpecialFocus.cs @@ -0,0 +1,32 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MessageService.Messages +{ + /// + /// 用户特别关注 + /// + public class UserSpecialFocus : CreationAuditedEntity, IMultiTenant + { + /// + /// 租户 + /// + public virtual Guid? TenantId { get; protected set; } + /// + /// 用户标识 + /// + public virtual Guid UserId { get; protected set; } + /// + /// 关注的用户 + /// + public virtual Guid FocusUserId { get; protected set; } + protected UserSpecialFocus() { } + public UserSpecialFocus(Guid userId, Guid focusUserId, Guid? tenantId) + { + UserId = userId; + FocusUserId = focusUserId; + TenantId = tenantId; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs index 8fdc82b7d..aee1cc373 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/AbpMessageServiceEntityFrameworkCoreModule.cs @@ -1,4 +1,5 @@ -using LINGYUN.Abp.MessageService.Notifications; +using LINGYUN.Abp.MessageService.Messages; +using LINGYUN.Abp.MessageService.Notifications; using LINGYUN.Abp.MessageService.Subscriptions; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.EntityFrameworkCore; @@ -19,6 +20,10 @@ namespace LINGYUN.Abp.MessageService.EntityFrameworkCore options.AddRepository(); options.AddRepository(); + options.AddRepository(); + options.AddRepository(); + options.AddRepository(); + options.AddDefaultRepositories(includeAllEntities: true); }); } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs index a30c550a8..71e42ab07 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/EntityFrameworkCore/MessageServiceDbContextModelCreatingExtensions.cs @@ -1,4 +1,5 @@ -using LINGYUN.Abp.MessageService.Notifications; +using LINGYUN.Abp.MessageService.Messages; +using LINGYUN.Abp.MessageService.Notifications; using LINGYUN.Abp.MessageService.Subscriptions; using Microsoft.EntityFrameworkCore; using System; @@ -52,11 +53,108 @@ namespace LINGYUN.Abp.MessageService.EntityFrameworkCore b.ConfigureCreationTime(); b.ConfigureMultiTenant(); - b.ConfigureMultiTenant(); b.HasIndex(p => new { p.TenantId, p.UserId, p.NotificationName }) .HasName("IX_Tenant_User_Notification_Name") .IsUnique(); }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "UserMessages", options.Schema); + + b.Property(p => p.SendUserName).HasMaxLength(MessageConsts.MaxSendUserNameLength).IsRequired(); + b.Property(p => p.Content).HasMaxLength(MessageConsts.MaxContentLength).IsRequired(); + + b.ConfigureCreationTime(); + b.ConfigureMultiTenant(); + + b.HasIndex(p => new { p.TenantId, p.ReceiveUserId }); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "GroupMessages", options.Schema); + + b.Property(p => p.SendUserName).HasMaxLength(MessageConsts.MaxSendUserNameLength).IsRequired(); + b.Property(p => p.Content).HasMaxLength(MessageConsts.MaxContentLength).IsRequired(); + + b.ConfigureCreationTime(); + b.ConfigureMultiTenant(); + + b.HasIndex(p => new { p.TenantId, p.GroupId }); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "UserChatSettings", options.Schema); + + b.ConfigureMultiTenant(); + + b.HasIndex(p => new { p.TenantId, p.UserId }); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "UserSpecialFocuss", options.Schema); + + b.ConfigureMultiTenant(); + + b.HasIndex(p => new { p.TenantId, p.UserId }); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "UserChatBlacks", options.Schema); + + b.ConfigureMultiTenant(); + + b.HasIndex(p => new { p.TenantId, p.UserId }); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "GroupChatBlacks", options.Schema); + + b.ConfigureMultiTenant(); + + b.HasIndex(p => new { p.TenantId, p.GroupId }); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "ChatGroupAdmins", options.Schema); + + b.ConfigureMultiTenant(); + + b.HasIndex(p => new { p.TenantId, p.GroupId }); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "ChatGroups", options.Schema); + + b.Property(p => p.Name).HasMaxLength(ChatGroupConsts.MaxNameLength).IsRequired(); + + b.Property(p => p.Tag).HasMaxLength(ChatGroupConsts.MaxTagLength); + b.Property(p => p.Notice).HasMaxLength(ChatGroupConsts.MaxNoticeLength); + b.Property(p => p.Address).HasMaxLength(ChatGroupConsts.MaxAddressLength); + b.Property(p => p.Description).HasMaxLength(ChatGroupConsts.MaxDescriptionLength); + + b.ConfigureAudited(); + b.ConfigureMultiTenant(); + + b.HasIndex(p => new { p.TenantId, p.Name }); + }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "UserChatGroups", options.Schema); + + b.ConfigureCreationAudited(); + b.ConfigureMultiTenant(); + + b.HasIndex(p => new { p.TenantId, p.GroupId, p.UserId }); + }); } } } diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreGroupRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreGroupRepository.cs new file mode 100644 index 000000000..1b1b1e653 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreGroupRepository.cs @@ -0,0 +1,43 @@ +using LINGYUN.Abp.MessageService.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public class EfCoreGroupRepository : EfCoreRepository, + IGroupRepository, ITransientDependency + { + public EfCoreGroupRepository( + IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task GetByIdAsync(long id) + { + return await DbSet.Where(x => x.GroupId.Equals(id)).FirstOrDefaultAsync(); + } + + public async Task> GetGroupAdminAsync(long id) + { + var groupAdmins = await (from gp in DbContext.Set() + join gpa in DbContext.Set() + on gp.GroupId equals gpa.GroupId + select gpa).ToListAsync(); + return groupAdmins; + } + + public async Task UserHasBlackedAsync(long id, Guid formUserId) + { + var userHasBlack = await DbContext.Set() + .AnyAsync(x => x.GroupId.Equals(id) && x.ShieldUserId.Equals(formUserId)); + return userHasBlack; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreMessageRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreMessageRepository.cs new file mode 100644 index 000000000..6508e1a83 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreMessageRepository.cs @@ -0,0 +1,114 @@ +using LINGYUN.Abp.IM.Messages; +using LINGYUN.Abp.MessageService.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public class EfCoreMessageRepository : EfCoreRepository, + IMessageRepository, ITransientDependency + { + public EfCoreMessageRepository( + IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task GetGroupMessageAsync(long id) + { + return await DbContext.Set() + .Where(x => x.MessageId.Equals(id)) + .AsNoTracking() + .FirstOrDefaultAsync(); + } + + public async Task> GetGroupMessagesAsync(long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10) + { + if(skipCount > 0) + { + skipCount -= 1; + } + var groupMessages = await DbContext.Set() + .Where(x => x.GroupId.Equals(groupId) && x.Type.Equals(type)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Content.Contains(filter) || x.SendUserName.Contains(filter)) + .OrderByDescending(x => x.MessageId) + .Skip(skipCount * maxResultCount) + .Take(maxResultCount) + .ToListAsync(); + + return groupMessages; + } + + public async Task> GetUserGroupMessagesAsync(Guid sendUserId, long groupId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10) + { + if (skipCount > 0) + { + skipCount -= 1; + } + var groupMessages = await DbContext.Set() + .Where(x => x.GroupId.Equals(groupId) && x.CreatorId.Equals(sendUserId) && x.Type.Equals(type)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Content.Contains(filter) || x.SendUserName.Contains(filter)) + .OrderByDescending(x => x.MessageId) + .Skip(skipCount * maxResultCount) + .Take(maxResultCount) + .ToListAsync(); + + return groupMessages; + } + + public async Task GetUserMessageAsync(long id) + { + return await DbContext.Set() + .Where(x => x.MessageId.Equals(id)) + .AsNoTracking() + .FirstOrDefaultAsync(); + } + + public async Task> GetUserMessagesAsync(Guid sendUserId, Guid receiveUserId, string filter = "", MessageType type = MessageType.Text, int skipCount = 1, int maxResultCount = 10) + { + if (skipCount > 0) + { + skipCount -= 1; + } + var userMessages = await DbContext.Set() + .Where(x => x.CreatorId.Equals(sendUserId) && x.ReceiveUserId.Equals(receiveUserId) && x.Type.Equals(type)) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Content.Contains(filter) || x.SendUserName.Contains(filter)) + .OrderByDescending(x => x.MessageId) + .Skip(skipCount * maxResultCount) + .Take(maxResultCount) + .ToListAsync(); + + return userMessages; + } + + public async Task InsertGroupMessageAsync(GroupMessage groupMessage, bool saveChangs = false) + { + groupMessage = (await DbContext.Set().AddAsync(groupMessage, GetCancellationToken())).Entity; + + if(saveChangs) + { + await DbContext.SaveChangesAsync(); + } + + return groupMessage; + } + + public async Task InsertUserMessageAsync(UserMessage userMessage, bool saveChangs = false) + { + userMessage = (await DbContext.Set().AddAsync(userMessage, GetCancellationToken())).Entity; + + if (saveChangs) + { + await DbContext.SaveChangesAsync(); + } + + return userMessage; + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatGroupRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatGroupRepository.cs new file mode 100644 index 000000000..95cfec605 --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatGroupRepository.cs @@ -0,0 +1,86 @@ +using LINGYUN.Abp.IM.Group; +using LINGYUN.Abp.MessageService.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public class EfCoreUserChatGroupRepository : EfCoreRepository, + IUserChatGroupRepository, ITransientDependency + { + public EfCoreUserChatGroupRepository( + IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public async Task> GetGroupUsersAsync(long groupId) + { + // TODO: 急需单元测试,对这段代码不是太自信... + var groupUsers = await (from ug in DbSet + join x in ( + from gaj in DbContext.Set() + where gaj.GroupId.Equals(groupId) + select gaj + ) on ug.UserId equals x.UserId + into y from ga in y.DefaultIfEmpty() + where ug.GroupId.Equals(groupId) + select new UserGroup + { + GroupId = ug.GroupId, + IsSuperAdmin = ga != null && ga.IsSuperAdmin, + IsAdmin = ga != null, + TenantId = ug.TenantId, + UserId = ug.UserId + }) + .AsNoTracking() + .ToListAsync(); + return groupUsers; + } + + public async Task GetUserGroupAsync(long groupId, Guid userId) + { + return await DbSet.Where(x => x.GroupId.Equals(groupId) && x.UserId.Equals(userId)) + .AsNoTracking() + .FirstOrDefaultAsync(); + } + + public async Task> GetUserGroupsAsync(Guid userId) + { + // TODO: 急需单元测试,对这段代码不是太自信... + var userGroups = await (from ucg in DbSet + join cg in DbContext.Set() + on ucg.GroupId equals cg.GroupId + group cg by new + { + cg.GroupId, + cg.Name, + cg.AllowAnonymous, + cg.AllowSendMessage, + cg.MaxUserCount + } + into ug + orderby ug.Key.GroupId descending + select new Group + { + AllowAnonymous = ug.Key.AllowAnonymous, + AllowSendMessage = ug.Key.AllowSendMessage, + GroupUserCount = ug.Count(), + MaxUserLength = ug.Key.MaxUserCount, + Name = ug.Key.Name + }).ToListAsync(); + + return userGroups; + } + + public async Task UserHasInGroupAsync(long groupId, Guid userId) + { + return await DbSet.AnyAsync(x => x.GroupId.Equals(groupId) && x.UserId.Equals(userId)); + } + } +} diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatSettingRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatSettingRepository.cs new file mode 100644 index 000000000..e68008eaf --- /dev/null +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Messages/EfCoreUserChatSettingRepository.cs @@ -0,0 +1,39 @@ +using LINGYUN.Abp.MessageService.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.MessageService.Messages +{ + public class EfCoreUserChatSettingRepository : EfCoreRepository, + IUserChatSettingRepository, ITransientDependency + { + public EfCoreUserChatSettingRepository( + IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task GetByUserIdAsync(Guid userId) + { + return await DbSet.Where(x => x.UserId.Equals(userId)) + .AsNoTracking() + .FirstOrDefaultAsync(); + } + + public async Task UserHasBlackedAsync(Guid formUserId, Guid toUserId) + { + return await DbContext.Set() + .AnyAsync(x => x.UserId.Equals(toUserId) && x.ShieldUserId.Equals(formUserId)); + } + + public async Task UserHasOpendImAsync(Guid userId) + { + return await DbSet.AnyAsync(x => x.UserId.Equals(userId)); + } + } +} diff --git a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs index 53ac44165..e63868347 100644 --- a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs +++ b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs @@ -41,6 +41,12 @@ namespace LINGYUN.Abp.SettingManagement continue; } + // TODO: 是否遵循框架的限制? + //if (!setting.IsVisibleToClients) + //{ + // continue; + //} + var settingValue = await SettingManager.GetOrNullAsync(setting.Name, providerName, providerKey); var settingInfo = new SettingDto { diff --git a/vueJs/images/aggregate.png b/vueJs/images/aggregate.png new file mode 100644 index 0000000000000000000000000000000000000000..537a913dadcd8aa1a24a4f2669a35f0e9b5fab52 GIT binary patch literal 47986 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�xgw2&%vF->UfI8PFeSo5;hhJ*^Gy`al^?@I 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 literal 0 HcmV?d00001 diff --git a/vueJs/images/client.png b/vueJs/images/client.png new file mode 100644 index 0000000000000000000000000000000000000000..8c9f4679b2fbed6efbb6655e995cae86e06108c5 GIT binary patch literal 52915 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 R$kSF1nV27Vy8rym{{!=}JSPAE literal 0 HcmV?d00001 diff --git a/vueJs/images/im-notifications.png b/vueJs/images/im-notifications.png new file mode 100644 index 0000000000000000000000000000000000000000..aac0ca99cbee70c31b58fb18d43e5969a7c08c39 GIT binary patch literal 63710 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 nH4yk{zvQErO- - {{ $t('AbpUiMultiTenancy.SwitchTenant') }} + ({{ $t('AbpUiMultiTenancy.SwitchTenant') }})