diff --git a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Chat/EfCoreMessageRepository.cs b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Chat/EfCoreMessageRepository.cs index 4d0c7a9c5..939c0ed1b 100644 --- a/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Chat/EfCoreMessageRepository.cs +++ b/aspnet-core/modules/message/LINGYUN.Abp.MessageService.EntityFrameworkCore/LINGYUN/Abp/MessageService/Chat/EfCoreMessageRepository.cs @@ -161,12 +161,12 @@ namespace LINGYUN.Abp.MessageService.Chat { sorting = reverse ? sorting + " desc" : sorting; var userMessages = await DbContext.Set() - .Distinct() - .Where(x => x.CreatorId.Equals(sendUserId) && x.ReceiveUserId.Equals(receiveUserId)) + .Where(x => (x.CreatorId.Equals(sendUserId) && x.ReceiveUserId.Equals(receiveUserId)) | + x.CreatorId.Equals(receiveUserId) && x.ReceiveUserId.Equals(sendUserId)) .WhereIf(type != null, x => x.Type.Equals(type)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Content.Contains(filter) || x.SendUserName.Contains(filter)) .OrderBy(sorting ?? nameof(GroupMessage.MessageId)) - .Page(skipCount, maxResultCount) + .PageBy(skipCount, maxResultCount) .AsNoTracking() .ToListAsync(GetCancellationToken(cancellationToken)); @@ -181,8 +181,8 @@ namespace LINGYUN.Abp.MessageService.Chat CancellationToken cancellationToken = default) { var userMessagesCount = await DbContext.Set() - .Distinct() - .Where(x => x.CreatorId.Equals(sendUserId) && x.ReceiveUserId.Equals(receiveUserId)) + .Where(x => (x.CreatorId.Equals(sendUserId) && x.ReceiveUserId.Equals(receiveUserId)) | + x.CreatorId.Equals(receiveUserId) && x.ReceiveUserId.Equals(sendUserId)) .WhereIf(type != null, x => x.Type.Equals(type)) .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Content.Contains(filter) || x.SendUserName.Contains(filter)) .LongCountAsync(GetCancellationToken(cancellationToken)); diff --git a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db index 99db5d637..87685da6a 100644 Binary files a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db and b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db differ diff --git a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/AbpIdentityServerAdminHttpApiHostModule.cs b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/AbpIdentityServerAdminHttpApiHostModule.cs index d97700826..75aa85d7e 100644 --- a/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/AbpIdentityServerAdminHttpApiHostModule.cs +++ b/aspnet-core/services/identity-server/LINGYUN.Abp.IdentityServer4.HttpApi.Host/AbpIdentityServerAdminHttpApiHostModule.cs @@ -104,6 +104,14 @@ namespace LINGYUN.Abp.IdentityServer4 Configure(options => { options.UseMySQL(); + //if (hostingEnvironment.IsDevelopment()) + //{ + // options.PreConfigure(ctx => + // { + // ctx.DbContextOptions.EnableDetailedErrors(); + // ctx.DbContextOptions.EnableSensitiveDataLogging(); + // }); + //} }); // 加解密 diff --git a/vueJs/package-lock.json b/vueJs/package-lock.json index a6c66486a..03671975a 100644 --- a/vueJs/package-lock.json +++ b/vueJs/package-lock.json @@ -2019,12 +2019,37 @@ "glob-to-regexp": "^0.3.0" } }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npm.taobao.org/@nodelib/fs.scandir/download/@nodelib/fs.scandir-2.1.3.tgz", + "integrity": "sha1-Olgr21OATGum0UZXnEblITDPSjs=", + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + }, + "dependencies": { + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/@nodelib/fs.stat/download/@nodelib/fs.stat-2.0.3.tgz", + "integrity": "sha1-NNxfTKu8cg9OYPdadH5+zWwXW9M=" + } + } + }, "@nodelib/fs.stat": { "version": "1.1.3", "resolved": "https://registry.npm.taobao.org/@nodelib/fs.stat/download/@nodelib/fs.stat-1.1.3.tgz", "integrity": "sha1-K1o6s/kYzKSKjHVMCBaOPwPrphs=", "dev": true }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npm.taobao.org/@nodelib/fs.walk/download/@nodelib/fs.walk-1.2.4.tgz", + "integrity": "sha1-ARuSAqcKY2bkNspcBlhEUoqwSXY=", + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, "@samverschueren/stream-to-observable": { "version": "0.3.0", "resolved": "https://registry.npm.taobao.org/@samverschueren/stream-to-observable/download/@samverschueren/stream-to-observable-0.3.0.tgz", @@ -4663,8 +4688,7 @@ "big.js": { "version": "5.2.2", "resolved": "https://registry.npm.taobao.org/big.js/download/big.js-5.2.2.tgz", - "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=", - "dev": true + "integrity": "sha1-ZfCvOC9Xi83HQr2cKB6cstd2gyg=" }, "binary-extensions": { "version": "1.13.1", @@ -7563,8 +7587,7 @@ "emojis-list": { "version": "3.0.0", "resolved": "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz", - "integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang=", - "dev": true + "integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang=" }, "encodeurl": { "version": "1.0.2", @@ -8800,6 +8823,14 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fastq": { + "version": "1.8.0", + "resolved": "https://registry.npm.taobao.org/fastq/download/fastq-1.8.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffastq%2Fdownload%2Ffastq-1.8.0.tgz", + "integrity": "sha1-VQ4fn1m7xl/hhctqm02VNXEH9IE=", + "requires": { + "reusify": "^1.0.4" + } + }, "faye-websocket": { "version": "0.10.0", "resolved": "https://registry.npm.taobao.org/faye-websocket/download/faye-websocket-0.10.0.tgz", @@ -10971,8 +11002,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-finite": { "version": "1.1.0", @@ -10995,7 +11025,6 @@ "version": "4.0.1", "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-4.0.1.tgz", "integrity": "sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -14465,7 +14494,6 @@ "version": "2.1.3", "resolved": "https://registry.npm.taobao.org/json5/download/json5-2.1.3.tgz", "integrity": "sha1-ybD3+pIzv+WAf+ZvzzpWF+1ZfUM=", - "dev": true, "requires": { "minimist": "^1.2.5" } @@ -14534,6 +14562,11 @@ "integrity": "sha1-p5yezIbuHOP6YgbRIWxQHxR/wH4=", "dev": true }, + "klona": { + "version": "2.0.4", + "resolved": "https://registry.npm.taobao.org/klona/download/klona-2.0.4.tgz?cache=0&sync_timestamp=1600226641291&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fklona%2Fdownload%2Fklona-2.0.4.tgz", + "integrity": "sha1-e7Hjr/sMuGJFR+9+j2cI6i4538A=" + }, "launch-editor": { "version": "2.2.1", "resolved": "https://registry.npm.taobao.org/launch-editor/download/launch-editor-2.2.1.tgz", @@ -16149,8 +16182,7 @@ "merge2": { "version": "1.3.0", "resolved": "https://registry.npm.taobao.org/merge2/download/merge2-1.3.0.tgz", - "integrity": "sha1-WzZu6DsvFYLEj4fkfPGpNSEDyoE=", - "dev": true + "integrity": "sha1-WzZu6DsvFYLEj4fkfPGpNSEDyoE=" }, "methods": { "version": "1.1.2", @@ -16649,8 +16681,7 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz", - "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=", - "dev": true + "integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=" }, "normalize-range": { "version": "0.1.2", @@ -17256,8 +17287,7 @@ "picomatch": { "version": "2.2.2", "resolved": "https://registry.npm.taobao.org/picomatch/download/picomatch-2.2.2.tgz", - "integrity": "sha1-IfMz6ba46v8CRo9RRupAbTRfTa0=", - "dev": true + "integrity": "sha1-IfMz6ba46v8CRo9RRupAbTRfTa0=" }, "pify": { "version": "4.0.1", @@ -18772,6 +18802,11 @@ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", "dev": true }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npm.taobao.org/reusify/download/reusify-1.0.4.tgz", + "integrity": "sha1-kNo4Kx4SbvwCFG6QhFqI2xKSXXY=" + }, "rgb-regex": { "version": "1.0.1", "resolved": "https://registry.npm.taobao.org/rgb-regex/download/rgb-regex-1.0.1.tgz", @@ -18814,6 +18849,11 @@ "integrity": "sha1-hEDsz5nqPnC9QJ1JqriOEMGJpFU=", "dev": true }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npm.taobao.org/run-parallel/download/run-parallel-1.1.9.tgz", + "integrity": "sha1-yd06fPn0ssS2JE4XOm7YZuYd1nk=" + }, "run-queue": { "version": "1.0.3", "resolved": "https://registry.npm.taobao.org/run-queue/download/run-queue-1.0.3.tgz", @@ -19939,6 +19979,125 @@ } } }, + "stylus-loader": { + "version": "4.1.1", + "resolved": "https://registry.npm.taobao.org/stylus-loader/download/stylus-loader-4.1.1.tgz", + "integrity": "sha1-DpT11idJMqLa0FTRpzazIUasepk=", + "requires": { + "fast-glob": "^3.2.4", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "normalize-path": "^3.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npm.taobao.org/@nodelib/fs.stat/download/@nodelib/fs.stat-2.0.3.tgz", + "integrity": "sha1-NNxfTKu8cg9OYPdadH5+zWwXW9M=" + }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npm.taobao.org/@types/json-schema/download/@types/json-schema-7.0.6.tgz", + "integrity": "sha1-9MfsQ+gbMZqYFRFQMXCfJph4kfA=" + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.6.tgz?cache=0&sync_timestamp=1603561543180&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.6.tgz", + "integrity": "sha1-uvWmLoArB9l3A0WG+MO69a3ybfQ=", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npm.taobao.org/ajv-keywords/download/ajv-keywords-3.5.2.tgz?cache=0&sync_timestamp=1603565974467&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv-keywords%2Fdownload%2Fajv-keywords-3.5.2.tgz", + "integrity": "sha1-MfKdpatuANHC0yms97WSlhTVAU0=" + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz", + "integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=", + "requires": { + "fill-range": "^7.0.1" + } + }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npm.taobao.org/fast-glob/download/fast-glob-3.2.4.tgz?cache=0&sync_timestamp=1592290276588&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffast-glob%2Fdownload%2Ffast-glob-3.2.4.tgz", + "integrity": "sha1-0grvv5lXk4Pn88xmUpFYybmFVNM=", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz", + "integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-5.1.1.tgz", + "integrity": "sha1-tsHvQXxOVmPqSY8cRa+saRa7wik=", + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz", + "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=" + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npm.taobao.org/loader-utils/download/loader-utils-2.0.0.tgz?cache=0&sync_timestamp=1584445172927&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Floader-utils%2Fdownload%2Floader-utils-2.0.0.tgz", + "integrity": "sha1-5MrOW4FtQloWa18JfhDNErNgZLA=", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npm.taobao.org/micromatch/download/micromatch-4.0.2.tgz", + "integrity": "sha1-T8sJmb+fvC/L3SEvbWKbmlbDklk=", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "schema-utils": { + "version": "3.0.0", + "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-3.0.0.tgz", + "integrity": "sha1-Z1AvaqK2ai1AMrQnmilEl4oJE+8=", + "requires": { + "@types/json-schema": "^7.0.6", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz", + "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=", + "requires": { + "is-number": "^7.0.0" + } + } + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-5.5.0.tgz", diff --git a/vueJs/package.json b/vueJs/package.json index 2970d1cf1..6eb1f57b7 100644 --- a/vueJs/package.json +++ b/vueJs/package.json @@ -42,6 +42,7 @@ "script-loader": "^0.7.2", "simple-progress-webpack-plugin": "^1.1.2", "sortablejs": "^1.10.2", + "stylus-loader": "^4.1.1", "tinymce": "^5.2.1", "tui-editor": "^1.4.10", "view-design": "^4.2.0", diff --git a/vueJs/src/api/instant-message.ts b/vueJs/src/api/instant-message.ts index 97aadafed..29ff4eb55 100644 --- a/vueJs/src/api/instant-message.ts +++ b/vueJs/src/api/instant-message.ts @@ -5,7 +5,7 @@ const serviceUrl = process.env.VUE_APP_BASE_API export default class ImApiService { public static getMyFriends(payload: MyFriendGetByPaged) { - let _url = 'api/im/my-friends' + let _url = '/api/im/my-friends' _url += '?filter=' + payload.filter _url += '&sorting=' + payload.sorting _url += '&reverse=' + payload.reverse @@ -13,6 +13,18 @@ export default class ImApiService { _url += '&maxResultCount=' + payload.maxResultCount return ApiService.Get>(_url, serviceUrl) } + + public static getMyChatMessages(payload: UserMessageGetByPaged) { + let _url = '/api/im/chat/messages/me' + _url += '?receiveUserId=' + payload.receiveUserId + _url += '&messageType=' + payload.messageType + _url += '&filter=' + payload.filter + _url += '&sorting=' + payload.sorting + _url += '&reverse=' + payload.reverse + _url += '&skipCount=' + payload.skipCount + _url += '&maxResultCount=' + payload.maxResultCount + return ApiService.Get>(_url, serviceUrl) + } } export enum Sex @@ -50,11 +62,21 @@ export class MyFriendGetByPaged extends PagedAndSortedResultRequestDto { reverse = false } +export class UserMessageGetByPaged extends PagedAndSortedResultRequestDto { + filter = '' + messageType = MessageType.Text + sorting = 'CreationTime' + reverse = true + receiveUserId = '' +} + export enum MessageType { Text = 0, Image = 10, Link = 20, - Video = 30 + Video = 30, + Voice = 40, + File = 50 } export class ChatMessage { @@ -68,4 +90,22 @@ export class ChatMessage { sendTime = new Date() isAnonymous = false messageType = MessageType.Text + + public static getType(messageType: MessageType) { + switch(messageType) { + case MessageType.Text : + case MessageType.Link : + return 'text' + case MessageType.Video : + return 'video' + case MessageType.Image : + return 'image' + case MessageType.Voice : + return 'voice' + case MessageType.File : + return 'file' + default : + return 'text' + } + } } diff --git a/vueJs/src/components/InstantMessage/index.vue b/vueJs/src/components/InstantMessage/index.vue index 5f578350e..1236c44bc 100644 --- a/vueJs/src/components/InstantMessage/index.vue +++ b/vueJs/src/components/InstantMessage/index.vue @@ -1,11 +1,29 @@ @@ -13,9 +31,16 @@ import EventBusMiXin from '@/mixins/EventBusMiXin' import Component, { mixins } from 'vue-class-component' +import { abpPagerFormat } from '@/utils' + import { UserModule } from '@/store/modules/user' -import ImApiService, { MyFriendGetByPaged, UserFriend, ChatMessage } from '@/api/instant-message' +import ImApiService, { + MyFriendGetByPaged, + UserMessageGetByPaged, + UserFriend, + ChatMessage +} from '@/api/instant-message' import { HubConnection, HubConnectionBuilder, HubConnectionState } from '@microsoft/signalr' @@ -26,8 +51,58 @@ class MyContract { type = '' index = 'A' unread = 0 - lastSendTime = 0 - lastContent = '0' + lastSendTime = 1345209465000 + lastContent = '' + readMsgPage = 1 +} + +class ChatMenu { + name = '' + title = '' + unread = 0 + render?: Function + renderContainer?: Function + isBottom = false + + constructor( + name: string, + title: string, + unread = 0, + isBottom = false + ) { + this.name = name + this.title = title + this.unread = unread + this.isBottom = isBottom + } +} + +class FromUser { + id = '' + displayName = '' + avatar = '' +} + +class Message { + id = '' + status = '' + type = 'text' + sendTime = 0 + content = '' + fileSize = 0 + fileName = '' + toContactId = '' + fromUser = new FromUser() + + public fromChatMessage(chatMessage: ChatMessage) { + this.id = chatMessage.messageId + this.content = chatMessage.content + this.fromUser.id = chatMessage.formUserId + this.fromUser.displayName = chatMessage.formUserName + this.toContactId = chatMessage.toUserId + this.type = ChatMessage.getType(chatMessage.messageType) + this.sendTime = new Date(chatMessage.sendTime).getTime() + } } @Component({ @@ -40,6 +115,9 @@ export default class InstantMessage extends mixins(EventBusMiXin) { private myFriends = new Array() private connection!: HubConnection + private chatMenus = new Array() + + private getChatMessageFilter = new UserMessageGetByPaged() get currentUser() { return { @@ -50,7 +128,9 @@ export default class InstantMessage extends mixins(EventBusMiXin) { } mounted() { + this.unSubscribeAll() this.subscribe('onShowImDialog', this.onShowImDialog) + this.handleInitDefaultMenus() this.handleStartConnection() } @@ -58,6 +138,40 @@ export default class InstantMessage extends mixins(EventBusMiXin) { this.unSubscribe('onShowImDialog') } + private handleInitIMUI() { + const imui = this.$refs.IMUI as any + ImApiService + .getMyFriends(this.dataFilter) + .then(res => { + this.myFriends = res.items + this.myFriendCount = res.totalCount + this.handleInitContracts(imui) + }) + } + + private handleInitContracts(imui: any) { + const myContracts = new Array() + this.myFriends + .forEach(friend => { + const myContract = new MyContract() + myContract.id = friend.friendId + myContract.displayName = friend.remarkName ?? friend.userName + myContract.unread = 0 + myContract.lastSendTime = new Date().getTime() + myContract.lastContent = '1524545' + myContract.type = 'many' + myContracts.push(myContract) + }) + imui.initContacts(myContracts) + imui.initMenus(this.chatMenus) + } + + private handleInitDefaultMenus() { + const lastMsgMenu = new ChatMenu('lastMessages', '历史消息') + const contractsMenu = new ChatMenu('contacts', '联系人') + this.chatMenus.push(lastMsgMenu, contractsMenu) + } + private handleStartConnection() { if (!this.connection) { const builder = new HubConnectionBuilder() @@ -66,6 +180,10 @@ export default class InstantMessage extends mixins(EventBusMiXin) { .withUrl('/signalr-hubs/signalr-hubs/messages', { accessTokenFactory: () => userToken }) .withAutomaticReconnect({ nextRetryDelayInMilliseconds: () => 60000 }) .build() + this.connection.on('getChatMessage', this.handleReceiveMessage) + this.connection.onreconnected(() => { + this.handleInitIMUI() + }) this.connection.onclose(error => { console.log('signalr connection has closed, error:') console.log(error) @@ -75,36 +193,83 @@ export default class InstantMessage extends mixins(EventBusMiXin) { this.connection .start() .then(() => { - ImApiService - .getMyFriends(this.dataFilter) - .then(res => { - this.myFriends = res.items - this.myFriendCount = res.totalCount - this.handleInitContracts() - }) + this.handleInitIMUI() }) } } - private handleInitContracts() { - const myContracts = new Array() - this.myFriends - .forEach(friend => { - const myContract = new MyContract() - myContract.id = friend.friendId - myContract.displayName = friend.remarkName ?? friend.userName - myContracts.push(myContract) - }) + private onShowImDialog() { + this.showDialog = !this.showDialog + } + + private onChangeMenu() { + console.log('Event:change-menu') + } + + private onPullMessages(contact: any, next: any) { + console.log(contact) const imui = this.$refs.IMUI as any - imui.initContacts(myContracts) + if (this.getChatMessageFilter.receiveUserId !== contact.id) { + this.getChatMessageFilter.receiveUserId = contact.id + } else { + contact.readMsgPage += 1 + } + this.getChatMessageFilter.skipCount = abpPagerFormat(contact.readMsgPage, this.getChatMessageFilter.maxResultCount) + ImApiService + .getMyChatMessages(this.getChatMessageFilter) + .then(res => { + const messages = res.items + .sort((last, next) => { + return next.sendTime < last.sendTime ? 1 : -1 + }) + .map(msg => { + const message = new Message() + message.fromChatMessage(msg) + return message + }) + let isEnd = true + if (imui.getMessages(contact.id).length < res.totalCount) { + isEnd = false + } + next(messages, isEnd) + }) + .catch(() => { + next(new Array(), true) + imui.messageViewToBottom() + }) } - private onShowImDialog() { - this.showDialog = !this.showDialog + private handleMenuAvatarClick() { + console.log('Event:menu-avatar-click') + } + + private handleMessageClick(e: any, key: any, message: any) { + console.log(e) + console.log(key) + console.log(message) + } + + private handleReceiveMessage(chatMessage: ChatMessage) { + const message = new Message() + message.fromChatMessage(chatMessage) + const imui = this.$refs.IMUI as any + imui.appendMessage(message) + const currentContact = imui.currentContact + if (currentContact && currentContact.id === chatMessage.formUserId) { + currentContact.lastContent = chatMessage.content + currentContact.lastSendTime = new Date(chatMessage.sendTime).getTime() + } else { + imui.updateContact(chatMessage.formUserId, { + unread: '+1', + lastSendTime: new Date(chatMessage.sendTime).getTime(), + lastContent: chatMessage.content + }) + } } - private handleSendMessage(message: any, next: any, file: any) { + private handleSendMessage(message: Message, next: any, file: any) { console.log(message, next, file) + const imui = this.$refs.IMUI as any const chatMessage = new ChatMessage() chatMessage.formUserId = message.fromUser.id chatMessage.formUserName = message.fromUser.displayName @@ -117,6 +282,103 @@ export default class InstantMessage extends mixins(EventBusMiXin) { next() }, 1000) }) + .catch(() => { + imui + .updateMessage(message.id, message.toContactId, { + status: 'failed' + }) + }) + } + + private onChangeContract(contract: any) { + const imui = this.$refs.IMUI as any + imui.updateContact(contract.id, { + unread: 0 + }) + imui.closeDrawer() } } + + diff --git a/vueJs/src/components/Lemon-IMUI/components/Avatar.vue b/vueJs/src/components/Lemon-IMUI/components/Avatar.vue new file mode 100644 index 000000000..a9a1efd7e --- /dev/null +++ b/vueJs/src/components/Lemon-IMUI/components/Avatar.vue @@ -0,0 +1,54 @@ + + + diff --git a/vueJs/src/components/Lemon-IMUI/index.vue b/vueJs/src/components/Lemon-IMUI/index.vue new file mode 100644 index 000000000..e69de29bb diff --git a/vueJs/src/mixins/DataListMiXin.ts b/vueJs/src/mixins/DataListMiXin.ts index 0caf13f13..76185319d 100644 --- a/vueJs/src/mixins/DataListMiXin.ts +++ b/vueJs/src/mixins/DataListMiXin.ts @@ -41,6 +41,7 @@ export default class DataListMiXin extends Vue { .then(res => { this.dataList = res.items this.dataTotal = res.items.length + this.onDataLoadCompleted() }) .finally(() => { this.dataLoading = false @@ -110,7 +111,9 @@ export default class DataListMiXin extends Vue { } /** 数据加载完毕事件 */ - protected onDataLoadCompleted() {} + protected onDataLoadCompleted() { + this.dataLoading = false + } /** * 排序变更事件 diff --git a/vueJs/src/mixins/EventBusMiXin.ts b/vueJs/src/mixins/EventBusMiXin.ts index a59ed6a59..af6fb439e 100644 --- a/vueJs/src/mixins/EventBusMiXin.ts +++ b/vueJs/src/mixins/EventBusMiXin.ts @@ -48,6 +48,13 @@ export default class EventBusMiXin extends Vue { this.$events.off(name, undefined) } + /** + * 注销所有事件 + */ + protected unSubscribeAll() { + this.$events.removeAll() + } + /** * 触发事件 * @param name 事件名称 diff --git a/vueJs/src/views/dashboard/admin/index.vue b/vueJs/src/views/dashboard/admin/index.vue index 63a5102ce..00034ba3f 100644 --- a/vueJs/src/views/dashboard/admin/index.vue +++ b/vueJs/src/views/dashboard/admin/index.vue @@ -1,29 +1,15 @@ diff --git a/vueJs/src/views/dashboard/index.vue b/vueJs/src/views/dashboard/index.vue index 3208b3cfc..c219b0373 100644 --- a/vueJs/src/views/dashboard/index.vue +++ b/vueJs/src/views/dashboard/index.vue @@ -1,23 +1,31 @@