vue-chat-kit 0.3.6 → 0.3.8

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.
@@ -0,0 +1,197 @@
1
+ <template>
2
+ <div v-if="visible" class="emoji-picker" @click.stop>
3
+ <div class="emoji-header">
4
+ <div
5
+ v-for="(category, index) in emojiCategories"
6
+ :key="category.id"
7
+ :class="['emoji-category-tab', { active: currentCategory === index }]"
8
+ @click="currentCategory = index"
9
+ >
10
+ {{ category.icon }}
11
+ </div>
12
+ </div>
13
+ <div class="emoji-body">
14
+ <div
15
+ v-for="emoji in emojiCategories[currentCategory].emojis"
16
+ :key="emoji"
17
+ class="emoji-item"
18
+ @click="selectEmoji(emoji)"
19
+ >
20
+ {{ emoji }}
21
+ </div>
22
+ </div>
23
+ </div>
24
+ </template>
25
+
26
+ <script setup>
27
+ import { ref } from 'vue'
28
+
29
+ const props = defineProps({
30
+ visible: {
31
+ type: Boolean,
32
+ default: false
33
+ }
34
+ })
35
+
36
+ const emit = defineEmits(['select', 'close'])
37
+
38
+ const currentCategory = ref(0)
39
+
40
+ // 常用表情分类
41
+ const emojiCategories = [
42
+ {
43
+ id: 'emoticons',
44
+ icon: '😀',
45
+ name: '表情',
46
+ emojis: [
47
+ '😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂', '🙂', '🙃',
48
+ '😉', '😊', '😇', '🥰', '😍', '🤩', '😘', '😗', '😚', '😋',
49
+ '😛', '😜', '🤪', '😝', '🤑', '🤗', '🤭', '🤫', '🤔', '🤐',
50
+ '🤨', '😐', '😑', '😶', '😏', '😒', '🙄', '😬', '🤥', '😌',
51
+ '😔', '😪', '🤤', '😴', '😷', '🤒', '🤕', '🤢', '🤮', '🤧',
52
+ '🥵', '🥶', '🥴', '😵', '🤯', '🤠', '🥳', '😎', '🤓', '🧐',
53
+ '😕', '😟', '🙁', '☹️', '😮', '😯', '😲', '😳', '🥺', '😦',
54
+ '😧', '😨', '😰', '😥', '😢', '😭', '😱', '😖', '😣', '😞'
55
+ ]
56
+ },
57
+ {
58
+ id: 'gestures',
59
+ icon: '👋',
60
+ name: '手势',
61
+ emojis: [
62
+ '👋', '🤚', '🖐️', '✋', '🖖', '👌', '🤌', '🤏', '✌️', '🤞',
63
+ '🤟', '🤘', '🤙', '👈', '👉', '👆', '🖕', '👇', '☝️', '👍',
64
+ '👎', '✊', '👊', '🤛', '🤜', '👏', '🙌', '👐', '🤲', '🤝',
65
+ '🙏', '🤚🏻', '🖐🏻', '✋🏻', '🖖🏻', '👌🏻', '🤌🏻', '🤏🏻', '✌🏻', '🤞🏻',
66
+ '🤟🏻', '🤘🏻', '🤙🏻', '👈🏻', '👉🏻', '👆🏻', '🖕🏻', '👇🏻', '☝🏻', '👍🏻'
67
+ ]
68
+ },
69
+ {
70
+ id: 'animals',
71
+ icon: '🐶',
72
+ name: '动物',
73
+ emojis: [
74
+ '🐶', '🐱', '🐭', '🐹', '🐰', '🦊', '🐻', '🐼', '🐨', '🐯',
75
+ '🦁', '🐮', '🐷', '🐸', '🐵', '🙈', '🙉', '🙊', '🐒', '🐔',
76
+ '🐧', '🐦', '🐤', '🐣', '🐥', '🦆', '🦅', '🦉', '🦇', '🐺',
77
+ '🐗', '🐴', '🦄', '🐝', '🐛', '🦋', '🐌', '🐞', '🐜', '🦟',
78
+ '🦗', '🕷️', '🦂', '🐢', '🐍', '🦎', '🦖', '🦕', '🐙', '🦑'
79
+ ]
80
+ },
81
+ {
82
+ id: 'food',
83
+ icon: '🍎',
84
+ name: '食物',
85
+ emojis: [
86
+ '🍎', '🍊', '🍋', '🍌', '🍉', '🍇', '🍓', '🍈', '🍒', '🍑',
87
+ '🥭', '🍍', '🥥', '🥝', '🍅', '🍆', '🥑', '🥦', '🥬', '🥒',
88
+ '🌶️', '🌽', '🥕', '🧄', '🧅', '🥔', '🍠', '🥐', '🥯', '🍞',
89
+ '🥖', '🥨', '🧀', '🥚', '🍳', '🧈', '🥞', '🧇', '🥓', '🥩',
90
+ '🍗', '🍖', '🌭', '🍔', '🍟', '🍕', '🥪', '🥙', '🧆', '🌮'
91
+ ]
92
+ },
93
+ {
94
+ id: 'objects',
95
+ icon: '⌚',
96
+ name: '物品',
97
+ emojis: [
98
+ '⌚', '📱', '📲', '💻', '⌨️', '🖥️', '🖨️', '🖱️', '🖲️', '🕹️',
99
+ '🗜️', '💽', '💾', '💿', '📀', '🧮', '🎥', '🎞️', '📽️', '🎬',
100
+ '📺', '📷', '📸', '📹', '📼', '🔍', '🔎', '🕯️', '💡', '🔦',
101
+ '🏮', '📔', '📕', '📖', '📗', '📘', '📙', '📚', '📓', '📒',
102
+ '📃', '📜', '📄', '📰', '🗞️', '📑', '🔖', '🏷️', '💰', '🪙'
103
+ ]
104
+ },
105
+ {
106
+ id: 'nature',
107
+ icon: '☀️',
108
+ name: '自然',
109
+ emojis: [
110
+ '☀️', '🌤️', '⛅', '🌥️', '☁️', '🌦️', '🌧️', '⛈️', '🌩️', '🌨️',
111
+ '❄️', '☃️', '⛄', '🌬️', '💨', '🌪️', '🌫️', '🌊', '💧', '💦',
112
+ '☔', '☂️', '🌱', '🌲', '🌳', '🌴', '🌵', '🌷', '🌹', '🥀',
113
+ '🌺', '🌸', '🌼', '🌻', '🌞', '⭐', '🌟', '✨', '💫', '🌙',
114
+ '🌚', '🌛', '🌜', '🌝', '🪐', '🌍', '🌎', '🌏', '⛱️', '🏖️'
115
+ ]
116
+ }
117
+ ]
118
+
119
+ const selectEmoji = (emoji) => {
120
+ emit('select', emoji)
121
+ }
122
+ </script>
123
+
124
+ <style scoped>
125
+ .emoji-picker {
126
+ position: absolute;
127
+ bottom: 100%;
128
+ left: 0;
129
+ width: 320px;
130
+ background: rgba(255, 255, 255, 0.9);
131
+ backdrop-filter: blur(20px);
132
+ -webkit-backdrop-filter: blur(20px);
133
+ border-radius: 16px;
134
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
135
+ border: 1px solid rgba(255, 255, 255, 0.3);
136
+ overflow: hidden;
137
+ z-index: 1000;
138
+ margin-bottom: 8px;
139
+ }
140
+
141
+ .emoji-header {
142
+ display: flex;
143
+ padding: 8px 12px;
144
+ border-bottom: 1px solid rgba(0, 0, 0, 0.08);
145
+ gap: 4px;
146
+ }
147
+
148
+ .emoji-category-tab {
149
+ padding: 8px 12px;
150
+ cursor: pointer;
151
+ border-radius: 8px;
152
+ transition: all 0.2s;
153
+ font-size: 18px;
154
+ line-height: 1;
155
+ }
156
+
157
+ .emoji-category-tab:hover {
158
+ background: rgba(0, 0, 0, 0.05);
159
+ }
160
+
161
+ .emoji-category-tab.active {
162
+ background: rgba(7, 193, 96, 0.1);
163
+ }
164
+
165
+ .emoji-body {
166
+ display: grid;
167
+ grid-template-columns: repeat(8, 1fr);
168
+ gap: 4px;
169
+ padding: 12px;
170
+ max-height: 240px;
171
+ overflow-y: auto;
172
+ }
173
+
174
+ .emoji-body::-webkit-scrollbar {
175
+ width: 6px;
176
+ }
177
+
178
+ .emoji-body::-webkit-scrollbar-thumb {
179
+ background: rgba(0, 0, 0, 0.2);
180
+ border-radius: 3px;
181
+ }
182
+
183
+ .emoji-item {
184
+ font-size: 24px;
185
+ padding: 8px;
186
+ text-align: center;
187
+ cursor: pointer;
188
+ border-radius: 8px;
189
+ transition: all 0.15s;
190
+ line-height: 1;
191
+ }
192
+
193
+ .emoji-item:hover {
194
+ background: rgba(0, 0, 0, 0.08);
195
+ transform: scale(1.2);
196
+ }
197
+ </style>
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * 聊天核心状态管理
3
3
  */
4
- import { ref, computed, nextTick } from 'vue'
4
+ import { ref, computed, nextTick, watch } from 'vue'
5
5
  import dayjs from 'dayjs'
6
6
  import { ChatWebSocket } from '../core/websocket.js'
7
7
  import { ChatApi } from '../core/api.js'
@@ -88,10 +88,7 @@ export function useChat(config, emit) {
88
88
 
89
89
  // 过滤后的可添加用户
90
90
  const filteredAvailableUsers = computed(() => {
91
- if (!addFriendSearchText.value) return availableUsers.value
92
- return availableUsers.value.filter(item =>
93
- item.username?.toLowerCase().includes(addFriendSearchText.value.toLowerCase())
94
- )
91
+ return availableUsers.value
95
92
  })
96
93
 
97
94
  // 当前选中的用户
@@ -442,13 +439,20 @@ export function useChat(config, emit) {
442
439
  const openAddFriendDialog = async () => {
443
440
  addFriendDialogVisible.value = true
444
441
  addFriendSearchText.value = ''
445
- await loadAvailableUsers()
442
+ availableUsers.value = [] // 清空列表,打开时不搜索
446
443
  }
447
444
 
448
- const loadAvailableUsers = async () => {
445
+ const loadAvailableUsers = async (keyword = '') => {
449
446
  loadingAvailableUsers.value = true
450
447
  try {
451
- const res = await api.getAvailableUsers(myUsername)
448
+ let res
449
+ if (keyword) {
450
+ // 使用模糊查询接口搜索用户
451
+ res = await api.searchUser(keyword)
452
+ } else {
453
+ // 使用获取可添加好友接口
454
+ res = await api.getAvailableUsers(myUsername)
455
+ }
452
456
  availableUsers.value = res?.data || []
453
457
  } catch (error) {
454
458
  console.error('[VueChatKit] 获取可用用户失败', error)
@@ -506,22 +510,6 @@ export function useChat(config, emit) {
506
510
  myAvatar.value = avatarUrl
507
511
  }
508
512
 
509
- const getUserInfo = async () => {
510
- loadingUserInfo.value = true
511
- try {
512
- const res = await api.getUserInfo(myUsername)
513
- if (res.code === 200 && res.data) {
514
- userInfo.value = {
515
- ...userInfo.value,
516
- ...res.data
517
- }
518
- }
519
- } catch (error) {
520
- console.error('[VueChatKit] 获取用户信息失败', error)
521
- } finally {
522
- loadingUserInfo.value = false
523
- }
524
- }
525
513
 
526
514
  const updateUserInfo = async (data) => {
527
515
  try {
@@ -551,6 +539,11 @@ export function useChat(config, emit) {
551
539
  // 初始化头像
552
540
  initUserAvatar()
553
541
 
542
+ // 监听添加好友搜索关键词变化,实时调用模糊查询
543
+ watch(addFriendSearchText, async (newKeyword) => {
544
+ await loadAvailableUsers(newKeyword)
545
+ })
546
+
554
547
  return {
555
548
  // 状态
556
549
  myUsername,
@@ -591,11 +584,11 @@ export function useChat(config, emit) {
591
584
  closeWebSocket,
592
585
  reset,
593
586
  openAddFriendDialog,
587
+ loadAvailableUsers,
594
588
  addFriend,
595
589
  loadFriendApplyList,
596
590
  agreeFriend,
597
591
  updateMyAvatar,
598
- getUserInfo,
599
592
  updateUserInfo
600
593
  }
601
594
  }
@@ -16,8 +16,7 @@ const defaultConfig = {
16
16
  agreeFriend: '/chart/friend/agree',
17
17
  setChatStatus: '/chart/friend/chat/status',
18
18
  getAvailableUsers: '/chart/user/canAddFriend',
19
- getUserInfo: '/user/info',
20
- updateUserInfo: '/user/info',
19
+ searchUser: '/chart/user/search',
21
20
  getUserAvatar: '/user/getAvatar',
22
21
  uploadAvatar: '/user/uploadAvatar'
23
22
  },
@@ -145,26 +145,6 @@ export const customAdapter = {
145
145
  return { code: 200 }
146
146
  },
147
147
 
148
- /**
149
- * 获取用户信息
150
- * @param {string} username - 用户名
151
- * @returns {Promise<{code: number, data: Object}>}
152
- */
153
- async getUserInfo(username) {
154
- console.log('getUserInfo 被调用, username:', username)
155
- return { code: 200, data: { username, nickname: '', avatar: '', email: '', phone: '', bio: '' } }
156
- },
157
-
158
- /**
159
- * 更新用户信息
160
- * @param {string} username - 用户名
161
- * @param {Object} data - 更新的数据
162
- * @returns {Promise<{code: number}>}
163
- */
164
- async updateUserInfo(username, data) {
165
- console.log('updateUserInfo 被调用', { username, data })
166
- return { code: 200 }
167
- },
168
148
 
169
149
  /**
170
150
  * 获取用户头像
package/src/core/api.js CHANGED
@@ -55,6 +55,17 @@ export class ChatApi {
55
55
  return this.http.get(this.endpoints.getAvailableUsers, { currentUser })
56
56
  }
57
57
 
58
+ /**
59
+ * 搜索用户
60
+ */
61
+ async searchUser(keyword) {
62
+ return this._call('searchUser', keyword)
63
+ }
64
+
65
+ async _searchUser(keyword) {
66
+ return this.http.get(this.endpoints.searchUser, { keyword })
67
+ }
68
+
58
69
  /**
59
70
  * 添加好友
60
71
  */
@@ -138,19 +149,6 @@ export class ChatApi {
138
149
  return this.http.post(this.endpoints.uploadFile, formData)
139
150
  }
140
151
 
141
- // ========== 用户相关 ==========
142
-
143
- /**
144
- * 获取用户信息
145
- */
146
- async getUserInfo(username) {
147
- return this._call('getUserInfo', username)
148
- }
149
-
150
- async _getUserInfo(username) {
151
- return this.http.get(this.endpoints.getUserInfo, { username })
152
- }
153
-
154
152
  /**
155
153
  * 更新用户信息
156
154
  */