protected virtual async Task StoreUserMessageAsync(
            ChatMessage chatMessage,
            CancellationToken cancellationToken = default)
        {
            // 检查接收用户
            if (!chatMessage.ToUserId.HasValue)
            {
                throw new BusinessException(MessageServiceErrorCodes.UseNotFount);
            }

            var myFriend = await _friendStore
                           .GetMemberAsync(chatMessage.TenantId, chatMessage.ToUserId.Value, chatMessage.FormUserId, cancellationToken);

            var userChatSetting = await _userChatSettingRepository
                                  .FindByUserIdAsync(chatMessage.ToUserId.Value, cancellationToken);

            if (userChatSetting != null)
            {
                if (!userChatSetting.AllowReceiveMessage)
                {
                    // 当前发送的用户不接收消息
                    throw new BusinessException(MessageServiceErrorCodes.UserHasRejectAllMessage);
                }

                if (myFriend == null && !chatMessage.IsAnonymous)
                {
                    throw new BusinessException(MessageServiceErrorCodes.UserHasRejectNotFriendMessage);
                }

                if (chatMessage.IsAnonymous && !userChatSetting.AllowAnonymous)
                {
                    // 当前用户不允许匿名发言
                    throw new BusinessException(MessageServiceErrorCodes.UserNotAllowedToSpeakAnonymously);
                }
            }
            else
            {
                if (myFriend == null)
                {
                    throw new BusinessException(MessageServiceErrorCodes.UserHasRejectNotFriendMessage);
                }
            }
            if (myFriend?.Black == true)
            {
                throw new BusinessException(MessageServiceErrorCodes.UserHasBlack);
            }
            var messageId = _snowflakeIdGenerator.Create();
            var message   = new UserMessage(messageId, chatMessage.FormUserId, chatMessage.FormUserName, chatMessage.Content, chatMessage.MessageType);

            message.SendToUser(chatMessage.ToUserId.Value);
            message.SetProperty(nameof(ChatMessage.IsAnonymous), chatMessage.IsAnonymous);

            await _messageRepository.InsertUserMessageAsync(message, cancellationToken);

            chatMessage.MessageId = messageId.ToString();
        }
        public virtual async Task InsertNotificationAsync(
            NotificationInfo notification,
            CancellationToken cancellationToken = default)
        {
            using (var unitOfWork = _unitOfWorkManager.Begin())
                using (_currentTenant.Change(notification.TenantId))
                {
                    // var notifyId = notification.GetId();
                    var notifyId = _snowflakeIdGenerator.Create();
                    // 保存主键,防止前端js long类型溢出
                    // notification.Data["id"] = notifyId.ToString();

                    var notify = new Notification(notifyId, notification.Name,
                                                  notification.Data.GetType().AssemblyQualifiedName,
                                                  _jsonSerializer.Serialize(notification.Data),
                                                  notification.Severity, notification.TenantId)
                    {
                        CreationTime = _clock.Now,
                        Type         = notification.Type,
                        // TODO: 通知过期时间应该可以配置
                        ExpirationTime = _clock.Now.AddDays(60)
                    };

                    await _notificationRepository.InsertAsync(notify, cancellationToken : cancellationToken);

                    notification.Id = notify.NotificationId.ToString();

                    await unitOfWork.SaveChangesAsync(cancellationToken);
                }
        }