From 763e11eb7882aa561bc66e467f3719cbdda9d651 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 28 May 2026 19:49:54 +0800 Subject: [PATCH] =?UTF-8?q?refactor(im):=20=E7=BB=9F=E4=B8=80=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E5=AD=98=E5=82=A8=E5=85=A5=E5=8F=A3=E5=92=8C=20store?= =?UTF-8?q?=20=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除 utils/storage.ts,getCurrentUserId 移到 utils/user.ts - StorageKeys 移到 utils/db.ts,按 localStorage / settings 分组 - db 客户端新增 clearStore;整桶 store 改为 clearStore + 循环 put 单事务 - 业务 store action / getter 统一改为 verbXxxList / verbXxx 风格 - draft API 加 Conversation 前缀;FriendStore loadFriends 改名 loadFriendData - 卸载 localforage 依赖 --- .gitignore | 1 + package.json | 1 - pnpm-lock.yaml | 22 -- .../im/home/components/ResizableAside.vue | 2 +- src/views/im/home/components/ToolBar.vue | 2 +- .../components/friend/FriendAddDialog.vue | 10 +- .../im/home/components/group/GroupAvatar.vue | 2 +- .../components/group/GroupCreateDialog.vue | 4 +- .../im/home/components/group/GroupInfo.vue | 4 +- .../components/group/GroupMemberAddDialog.vue | 2 +- .../group/GroupRequestListDialog.vue | 4 +- .../home/components/rtc/RtcCallContainer.vue | 2 +- .../rtc/RtcCallMemberPickerDialog.vue | 2 +- .../components/rtc/RtcGroupCallBanner.vue | 2 +- .../components/user/RecommendCardDialog.vue | 10 +- .../im/home/components/user/UserInfo.vue | 2 +- .../im/home/components/user/UserInfoCard.vue | 10 +- .../im/home/composables/useMessagePuller.ts | 6 +- .../im/home/composables/useMessageSender.ts | 4 +- src/views/im/home/index.vue | 54 ++--- .../pages/contact/FriendRequestDetail.vue | 2 +- .../home/pages/contact/FriendRequestList.vue | 4 +- src/views/im/home/pages/contact/index.vue | 14 +- .../conversation/ConversationGroupSide.vue | 12 +- .../conversation/ConversationItem.vue | 14 +- .../conversation/ConversationPrivateSide.vue | 10 +- .../components/input/FacePicker.vue | 4 +- .../components/input/MessageInput.vue | 28 +-- .../message/GroupRequestPending.vue | 2 +- .../components/message/MessageItem.vue | 2 +- .../components/message/MessagePanel.vue | 14 +- .../message/forward/MessageForwardDialog.vue | 10 +- .../im/home/pages/conversation/index.vue | 13 +- src/views/im/home/store/channelStore.ts | 31 +-- src/views/im/home/store/conversationStore.ts | 93 +++---- src/views/im/home/store/faceStore.ts | 22 +- src/views/im/home/store/friendStore.ts | 173 ++++++++----- src/views/im/home/store/groupRequestStore.ts | 78 ++++-- src/views/im/home/store/groupStore.ts | 229 +++++++++--------- src/views/im/home/store/messageStore.ts | 129 ++++++---- src/views/im/home/store/rtcStore.ts | 2 +- src/views/im/home/store/websocketStore.ts | 20 +- src/views/im/home/types/index.ts | 16 +- src/views/im/utils/db.ts | 43 +++- src/views/im/utils/message.ts | 2 +- src/views/im/utils/storage.ts | 83 ------- src/views/im/utils/user.ts | 11 +- 47 files changed, 641 insertions(+), 566 deletions(-) delete mode 100644 src/views/im/utils/storage.ts diff --git a/.gitignore b/.gitignore index 848638a96..9fc0edc7f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ pnpm-debug auto-*.d.ts .idea .history +output/ diff --git a/package.json b/package.json index 481eca6a1..af0746bc8 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,6 @@ "jsencrypt": "^3.3.2", "jsoneditor": "^10.1.3", "livekit-client": "^2.18.9", - "localforage": "^1.10.0", "lodash-es": "^4.17.21", "markdown-it": "^14.1.0", "markmap-common": "^0.16.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b8218314a..176b6b65f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -104,9 +104,6 @@ importers: livekit-client: specifier: ^2.18.9 version: 2.18.9(@types/dom-mediacapture-record@1.0.22) - localforage: - specifier: ^1.10.0 - version: 1.10.0 lodash-es: specifier: ^4.17.21 version: 4.17.21 @@ -3552,9 +3549,6 @@ packages: resolution: {integrity: sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==} engines: {node: '>= 4'} - immediate@3.0.6: - resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==, tarball: https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz} - immer@9.0.21: resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} @@ -3785,9 +3779,6 @@ packages: lezer-feel@1.4.0: resolution: {integrity: sha512-kNxG7O38gwpuYy+C3JCRxQNTCE2qu9uTuH5dE3EGVnRhIQMe6rPDz0S8t3urLEOsMud6HI795m6zX2ujfUaqTw==, tarball: https://registry.npmmirror.com/lezer-feel/-/lezer-feel-1.4.0.tgz} - lie@3.1.1: - resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==, tarball: https://registry.npmmirror.com/lie/-/lie-3.1.1.tgz} - lilconfig@3.1.2: resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} engines: {node: '>=14'} @@ -3820,9 +3811,6 @@ packages: resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} engines: {node: '>=14'} - localforage@1.10.0: - resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==, tarball: https://registry.npmmirror.com/localforage/-/localforage-1.10.0.tgz} - locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -8993,8 +8981,6 @@ snapshots: ignore@6.0.2: {} - immediate@3.0.6: {} - immer@9.0.21: {} immutable@5.0.3: {} @@ -9188,10 +9174,6 @@ snapshots: '@lezer/lr': 1.4.2 min-dash: 4.2.2 - lie@3.1.1: - dependencies: - immediate: 3.0.6 - lilconfig@3.1.2: {} lines-and-columns@1.2.4: {} @@ -9244,10 +9226,6 @@ snapshots: mlly: 1.7.3 pkg-types: 1.2.1 - localforage@1.10.0: - dependencies: - lie: 3.1.1 - locate-path@5.0.0: dependencies: p-locate: 4.1.0 diff --git a/src/views/im/home/components/ResizableAside.vue b/src/views/im/home/components/ResizableAside.vue index 9ee4b5fca..f8ca4c872 100644 --- a/src/views/im/home/components/ResizableAside.vue +++ b/src/views/im/home/components/ResizableAside.vue @@ -30,7 +30,7 @@ const props = withDefaults( defaultWidth?: number // 默认宽度 minWidth?: number // 最小宽度 maxWidth?: number // 最大宽度 - storageKey: string // localStorage 存储 key,必填;调用方传 StorageKeys.asideWidth(三 Tab 共用一份) + storageKey: string // localStorage 存储 key,必填;调用方传 StorageKeys.localStorage.asideWidth }>(), { defaultWidth: 260, diff --git a/src/views/im/home/components/ToolBar.vue b/src/views/im/home/components/ToolBar.vue index 2ef5e24a7..b9647465a 100644 --- a/src/views/im/home/components/ToolBar.vue +++ b/src/views/im/home/components/ToolBar.vue @@ -76,7 +76,7 @@ const conversationStore = useConversationStore() const friendStore = useFriendStore() const uiStore = useImUiStore() -const totalUnread = computed(() => conversationStore.getTotalUnread) // 消息 Tab 的红点:所有非免打扰会话的未读总和 +const totalUnread = computed(() => conversationStore.getTotalUnreadCount) // 消息 Tab 的红点:所有非免打扰会话的未读总和 const unhandledRequestCount = computed(() => friendStore.getUnhandledRequestCount) // 通讯录 Tab 的红点:未处理好友申请数(接收方=我) const tabs = [ diff --git a/src/views/im/home/components/friend/FriendAddDialog.vue b/src/views/im/home/components/friend/FriendAddDialog.vue index 4f55f6b3f..011a66866 100644 --- a/src/views/im/home/components/friend/FriendAddDialog.vue +++ b/src/views/im/home/components/friend/FriendAddDialog.vue @@ -61,7 +61,7 @@ (() => friendStore.getActiveFriendsLite) +const friends = computed(() => friendStore.getActiveFriendLiteList) /** 完成按钮可点:至少有 1 个非 locked 勾选(locked 是入口锁定项,不算"用户主动选择") */ const canSubmit = computed(() => selectedIds.value.length > 0) @@ -115,7 +115,7 @@ async function handleOk() { if (!group?.id) { throw new Error('创建群失败:未返回群编号') } - // 直接 upsert 进 groupStore,省一次 fetchGroups —— 服务端返回 VO 已经够建会话了 + // 直接 upsert 进 groupStore,省一次 fetchGroupList —— 服务端返回 VO 已经够建会话了 groupStore.upsertGroup({ id: group.id, name: group.name, diff --git a/src/views/im/home/components/group/GroupInfo.vue b/src/views/im/home/components/group/GroupInfo.vue index 522e5eb03..171571f68 100644 --- a/src/views/im/home/components/group/GroupInfo.vue +++ b/src/views/im/home/components/group/GroupInfo.vue @@ -80,7 +80,7 @@ const members = ref([]) * 是否已加群:基于"自己确实在成员列表里"判断 * - 缓存未命中:直接 false(陌生群) * - 命中且 members 已拉:精准查 self.userId 在不在 - * - 命中但 members 未拉:fetchGroups 接口语义即「我加入的群」,命中视为 member(拉成员后会自动收敛) + * - 命中但 members 未拉:fetchGroupList 接口语义即「我加入的群」,命中视为 member(拉成员后会自动收敛) */ const isMember = computed(() => { if (!props.group?.id) { @@ -117,7 +117,7 @@ watch( if (!id || !member) { return } - const list = await groupStore.fetchGroupMembers(id) + const list = await groupStore.fetchGroupMemberList(id) if (props.group?.id !== id) { return } diff --git a/src/views/im/home/components/group/GroupMemberAddDialog.vue b/src/views/im/home/components/group/GroupMemberAddDialog.vue index 89e619732..04ebdd57d 100644 --- a/src/views/im/home/components/group/GroupMemberAddDialog.vue +++ b/src/views/im/home/components/group/GroupMemberAddDialog.vue @@ -84,7 +84,7 @@ const members = computed(() => { }) /** 全量好友:直接复用 friendStore Lite 视图 */ -const friends = computed(() => friendStore.getActiveFriendsLite) +const friends = computed(() => friendStore.getActiveFriendLiteList) /** 已在群里的好友 id:传给 Panel 的 disabledIds 置灰 + 不计入已选 */ const disabledIds = computed(() => diff --git a/src/views/im/home/components/group/GroupRequestListDialog.vue b/src/views/im/home/components/group/GroupRequestListDialog.vue index a9e0093bf..dcb19f6d2 100644 --- a/src/views/im/home/components/group/GroupRequestListDialog.vue +++ b/src/views/im/home/components/group/GroupRequestListDialog.vue @@ -273,7 +273,7 @@ async function handleAgree(item: ImGroupRequestRespVO) { if (actingId.value !== null) return actingId.value = item.id try { - await groupRequestStore.agreeRequest(item.id) + await groupRequestStore.agreeGroupRequest(item.id) updateLocalResult(item.id, ImGroupRequestHandleResult.AGREED) message.success('已同意') } finally { @@ -293,7 +293,7 @@ async function handleRefuse(item: ImGroupRequestRespVO) { } actingId.value = item.id try { - await groupRequestStore.refuseRequest(item.id, handleContent || undefined) + await groupRequestStore.refuseGroupRequest(item.id, handleContent || undefined) updateLocalResult(item.id, ImGroupRequestHandleResult.REFUSED) message.success('已拒绝') } finally { diff --git a/src/views/im/home/components/rtc/RtcCallContainer.vue b/src/views/im/home/components/rtc/RtcCallContainer.vue index a53f27272..f87d366de 100644 --- a/src/views/im/home/components/rtc/RtcCallContainer.vue +++ b/src/views/im/home/components/rtc/RtcCallContainer.vue @@ -77,7 +77,7 @@ import { ImConversationType } from '@/views/im/utils/constants' import { RTC_NO_ANSWER_CALL_CHECK_INTERVAL_MS } from '@/views/im/utils/config' -import { getCurrentUserId } from '@/views/im/utils/storage' +import { getCurrentUserId } from '@/views/im/utils/user' import { getSenderAvatar, getSenderDisplayName } from '@/views/im/utils/user' import { Track } from 'livekit-client' import RtcCallInviting from './RtcCallInviting.vue' diff --git a/src/views/im/home/components/rtc/RtcCallMemberPickerDialog.vue b/src/views/im/home/components/rtc/RtcCallMemberPickerDialog.vue index 214159c0a..f2f390b31 100644 --- a/src/views/im/home/components/rtc/RtcCallMemberPickerDialog.vue +++ b/src/views/im/home/components/rtc/RtcCallMemberPickerDialog.vue @@ -28,7 +28,7 @@