vue-chat-kit 0.3.9 → 0.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/vue-chat-kit.css +1 -1
  2. package/dist/vue-chat-kit.es.js +4420 -2877
  3. package/dist/vue-chat-kit.umd.js +1 -1
  4. package/package.json +1 -1
  5. package/src/components/AvatarCrop.vue +16 -127
  6. package/src/components/ChatPanel.vue +503 -2818
  7. package/src/components/EmojiPicker.vue +2 -73
  8. package/src/components/chat/ChatWindow.vue +177 -0
  9. package/src/components/chat/ContentList.vue +300 -0
  10. package/src/components/chat/ContextMenu.vue +32 -0
  11. package/src/components/chat/GroupSidebar.vue +284 -0
  12. package/src/components/chat/MainArea.vue +87 -0
  13. package/src/components/chat/Sidebar.vue +52 -0
  14. package/src/components/chat/dialogs/AddFriendDialog.vue +62 -0
  15. package/src/components/chat/dialogs/CreateGroupDialog.vue +86 -0
  16. package/src/components/chat/dialogs/GroupDetailDialog.vue +132 -0
  17. package/src/components/ui/Button.vue +190 -0
  18. package/src/components/ui/Dialog.vue +194 -0
  19. package/src/components/ui/Empty.vue +66 -0
  20. package/src/components/ui/Input.vue +166 -0
  21. package/src/components/ui/Message.vue +186 -0
  22. package/src/components/ui/MessageBox.vue +143 -0
  23. package/src/components/ui/MessageManager.vue +92 -0
  24. package/src/components/ui/Switch.vue +65 -0
  25. package/src/components/ui/Tag.vue +68 -0
  26. package/src/components/ui/icons/ArrowDown.vue +5 -0
  27. package/src/components/ui/icons/ArrowRight.vue +5 -0
  28. package/src/components/ui/icons/Bell.vue +6 -0
  29. package/src/components/ui/icons/Camera.vue +6 -0
  30. package/src/components/ui/icons/ChatDotRound.vue +5 -0
  31. package/src/components/ui/icons/Check.vue +5 -0
  32. package/src/components/ui/icons/CircleCheck.vue +6 -0
  33. package/src/components/ui/icons/Clock.vue +6 -0
  34. package/src/components/ui/icons/Close.vue +5 -0
  35. package/src/components/ui/icons/Delete.vue +8 -0
  36. package/src/components/ui/icons/Edit.vue +6 -0
  37. package/src/components/ui/icons/Folder.vue +5 -0
  38. package/src/components/ui/icons/Minus.vue +5 -0
  39. package/src/components/ui/icons/Monitor.vue +7 -0
  40. package/src/components/ui/icons/Moon.vue +5 -0
  41. package/src/components/ui/icons/Picture.vue +7 -0
  42. package/src/components/ui/icons/Plus.vue +5 -0
  43. package/src/components/ui/icons/Search.vue +6 -0
  44. package/src/components/ui/icons/Setting.vue +6 -0
  45. package/src/components/ui/icons/Sunny.vue +6 -0
  46. package/src/components/ui/icons/User.vue +6 -0
  47. package/src/components/ui/icons/UserFilled.vue +6 -0
  48. package/src/components/ui/icons/Warning.vue +5 -0
  49. package/src/components/ui/icons/index.js +24 -0
  50. package/src/components/ui/index.js +10 -0
  51. package/src/composables/useFriendChat.js +10 -14
  52. package/src/composables/useGroupChat.js +140 -48
  53. package/src/composables/useMessage.js +21 -0
  54. package/src/composables/useMessageBox.js +98 -0
  55. package/src/composables/useTheme.js +140 -0
  56. package/src/config/index.js +1 -0
  57. package/src/const/index.js +1 -0
  58. package/src/const/theme.js +19 -0
  59. package/src/core/api.js +13 -2
  60. package/src/index.js +5 -5
  61. package/src/styles/_base.scss +38 -0
  62. package/src/styles/_variables.scss +43 -0
  63. package/src/styles/components/_add-friend-dialog.scss +45 -0
  64. package/src/styles/components/_avatar-crop.scss +120 -0
  65. package/src/styles/components/_chat-panel.scss +546 -0
  66. package/src/styles/components/_chat-window.scss +239 -0
  67. package/src/styles/components/_content-list.scss +260 -0
  68. package/src/styles/components/_context-menu.scss +35 -0
  69. package/src/styles/components/_create-group-dialog.scss +78 -0
  70. package/src/styles/components/_dialogs.scss +226 -0
  71. package/src/styles/components/_emoji-picker.scss +74 -0
  72. package/src/styles/components/_group-detail-dialog.scss +110 -0
  73. package/src/styles/components/_group-sidebar.scss +278 -0
  74. package/src/styles/components/_main-area.scss +94 -0
  75. package/src/styles/components/_sidebar.scss +83 -0
  76. package/src/styles/index.scss +18 -0
  77. package/src/styles/themes/_dark.scss +68 -0
  78. package/src/styles/themes/_index.scss +7 -0
  79. package/src/styles/themes/_light.scss +69 -0
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M6 9L12 15L18 9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M13.73 21a2 2 0 0 1-3.46 0" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
6
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M23 19V5C23 3.89543 22.1046 3 21 3H17L15 1H9L7 3H3C1.89543 3 1 3.89543 1 5V19C1 20.1046 1.89543 21 3 21H21C22.1046 21 23 20.1046 23 19Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M12 17C14.7614 17 17 14.7614 17 12C17 9.23858 14.7614 7 12 7C9.23858 7 7 9.23858 7 12C7 14.7614 9.23858 17 12 17Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
6
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M21 15C21 18.866 16.9706 22 12 22C8.141 22 4.8475 19.826 3.5 16.5M21 15C21 6 12 2 12 2C12 2 3 6 3 15C3 16.3958 3.38031 17.6959 4.06703 18.8409M21 15C21 16.3958 20.6197 17.6959 19.933 18.8409M3.5 16.5C3.30485 16.7949 3.15853 17.1078 3.06817 17.4314M4.06703 18.8409L3 22L7 20" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M5 13L9 17L19 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
4
+ <path d="M8 12L11 15L16 9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
6
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
4
+ <path d="M12 6V12L16 14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
6
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M6 6L18 18M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,8 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M3 6H21" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
4
+ <path d="M19 6V20C19 21.1046 18.1046 22 17 22H7C5.89543 22 5 21.1046 5 20V6M8 6V4C8 2.89543 8.89543 2 10 2H14C15.1046 2 16 2.89543 16 4V6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path d="M10 11V17" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
6
+ <path d="M14 11V17" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
7
+ </svg>
8
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M11 4H4C2.89543 4 2 4.89543 2 6V20C2 21.1046 2.89543 22 4 22H18C19.1046 22 20 21.1046 20 20V13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M18.5 2.5C18.8978 2.10218 19.4374 1.87869 20 1.87869C20.5626 1.87869 21.1022 2.10218 21.5 2.5C21.8978 2.89782 22.1213 3.43744 22.1213 4C22.1213 4.56256 21.8978 5.10218 21.5 5.5L12 15L8 16L9 12L18.5 2.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
6
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M3 7V5C3 3.89543 3.89543 3 5 3H8L10 6H19C20.1046 6 21 6.89543 21 8V19C21 20.1046 20.1046 21 19 21H5C3.89543 21 3 20.1046 3 19V7Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M5 12H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <rect x="2" y="3" width="20" height="14" rx="2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M8 21H16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path d="M12 17V21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
6
+ </svg>
7
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M21 19V5C21 3.89543 20.1046 3 19 3H5C3.89543 3 3 3.89543 3 5V19C3 20.1046 3.89543 21 5 21H19C20.1046 21 21 20.1046 21 19Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M8.5 10C9.88071 10 11 8.88071 11 7.5C11 6.11929 9.88071 5 8.5 5C7.11929 5 6 6.11929 6 7.5C6 8.88071 7.11929 10 8.5 10Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path d="M21 15L16 10L5 21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
6
+ </svg>
7
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M12 5V19M5 12H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M11 19C15.4183 19 19 15.4183 19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11C3 15.4183 6.58172 19 11 19Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M21 21L16.65 16.65" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
6
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M19.4 15C19.1 15.6 18.6 16.1 18 16.4L16.5 13.9C16.2 13.8 15.8 13.8 15.5 13.9L14.5 16.4C13.9 16.8 13 16.9 12.4 16.6L12 14.4C12 14.1 11.8 13.9 11.6 13.9H9.6C9.4 13.9 9.1 14.1 9 14.4L8.6 16.6C8 16.9 7.1 16.8 6.5 16.4L5.5 13.9C5.2 13.8 4.8 13.8 4.5 13.9L3 16.4C2.4 16.1 1.9 15.6 1.6 15L1 13C0.7 12.3 0.9 11.5 1.6 11L4.5 8.5C4.8 8.2 4.8 7.8 4.5 7.5L3 5C3.3 4.4 3.8 3.9 4.4 3.6L7.5 2.5C8.1 2.3 8.8 2.5 9.2 2.9L10.2 5.4C10.5 5.7 10.8 5.8 11.2 5.8H13.2C13.5 5.8 13.8 5.7 14.1 5.4L15.1 2.9C15.5 2.5 16.2 2.3 16.8 2.5L19.9 3.6C20.5 3.9 21 4.4 21.3 5L22.8 7.5C23.1 7.8 23.1 8.2 22.8 8.5L20 11C20.3 11.5 20.4 12.2 20.1 12.8L19.4 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
6
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M12 17C14.7614 17 17 14.7614 17 12C17 9.23858 14.7614 7 12 7C9.23858 7 7 9.23858 7 12C7 14.7614 9.23858 17 12 17Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M12 1V3M12 21V23M4.22 4.22L5.64 5.64M18.36 18.36L19.78 19.78M1 12H3M21 12H23M4.22 19.78L5.64 18.36M18.36 5.64L19.78 4.22" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
6
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M20 21V19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19V21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M12 11C14.2091 11 16 9.20914 16 7C16 4.79086 14.2091 3 12 3C9.79086 3 8 4.79086 8 7C8 9.20914 9.79086 11 12 11Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
6
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M12 13C14.7614 13 17 10.7614 17 8C17 5.23858 14.7614 3 12 3C9.23858 3 7 5.23858 7 8C7 10.7614 9.23858 13 12 13Z" fill="currentColor"/>
4
+ <path d="M20 21V19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19V21" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </svg>
6
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M12 9V13M12 17H12.01M21 12C21 16.9706 16.9706 21 12 21 7.02944 21 3 16.9706 3 12 3 7.02944 7.02944 3 12 3 16.9706 3 21 7.02944 21 12 21Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -0,0 +1,24 @@
1
+ // 图标组件导出
2
+ export { default as Search } from './Search.vue'
3
+ export { default as User } from './User.vue'
4
+ export { default as UserFilled } from './UserFilled.vue'
5
+ export { default as ArrowDown } from './ArrowDown.vue'
6
+ export { default as ArrowRight } from './ArrowRight.vue'
7
+ export { default as Folder } from './Folder.vue'
8
+ export { default as ChatDotRound } from './ChatDotRound.vue'
9
+ export { default as Check } from './Check.vue'
10
+ export { default as CircleCheck } from './CircleCheck.vue'
11
+ export { default as Close } from './Close.vue'
12
+ export { default as Delete } from './Delete.vue'
13
+ export { default as Setting } from './Setting.vue'
14
+ export { default as Camera } from './Camera.vue'
15
+ export { default as Edit } from './Edit.vue'
16
+ export { default as Plus } from './Plus.vue'
17
+ export { default as Minus } from './Minus.vue'
18
+ export { default as Sunny } from './Sunny.vue'
19
+ export { default as Moon } from './Moon.vue'
20
+ export { default as Monitor } from './Monitor.vue'
21
+ export { default as Warning } from './Warning.vue'
22
+ export { default as Picture } from './Picture.vue'
23
+ export { default as Bell } from './Bell.vue'
24
+ export { default as Clock } from './Clock.vue'
@@ -0,0 +1,10 @@
1
+ // UI 组件导出
2
+ export { default as Button } from './Button.vue'
3
+ export { default as Dialog } from './Dialog.vue'
4
+ export { default as Input } from './Input.vue'
5
+ export { default as Empty } from './Empty.vue'
6
+ export { default as Message } from './Message.vue'
7
+ export { default as MessageManager } from './MessageManager.vue'
8
+ export { default as MessageBox } from './MessageBox.vue'
9
+ export { default as Switch } from './Switch.vue'
10
+ export { default as Tag } from './Tag.vue'
@@ -36,7 +36,7 @@ export function useFriendChat(core) {
36
36
  return list.map(item => ({
37
37
  id: item.username,
38
38
  name: item.username,
39
- avatar: item.avatar ? `${config.api.baseUrl}${item.avatar}` : myAvatar.value,
39
+ avatar: item.avatar ? `${config.api.baseUrl}${item.avatar}` : `https://api.dicebear.com/7.x/avataaars/svg?seed=${item.username}`,
40
40
  online: item.online,
41
41
  lastMsg: item.lastMsg || '暂无消息',
42
42
  lastTime: item.lastTime,
@@ -56,7 +56,7 @@ export function useFriendChat(core) {
56
56
  return list.map(item => ({
57
57
  id: item.username,
58
58
  name: item.username,
59
- avatar: item.avatar ? `${config.api.baseUrl}${item.avatar}` : myAvatar.value,
59
+ avatar: item.avatar ? `${config.api.baseUrl}${item.avatar}` : `https://api.dicebear.com/7.x/avataaars/svg?seed=${item.username}`,
60
60
  online: item.online,
61
61
  isChatting: item.isChatting
62
62
  }))
@@ -111,20 +111,16 @@ export function useFriendChat(core) {
111
111
  const res = await api.getFriends(myUsername)
112
112
  const allFriends = res.data || []
113
113
  friendList.value = allFriends
114
+
115
+ console.log('[VueChatKit] 获取到的好友列表:', friendList.value)
116
+ console.log('[VueChatKit] 所有好友的 isChatting:', friendList.value.map(f => ({ username: f.username, isChatting: f.isChatting })))
117
+
114
118
  chatList.value = allFriends.filter(item => item.isChatting === 1)
115
119
 
116
- // 获取未读数
117
- for (const friend of chatList.value) {
118
- try {
119
- const historyRes = await api.getHistory(myUsername, friend.username)
120
- const messages = historyRes.data || []
121
- friend.unReadNum = messages.filter(msg =>
122
- msg.isRead === 0 && msg.sendUsername === friend.username
123
- ).length
124
- } catch {
125
- friend.unReadNum = 0
126
- }
127
- }
120
+ console.log('[VueChatKit] 正在聊天的好友列表:', chatList.value)
121
+
122
+ // 未读数直接从接口返回的数据中获取,不再单独请求历史记录
123
+ // 假设接口返回的 friend 对象中已经包含 unReadNum 字段
128
124
  } catch (error) {
129
125
  console.error('[VueChatKit] 获取好友列表失败', error)
130
126
  }
@@ -9,6 +9,7 @@ export function useGroupChat(core) {
9
9
  // ========== 状态 ==========
10
10
  const activeTab = ref('friends')
11
11
  const groupList = ref([])
12
+ const chatList = ref([]) // 正在聊天的群聊列表
12
13
  const currentSelectGroup = ref(null)
13
14
  const groupMsgList = ref([])
14
15
  const groupMemberList = ref([])
@@ -22,6 +23,7 @@ export function useGroupChat(core) {
22
23
  const selectedMembersForInvite = ref([])
23
24
  // 新增状态
24
25
  const groupInfoVisible = ref(false)
26
+ const isRemoveMemberMode = ref(false) // 是否处于移除成员模式
25
27
  const editingGroupInfo = ref({
26
28
  groupNickname: '',
27
29
  remark: '',
@@ -53,6 +55,69 @@ export function useGroupChat(core) {
53
55
  })
54
56
 
55
57
  // ========== 计算属性 ==========
58
+
59
+ // 判断当前用户是否是群主:优先检查群成员列表中当前用户的 memberType === 0
60
+ const isGroupOwner = computed(() => {
61
+ console.log('[VueChatKit] 检查是否群主:', {
62
+ myUsername,
63
+ groupMemberCount: groupMemberList.value?.length
64
+ })
65
+
66
+ if (!currentSelectGroup.value) {
67
+ console.log('[VueChatKit] 没有选择群')
68
+ return false
69
+ }
70
+
71
+ // 优先检查群成员列表中当前用户的 memberType === 0
72
+ if (groupMemberList.value && groupMemberList.value.length > 0) {
73
+ const currentUserInGroup = groupMemberList.value.find(
74
+ m => m.username === myUsername
75
+ )
76
+
77
+ console.log('[VueChatKit] 当前用户在群成员:', currentUserInGroup)
78
+
79
+ if (currentUserInGroup) {
80
+ if (currentUserInGroup.memberType === 0) {
81
+ console.log('[VueChatKit] ✅ 当前用户是群主 (memberType=0)')
82
+ return true
83
+ }
84
+ console.log('[VueChatKit] 当前用户 memberType:', currentUserInGroup.memberType)
85
+ }
86
+ }
87
+
88
+ // 兜底逻辑:检查群的 ownerUsername/owner 字段
89
+ if (currentSelectGroup.value.ownerUsername === myUsername ||
90
+ currentSelectGroup.value.owner === myUsername) {
91
+ console.log('[VueChatKit] ✅ 通过群 owner 字段判断是群主')
92
+ return true
93
+ }
94
+
95
+ console.log('[VueChatKit] ❌ 当前用户不是群主')
96
+ return false
97
+ })
98
+
99
+ // 从群成员列表中获取群主用户名
100
+ const groupOwnerUsername = computed(() => {
101
+ if (!currentSelectGroup.value) return ''
102
+
103
+ // 优先从群信息中获取
104
+ if (currentSelectGroup.value.ownerUsername) {
105
+ return currentSelectGroup.value.ownerUsername
106
+ }
107
+ if (currentSelectGroup.value.owner) {
108
+ return currentSelectGroup.value.owner
109
+ }
110
+
111
+ // 从成员列表中查找 memberType === 0 的用户
112
+ if (groupMemberList.value.length > 0) {
113
+ const ownerMember = groupMemberList.value.find(m => m.memberType === 0)
114
+ if (ownerMember) {
115
+ return ownerMember.username
116
+ }
117
+ }
118
+
119
+ return ''
120
+ })
56
121
 
57
122
  // 过滤后的群聊列表
58
123
  const filteredGroupList = computed(() => {
@@ -65,41 +130,23 @@ export function useGroupChat(core) {
65
130
  )
66
131
  }
67
132
  return list.map(item => {
68
- const members = groupMembersMap.value[item.groupId] || []
69
- const memberAvatars = members.slice(0, 4).map(member => ({
70
- username: member.username,
71
- avatar: member.avatar
72
- ? `${config.api.baseUrl}${member.avatar}`
73
- : `https://api.dicebear.com/7.x/avataaars/svg?seed=${member.username}`
74
- }))
133
+ // 使用接口返回的 groupAvatarList 来生成 memberAvatars
134
+ const memberAvatars = (item.groupAvatarList || []).map((avatarPath, index) => ({
135
+ username: `member-${index}`,
136
+ avatar: `${config.api.baseUrl}${avatarPath}`
137
+ })).slice(0, 4)
75
138
 
76
- // 获取最后一条消息,处理不同的字段名
77
- let lastMsg = '暂无消息'
78
- if (item.lastMsg) {
79
- lastMsg = item.lastMsg
80
- } else if (item.lastMessage) {
81
- lastMsg = item.lastMessage
82
- } else if (item.latestMessage) {
83
- lastMsg = item.latestMessage
84
- }
139
+ // 获取最后一条消息
140
+ const lastMsg = item.lastMsgContent || '暂无消息'
85
141
 
86
- // 获取未读数,处理不同的字段名
87
- let unread = 0
88
- if (item.unReadNum !== undefined && item.unReadNum !== null) {
89
- unread = item.unReadNum
90
- } else if (item.unreadCount !== undefined && item.unreadCount !== null) {
91
- unread = item.unreadCount
92
- } else if (item.unread !== undefined && item.unread !== null) {
93
- unread = item.unread
94
- }
142
+ // 获取最后消息发送者
143
+ const lastMsgSender = item.lastMsgSender || ''
95
144
 
96
- // 获取最后时间,处理不同的字段名
97
- let lastTime = item.lastTime
98
- if (!lastTime && item.latestTime) {
99
- lastTime = item.latestTime
100
- } else if (!lastTime && item.lastMsgTime) {
101
- lastTime = item.lastMsgTime
102
- }
145
+ // 获取未读数
146
+ const unread = item.unreadCount || 0
147
+
148
+ // 获取最后时间
149
+ const lastTime = item.lastMsgTime
103
150
 
104
151
  return {
105
152
  id: item.groupId,
@@ -110,9 +157,10 @@ export function useGroupChat(core) {
110
157
  avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${item.groupId}`,
111
158
  memberAvatars: memberAvatars,
112
159
  lastMsg: lastMsg,
160
+ lastMsgSender: lastMsgSender,
113
161
  lastTime: lastTime,
114
162
  unread: unread,
115
- memberCount: item.memberCount || 0,
163
+ memberCount: item.memberTotal || 0,
116
164
  // 保留原始字段用于编辑功能
117
165
  notice: item.notice,
118
166
  groupNickname: item.groupNickname
@@ -160,19 +208,43 @@ export function useGroupChat(core) {
160
208
  const res = await api.getMyGroups(myUsername)
161
209
  groupList.value = res.data || []
162
210
 
163
- for (const group of groupList.value) {
164
- try {
165
- const membersRes = await api.getGroupMembers(group.groupId, myUsername)
166
- groupMembersMap.value[group.groupId] = membersRes.data || []
167
- } catch (err) {
168
- console.error(`[VueChatKit] 获取群 ${group.groupId} 成员失败`, err)
169
- groupMembersMap.value[group.groupId] = []
170
- }
171
- }
211
+ console.log('[VueChatKit] 获取到的群聊列表:', groupList.value)
212
+ console.log('[VueChatKit] 所有群聊的 groupChatStatus:', groupList.value.map(g => ({ groupId: g.groupId, groupName: g.groupName, groupChatStatus: g.groupChatStatus })))
213
+
214
+ chatList.value = groupList.value.filter(item => item.groupChatStatus === 1)
215
+
216
+ console.log('[VueChatKit] 正在聊天的群聊列表:', chatList.value)
217
+
218
+ // 不在这里获取所有群成员,改为按需获取
172
219
  } catch (error) {
173
220
  console.error('[VueChatKit] 获取群聊列表失败', error)
174
221
  }
175
222
  }
223
+
224
+ // 按需获取单个群的成员
225
+ const ensureGroupMembers = async (groupId) => {
226
+ if (!groupMembersMap.value[groupId]) {
227
+ try {
228
+ const membersRes = await api.getGroupMembers(groupId, myUsername)
229
+ groupMembersMap.value[groupId] = membersRes.data || []
230
+ } catch (err) {
231
+ console.error(`[VueChatKit] 获取群 ${groupId} 成员失败`, err)
232
+ groupMembersMap.value[groupId] = []
233
+ }
234
+ }
235
+ }
236
+
237
+ // 设置群聊聊天状态
238
+ const setGroupToChatStatus = async (groupId, status = 1) => {
239
+ try {
240
+ await api.setGroupChatStatus(groupId, myUsername, status)
241
+ await getGroupList()
242
+ return true
243
+ } catch (error) {
244
+ console.error('[VueChatKit] 设置群聊状态失败', error)
245
+ return false
246
+ }
247
+ }
176
248
 
177
249
  // 获取群聊历史消息
178
250
  const getGroupHistory = async (groupId) => {
@@ -206,9 +278,11 @@ export function useGroupChat(core) {
206
278
  // 3. 设置当前选中的群
207
279
  currentSelectGroup.value = group
208
280
 
209
- // 4. 加载该群历史聊天消息
281
+ // 4. 按需加载群成员和历史聊天消息
282
+ await ensureGroupMembers(group.groupId)
210
283
  await getGroupHistory(group.groupId)
211
- await getGroupMembers(group.groupId)
284
+ // 同时也更新 groupMemberList 供当前选中的群使用
285
+ groupMemberList.value = groupMembersMap.value[group.groupId] || []
212
286
 
213
287
  scrollToBottom()
214
288
  }
@@ -288,10 +362,14 @@ export function useGroupChat(core) {
288
362
  }
289
363
 
290
364
  // 开始编辑字段
291
- const startEditField = (field) => {
365
+ const startEditField = async (field) => {
292
366
  // 先确保有最新数据
293
367
  if (!currentGroupInfo.value && currentSelectGroup.value) {
294
- fetchGroupDetail(currentSelectGroup.value.groupId)
368
+ await fetchGroupDetail(currentSelectGroup.value.groupId)
369
+ }
370
+ // 初始化临时编辑值
371
+ if (currentGroupInfo.value) {
372
+ tempEditValues.value[field] = currentGroupInfo.value[field] || ''
295
373
  }
296
374
  editingFields.value[field] = true
297
375
  }
@@ -386,22 +464,30 @@ export function useGroupChat(core) {
386
464
  const removeGroupMember = async (targetUsername) => {
387
465
  if (!currentSelectGroup.value) return false
388
466
  try {
467
+ console.log('[VueChatKit] 开始移除成员:', targetUsername)
389
468
  const res = await api.removeGroupMember(
390
469
  currentSelectGroup.value.groupId,
391
470
  myUsername,
392
471
  targetUsername
393
472
  )
394
473
  if (res.code === 200) {
474
+ console.log('[VueChatKit] 移除成员成功,刷新成员列表')
395
475
  await getGroupMembers(currentSelectGroup.value.groupId)
476
+ // 如果移除的成员在当前显示列表中,刷新成员列表
477
+ if (isRemoveMemberMode.value) {
478
+ isRemoveMemberMode.value = false
479
+ }
396
480
  return true
397
481
  }
482
+ console.warn('[VueChatKit] 移除成员失败,返回结果:', res)
398
483
  return false
399
484
  } catch (error) {
400
- console.error('[VueChatKit] 移除成员失败', error)
485
+ console.error('[VueChatKit] 移除成员异常', error)
401
486
  return false
402
487
  }
403
488
  }
404
489
 
490
+
405
491
  // 转让群主
406
492
  const transferGroupOwner = async (newOwnerUsername) => {
407
493
  if (!currentSelectGroup.value) return false
@@ -687,6 +773,7 @@ export function useGroupChat(core) {
687
773
  // 状态
688
774
  activeTab,
689
775
  groupList,
776
+ chatList,
690
777
  currentSelectGroup,
691
778
  groupMsgList,
692
779
  groupMemberList,
@@ -699,6 +786,7 @@ export function useGroupChat(core) {
699
786
  inviteMemberDialogVisible,
700
787
  selectedMembersForInvite,
701
788
  groupInfoVisible,
789
+ isRemoveMemberMode,
702
790
  editingGroupInfo,
703
791
  editingMemberNick,
704
792
  memberNickDialogVisible,
@@ -711,6 +799,8 @@ export function useGroupChat(core) {
711
799
  // 计算属性
712
800
  filteredGroupList,
713
801
  currentGroupMessages,
802
+ isGroupOwner,
803
+ groupOwnerUsername,
714
804
 
715
805
  // 方法
716
806
  getGroupList,
@@ -741,7 +831,9 @@ export function useGroupChat(core) {
741
831
  updateSingleGroupField,
742
832
  startEditField,
743
833
  cancelEditField,
744
- saveEditField
834
+ saveEditField,
835
+ setGroupToChatStatus,
836
+ ensureGroupMembers
745
837
  }
746
838
  }
747
839
 
@@ -0,0 +1,21 @@
1
+ import { inject } from 'vue'
2
+
3
+ const MESSAGE_MANAGER_KEY = Symbol('messageManager')
4
+
5
+ export const useMessage = () => {
6
+ const manager = inject(MESSAGE_MANAGER_KEY)
7
+
8
+ if (!manager) {
9
+ console.warn('MessageManager not found. Please wrap your app with MessageManager component.')
10
+ // 提供一个后备实现
11
+ return {
12
+ show: (msg) => console.log('[Message]', msg),
13
+ success: (msg) => console.log('[Success]', msg),
14
+ warning: (msg) => console.warn('[Warning]', msg),
15
+ error: (msg) => console.error('[Error]', msg),
16
+ info: (msg) => console.info('[Info]', msg)
17
+ }
18
+ }
19
+
20
+ return manager
21
+ }