diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application.Contracts/Dtos/ChatUserGetListOutputDto.cs b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application.Contracts/Dtos/ChatUserGetListOutputDto.cs new file mode 100644 index 00000000..3980460f --- /dev/null +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application.Contracts/Dtos/ChatUserGetListOutputDto.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.ChatHub.Application.Contracts.Dtos +{ + public class ChatUserGetListOutputDto + { + /// + /// 用户id + /// + public Guid UserId { get; set; } + + /// + /// 用户名称 + /// + public string UserName { get; set; } + + /// + /// 用户头像 + /// + public string UserIcon { get; set; } + } +} diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application.Contracts/Yi.Framework.ChatHub.Application.Contracts.csproj b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application.Contracts/Yi.Framework.ChatHub.Application.Contracts.csproj index 4e071e4c..8df46007 100644 --- a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application.Contracts/Yi.Framework.ChatHub.Application.Contracts.csproj +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application.Contracts/Yi.Framework.ChatHub.Application.Contracts.csproj @@ -9,7 +9,6 @@ - diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application/Services/ChatUserService.cs b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application/Services/ChatUserService.cs new file mode 100644 index 00000000..92da73da --- /dev/null +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application/Services/ChatUserService.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FreeRedis; +using Mapster; +using Microsoft.Extensions.Options; +using Volo.Abp.Application.Services; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Yi.Framework.ChatHub.Application.Contracts.Dtos; +using Yi.Framework.ChatHub.Domain.Shared.Caches; + +namespace Yi.Framework.ChatHub.Application.Services +{ + public class ChatUserService : ApplicationService + { + /// + /// 使用懒加载防止报错 + /// + private IRedisClient RedisClient => LazyServiceProvider.LazyGetRequiredService(); + private string CacheKeyPrefix => LazyServiceProvider.LazyGetRequiredService>().Value.KeyPrefix; + public async Task> GetListAsync() + { + var key = new ChatOnlineUserCacheKey(CacheKeyPrefix); + var cacheUsers = (await RedisClient.HGetAllAsync(key.GetKey())).Select(x => System.Text.Json.JsonSerializer.Deserialize < ChatOnlineUserCacheItem >( x.Value)).ToList(); + var output = cacheUsers.Adapt>(); + return output; + } + } +} diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application/SignalRHubs/ChatHub.cs b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application/SignalRHubs/ChatHub.cs new file mode 100644 index 00000000..4dc09c99 --- /dev/null +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application/SignalRHubs/ChatHub.cs @@ -0,0 +1,69 @@ +using FreeRedis; +using Mapster; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Options; +using Volo.Abp.AspNetCore.SignalR; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Yi.Framework.ChatHub.Application.Contracts.Dtos; +using Yi.Framework.ChatHub.Domain.Shared.Caches; +using Yi.Framework.ChatHub.Domain.Shared.Consts; + +namespace Yi.Framework.ChatHub.Application.SignalRHubs +{ + [HubRoute("/hub/chat")] + [Authorize] + public class ChatHub : AbpHub + { + /// + /// 使用懒加载防止报错 + /// + private IRedisClient RedisClient => LazyServiceProvider.LazyGetRequiredService(); + /// + /// 缓存前缀 + /// + private string CacheKeyPrefix => LazyServiceProvider.LazyGetRequiredService>().Value.KeyPrefix; + public ChatHub() + { + } + + /// + /// 用户进入聊天室 + /// + /// + public override async Task OnConnectedAsync() + { + var key = new ChatOnlineUserCacheKey(CacheKeyPrefix); + var item = new ChatOnlineUserCacheItem() + { + UserId = CurrentUser.Id!.Value, + ClientId = Context.ConnectionId, + UserName = CurrentUser.UserName! + }; + + + await RedisClient.HSetAsync(key.GetKey(), key.GetField(CurrentUser.Id!.Value), item); + + + //连接时,还需要去查询用户包含在的群组,将群主全部加入.Todo + await Groups.AddToGroupAsync(Context.ConnectionId, ChatConst.AllGroupName); + await Clients.All.SendAsync("liveUser", item.Adapt()); + + + } + + /// + /// 用户退出聊天室 + /// + /// + /// + public async override Task OnDisconnectedAsync(Exception? exception) + { + var key = new ChatOnlineUserCacheKey(CacheKeyPrefix); + await RedisClient.HDelAsync(key.GetKey(), key.GetField(CurrentUser.Id!.Value)); + await Groups.RemoveFromGroupAsync(Context.ConnectionId, ChatConst.AllGroupName); + await Clients.All.SendAsync("offlineUser", CurrentUser.Id!.Value); + } + } +} diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application/Yi.Framework.ChatHub.Application.csproj b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application/Yi.Framework.ChatHub.Application.csproj index f56fff96..4df813a8 100644 --- a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application/Yi.Framework.ChatHub.Application.csproj +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Application/Yi.Framework.ChatHub.Application.csproj @@ -9,7 +9,6 @@ - diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain.Shared/Caches/ChatOnlineUserCacheItem.cs b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain.Shared/Caches/ChatOnlineUserCacheItem.cs new file mode 100644 index 00000000..e130c1c4 --- /dev/null +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain.Shared/Caches/ChatOnlineUserCacheItem.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.ChatHub.Domain.Shared.Caches +{ + public class ChatOnlineUserCacheItem + { + public ChatOnlineUserCacheItem() + { + + + } + /// + /// 用户id + /// + public Guid UserId { get; set; } + + /// + /// 用户名称 + /// + public string UserName { get; set; } + + /// + /// 用户头像 + /// + public string UserIcon { get; set; } + + /// + /// 客户端id + /// + public string ClientId { get; set; } + + /// + /// 连接时间 + /// + public DateTime CreationTime { get; }=DateTime.Now; + + public override string ToString() + { + return System.Text.Json.JsonSerializer.Serialize(this); + } + } + + public class ChatOnlineUserCacheKey + { + public string CacheKeyPrefix; + public ChatOnlineUserCacheKey(string cacheKeyPrefix ) + { + CacheKeyPrefix=cacheKeyPrefix; + } + + public string GetKey() + { + return $"{CacheKeyPrefix}ChatOnline"; + } + + public string GetField(Guid userId) + { + return $"{userId}"; + } + } +} diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain.Shared/Consts/ChatConst.cs b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain.Shared/Consts/ChatConst.cs new file mode 100644 index 00000000..f059a53a --- /dev/null +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain.Shared/Consts/ChatConst.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Yi.Framework.ChatHub.Domain.Shared.Consts +{ + public class ChatConst + { + public const string AllGroupName = "all"; + } +} diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain.Shared/Yi.Framework.ChatHub.Domain.Shared.csproj b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain.Shared/Yi.Framework.ChatHub.Domain.Shared.csproj index 867a83ce..95fbf7f0 100644 --- a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain.Shared/Yi.Framework.ChatHub.Domain.Shared.csproj +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain.Shared/Yi.Framework.ChatHub.Domain.Shared.csproj @@ -1,8 +1,6 @@ - + - - @@ -10,5 +8,6 @@ + diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Yi.Framework.ChatHub.Domain.csproj b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Yi.Framework.ChatHub.Domain.csproj index eb4a0764..d478ffca 100644 --- a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Yi.Framework.ChatHub.Domain.csproj +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/Yi.Framework.ChatHub.Domain.csproj @@ -1,4 +1,4 @@ - + @@ -12,8 +12,8 @@ - - + + diff --git a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/YiFrameworkChatHubDomainModule.cs b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/YiFrameworkChatHubDomainModule.cs index 2838749f..5554c43e 100644 --- a/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/YiFrameworkChatHubDomainModule.cs +++ b/Yi.Abp.Net8/module/chat-hub/Yi.Framework.ChatHub.Domain/YiFrameworkChatHubDomainModule.cs @@ -1,4 +1,5 @@ using Volo.Abp.Domain; +using Yi.Framework.Caching.FreeRedis; using Yi.Framework.ChatHub.Domain.Shared; @@ -6,6 +7,7 @@ namespace Yi.Framework.ChatHub.Domain { [DependsOn( typeof(YiFrameworkChatHubDomainSharedModule), + typeof(YiFrameworkCachingFreeRedisModule), typeof(AbpDddDomainModule) )] diff --git a/Yi.Bbs.Vue3/src/apis/chatUserApi.js b/Yi.Bbs.Vue3/src/apis/chatUserApi.js new file mode 100644 index 00000000..d5bfb36e --- /dev/null +++ b/Yi.Bbs.Vue3/src/apis/chatUserApi.js @@ -0,0 +1,8 @@ +import request from "@/config/axios/service"; + +export function getList() { + return request({ + url: "/chat-user", + method: "get" + }); +} diff --git a/Yi.Bbs.Vue3/src/hubs/chatHub.js b/Yi.Bbs.Vue3/src/hubs/chatHub.js new file mode 100644 index 00000000..6f4d4302 --- /dev/null +++ b/Yi.Bbs.Vue3/src/hubs/chatHub.js @@ -0,0 +1,26 @@ +import signalR from "@/utils/signalR"; +import useChatStore from "@/stores/chat"; + +const receiveMsg = (connection) => { + const chatStore = useChatStore(); + //上线用户 + connection.on("liveUser", (user) => { + chatStore.addUser(user); + }); + //下线用户 + connection.on("offlineUser", (userId) => { + chatStore.delUser(userId); + }); + //接受其他用户消息 + connection.on("receiveMsg", (type, content) => { + + }); + //用户状态-正在输入中,无 + connection.on("userStatus", (type) => { + + }); +}; +export default () => { + signalR.start(`chat`, receiveMsg); +} + diff --git a/Yi.Bbs.Vue3/src/layout/ChatLayout.vue b/Yi.Bbs.Vue3/src/layout/ChatLayout.vue index 707a5ecb..0b96217d 100644 --- a/Yi.Bbs.Vue3/src/layout/ChatLayout.vue +++ b/Yi.Bbs.Vue3/src/layout/ChatLayout.vue @@ -4,6 +4,14 @@ + \ No newline at end of file + diff --git a/Yi.Bbs.Vue3/src/main.js b/Yi.Bbs.Vue3/src/main.js index 080d87ed..da231070 100644 --- a/Yi.Bbs.Vue3/src/main.js +++ b/Yi.Bbs.Vue3/src/main.js @@ -14,7 +14,7 @@ import * as ElementPlusIconsVue from "@element-plus/icons-vue"; import directive from "./directive"; // directive import VueLuckyCanvas from '@lucky-canvas/vue' -// import "./permission"; +import "./permission"; (async () => { const app = createApp(App); diff --git a/Yi.Bbs.Vue3/src/stores/chat.js b/Yi.Bbs.Vue3/src/stores/chat.js new file mode 100644 index 00000000..16d779f9 --- /dev/null +++ b/Yi.Bbs.Vue3/src/stores/chat.js @@ -0,0 +1,28 @@ +import { defineStore } from "pinia"; + +const chatStore = defineStore("chat", { + state: () => ({ + userList: [], + }), +// getters: { +// userListData: (state) => state.userList, +// }, + actions: { + // 设置在线总数 + setUserList(value) { + this.userList = value; + }, + addUser(user) + { + + this.userList.push(user); + }, + delUser(userId) + { + + this.userList = this.userList.filter(obj => obj.userId != userId); + } + }, +}); + +export default chatStore; diff --git a/Yi.Bbs.Vue3/src/views/chathub/Index.vue b/Yi.Bbs.Vue3/src/views/chathub/Index.vue index a360657e..1afcf60c 100644 --- a/Yi.Bbs.Vue3/src/views/chathub/Index.vue +++ b/Yi.Bbs.Vue3/src/views/chathub/Index.vue @@ -1,6 +1,19 @@ + +