YunaiV
|
b455ce4949
|
✨ feat(im): 优化 rtcStore 的命名
|
2026-05-14 22:15:35 +08:00 |
YunaiV
|
4a811fb0bb
|
✨ feat(im): 评审下 rtcStore 的实现
|
2026-05-14 17:16:46 +08:00 |
YunaiV
|
e579a4de13
|
✨ feat(im): 优化 rtc 整体弹窗界面
|
2026-05-14 09:44:39 +08:00 |
YunaiV
|
a170ae37ab
|
✨ feat(im): 优化消息的 format 相关的逻辑,从 user 抽到 message 工具类里,更加统一
|
2026-05-13 23:27:02 +08:00 |
YunaiV
|
841d2cb763
|
✨ feat(im): 统一 im 的 api 风格,保持一致性
|
2026-05-13 22:58:09 +08:00 |
YunaiV
|
18e5c97bf3
|
✨ feat(im): 将后端的 roomName 和 callId 融合,简化字段和逻辑(一致性更好、概念更简洁)
|
2026-05-12 20:29:08 +08:00 |
YunaiV
|
38cb980ce4
|
✨ feat(im): 完善 rtc 的后端代码逻辑,各种代码风格的优化
|
2026-05-12 13:17:04 +08:00 |
YunaiV
|
750f25410c
|
✨ feat(im): 基于 livekit 构建 im 通话(语音聊天、视频聊天、共享桌面)v0.1:推进中
|
2026-05-09 15:23:07 +08:00 |
YunaiV
|
e12596ad7c
|
♻️ refactor(im): 移动 IM 相关 API 引用至新路径
|
2026-05-09 01:25:03 +08:00 |
YunaiV
|
2935d7d112
|
✨ feat(im): 拆出私聊 / 群聊已读两个全局开关,关闭后禁用接口与所有 UI 入口(含群回执)
ImProperties.message 新增 privateReadEnabled / groupReadEnabled,前端 config.ts 同步镜像。关闭后:
- 后端:read 系列接口(read / getMaxReadMessageId / getGroupReadUserIds)抛业务异常;sendGroupMessage 强制 NO_RECEIPT 忽略 receipt=true;pull 群消息跳过 Redis 已读游标读取与 readCount 补齐
- 前端:气泡已读标签 / 群回执 popover / 「发送回执消息」下拉入口 / admin 列表「状态」「回执」列与详情对应字段按开关隐藏;自动上报 / 冷启动同步对方已读位置 / WS READ & RECEIPT handler 全部按开关短路兜底,避免打到禁用接口
- 单测:补 @Spy ImProperties 修复原本就在的 NPE,加 disabled 分支断言
|
2026-05-09 01:07:18 +08:00 |
YunaiV
|
46b06b0444
|
【新增】IM:群头像支持成员头像九宫格兜底
群头像为空时,取前 9 个成员头像在 Canvas 上拼九宫格 dataURL;空头像 / 加载失败的格子画跟 UserAvatar 同款色卡(首字 + charCode 哈希调色板)。
- 新增 GroupAvatar 组件包一层 UserAvatar;按容器 size × DPR 自适应画布像素,避免 retina 屏糊
- utils/group.ts 加 buildGroupAvatar 与 LRU 缓存 facade(上限 200);utils/image.ts 抽公共 loadImage;utils/user.ts 抽 getAvatarText / getAvatarBgColor 供 UserAvatar 与拼图共用
- GroupItem / GroupInfo / ConversationItem / ConversationPickerPanel 按会话类型分支换用 GroupAvatar
|
2026-05-08 18:28:02 +08:00 |
YunaiV
|
70e7a1c900
|
【新增】IM:群头像支持成员头像九宫格兜底
群头像为空时,取前 9 个成员头像在 Canvas 上拼九宫格 dataURL;空头像 / 加载失败的格子画跟 UserAvatar 同款色卡(首字 + charCode 哈希调色板)。
- 新增 GroupAvatar 组件包一层 UserAvatar;按容器 size × DPR 自适应画布像素,避免 retina 屏糊
- utils/group.ts 加 buildGroupAvatar 与 LRU 缓存 facade(上限 200);utils/image.ts 抽公共 loadImage;utils/user.ts 抽 getAvatarText / getAvatarBgColor 供 UserAvatar 与拼图共用
- GroupItem / GroupInfo / ConversationItem / ConversationPickerPanel 按会话类型分支换用 GroupAvatar
|
2026-05-08 18:27:53 +08:00 |
YunaiV
|
c5b082ca80
|
♻️ refactor(im): 业务策略数值从 ImCommonConstants 上移到 ImProperties(按 group / message 子模块分组),常量类仅保留 AT_USER_ID_ALL 协议契约值
♻️ refactor(im): 抽出 utils/config.ts 集中数值常量,按业务域统一前缀(GROUP_ / MESSAGE_ / FRIEND_ / CONVERSATION_ / FORWARD_),constants.ts 只留协议枚举与契约值
|
2026-05-08 17:42:13 +08:00 |
YunaiV
|
dfd5b39a17
|
feat(im): MessageForwardDialog 接入「创建聊天」分支 + 收尾打磨
- MessageForwardDialog 加 view: 'conversation' | 'contact' 切换:
- 模板按 view 切 ConversationPickerPanel / FriendPickerPanel;dialog header 用 slot 渲染「← 返回」
- handleSwitchToContact 切 view + 清留言(避免不可见输入框留言被静默发出)
- handleCreateGroupAndSend 复用 forwardToTarget(newConversation),merge / single 都按 mode 自动跑
- 成功 / 失败统一末尾退多选 + 关弹窗,避免源会话遗留多选态
- 顺手清掉 GroupMemberAddDialog / MessageForwardDialog 末尾多余空行
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-05-08 16:16:01 +08:00 |
YunaiV
|
312df4c73d
|
refactor(im): 抽象 IM 选择类弹窗为 PickerPanel 体系,对齐微信 PC
- 拆「业务壳 + 纯 PickerPanel」两层;13 个 dialog 统一 ref + open(opts) 接口
- 新增 FriendPickerPanel / ConversationPickerPanel / GroupMemberPickerPanel
- 抽 useFriendBuckets / useSelectedItems composable + buildDefaultGroupName / picker-dialog.scss mixin
- conversationStore 加 recentForwardConversationKeys 系列 action(持久化到 IDB)
- 三态语义固化:hide > locked > disabled
- 圆形勾选用微信绿;主按钮跟随项目主题色;最近转发横向头像 + 移除模式
- 删 GroupMemberSelector(由 GroupMemberPickerPanel 替代)/ FriendLite.deleted 死字段
- 配套:project_duibiao/im/dialog-picker-{contract,wechat-compare}.md
|
2026-05-08 14:06:48 +08:00 |
YunaiV
|
40ac2daca8
|
✨ feat(im):文本气泡 @ 高亮支持点击 + URL 自动识别成可点击链接
- @ 段:群消息按 atUserIds 反查群成员,候选 name 兼容历史字面量(真实昵称 / 好友备注 / 群自定义昵称),displayName 统一收敛到 nickname,让历史消息也能渲染成 @真实昵称;@ 段点击弹 UserInfoCard
- @所有人:注入 IM_AT_ALL_USER_ID 虚拟候选,对齐微信 PC 仅高亮配色不挂点击
- 同名歧义:同字面量对应多个 userId 时标记 ambiguous,parser 整段消费成普通文本,避免错绑用户
- URL:识别 http(s) / www. 起头链接,<a target="_blank"> 新标签打开;默认补 https://
- TipSegment 加 link 变体作为统一文本片段类型,TEXT 气泡与灰条 tip 共用 TipSegments 组件渲染
- MessageInput @ token 文本统一用真实昵称,不再掺好友备注 / 群自定义昵称
|
2026-05-08 01:23:09 +08:00 |
YunaiV
|
094ab44094
|
🎨 refactor(im): joinMentionSegments 用 flatMap 替代命令式 push
少一个可变 out + 命令式 forEach,意图更直观
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
2026-05-07 23:59:00 +08:00 |
YunaiV
|
9eb221e8d2
|
✨ feat(im): 灰条 tip 文案的 mention 段支持点击弹 UserInfoCard
群广播 / 撤回 / 好友事件 tip 文案从纯字符串拆成 TipSegment[],mention
段携带 userId,渲染层挂点击 → uiStore.openUserInfoCardAtEvent。
- utils/message.ts:加 TipSegment 协议 + 零依赖 helper
- utils/user.ts、utils/conversation.ts:加 segments builder,string 版
改写为 segmentsToText 包装,避免 case 表分叉
- TipSegments.vue:按 activeConversation 推断 addSource,群里走
GROUP+群名、私聊走 SEARCH;nickname 不传备注避免 UserInfo 首屏闪
- MessageItem.vue / MessageHistory.vue:tip 块切 <TipSegments>
顺手补:utils/constants.ts 新增 SystemUserSexEnum,替换 IM 模块 sex
硬编码 1 / 2
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
2026-05-07 23:46:50 +08:00 |
YunaiV
|
5b85a4c469
|
✨ feat(im): 浏览器标签 title 拼上未读数前缀
|
2026-05-07 22:17:03 +08:00 |
YunaiV
|
7fa1dbc55c
|
🐛 fix(im): 当前打开的会话在列表里不再展示 [草稿] 前缀
|
2026-05-07 21:55:45 +08:00 |
YunaiV
|
cc93b8a742
|
✨ feat(im): 初始化消息转发 v0.4:第四次评审(语音播放器资源释放打磨)
agent 三轮复审后的质量打磨,无功能变更。
- useVoicePlayer.stop:audio.removeAttribute('src') + audio.load() 替代 audio.src = '';不会触发空 src 加载的 error 事件,也能让浏览器立即释放底层 decoder buffer
- useVoicePlayer.play:同 key 再点的 stop() 改 stop(key),意图自解释(我想停的就是我自己)
- useVoicePlayer 移除未消费的 currentKey 暴露;调用方都走 isPlaying(key) 派生
- home/index.vue onUnmounted 追加 voicePlayer.stop():模块级单例 audio 不会随视图卸载自动停,补主壳兜底
|
2026-05-07 21:46:33 +08:00 |
YunaiV
|
0b07091e79
|
🐛 fix(im): 修复切会话 watch 仅监听 targetId 导致私聊与群聊 id 同号时不触发
home/index.vue 已读 watch、MessagePanel 滚动 / 侧栏 / 群资料预拉 watch 都只看 targetId,
私聊 1 切群 1 时不会触发,会把侧栏 / 新消息浮窗 / 滚动状态 / 已读上报漏掉,且不跑 ensureGroupData。
对齐多选 + 语音那两条 watch,统一改成监听 [type, targetId]。
|
2026-05-07 21:26:40 +08:00 |
YunaiV
|
0323566878
|
✨ feat(im): 初始化消息转发 v0.3:第三次评审(语音播放全局互斥)
新点的语音停掉旧的,对齐微信 PC 语义;一次只播一条,主面板 / 历史抽屉 / 合并详情共享同一播放态,避免多窗口同时出声。
- 新增 useVoicePlayer composable:模块级单例 currentTask + play / stop;ended / error / play().catch 全部 once: true 收尾,避免 listener 泄漏;play(key, url) / stop(key?) / isPlaying(key) 以 Symbol 当播放身份
- MessageBubble setup 里 Symbol('im-message-bubble-voice') 生成实例级 voiceKey;voicePlaying 改成派生 computed,移除本地 currentAudio
- MessageBubble 卸载兜底:调 voicePlayer.stop(voiceKey) 仅停自己;防止删除消息 / 历史抽屉切筛选导致气泡消失但 audio 仍在响;不会误伤别处仍可见的同 url 气泡
- MessagePanel 切会话 watch 追加 voicePlayer.stop()
- MessageHistory 关闭抽屉 watch 追加 voicePlayer.stop()
- MessageMergeDetailDialog handleClose 追加 voicePlayer.stop()
|
2026-05-07 21:26:12 +08:00 |
YunaiV
|
82d065c270
|
✨ feat(im): 初始化消息转发 v0.2:第二次优化部分代码(一些工具类等)
|
2026-05-07 20:34:09 +08:00 |
YunaiV
|
cf01143632
|
✨ feat(im): 初始化消息转发 v0.1:第一次评审
|
2026-05-07 19:47:27 +08:00 |
YunaiV
|
9bcdc92806
|
✨ feat(im): 初始化群名片 v0.2:第二次评审(需求各种进群的小问题)
|
2026-05-07 19:07:37 +08:00 |
YunaiV
|
f5936a6e7f
|
✨ feat(im): 初始化群名片 v0.2:第二次评审(需求各种进群的小问题)
|
2026-05-07 18:01:43 +08:00 |
YunaiV
|
d175fe86be
|
✨ feat(im): 初始化群名片 v0.2:第二次评审(需求各种进群的小问题)
|
2026-05-07 17:28:16 +08:00 |
YunaiV
|
ce66a507ef
|
✨ feat(im): 初始化群名片 v0.2:第二次评审(需求各种进群的小问题)
|
2026-05-07 17:25:03 +08:00 |
YunaiV
|
65d5aacac9
|
✨ feat(im): 初始化群名片 v0.1:第一次评审
|
2026-05-07 13:07:56 +08:00 |
YunaiV
|
808ad575fc
|
✨ feat(im): 初始化群申请 v0.5:第六把 review(性能 / 健壮性 / 简洁度收口)
后端
- createInviteRequestList N+1 → 3 SQL:批量 select IN + update IN + insertBatch;20 人邀请从 40 RTT 降到 3 RTT
- service 不再出现 mybatis:复用记录的 update(null, wrapper) 下沉到 Im{Group,Friend}RequestMapper.update*Reset helper
- inviteGroupMember 入参去重切 hutool:CollUtil.subtractToList(CollUtil.distinct(...), activeMemberUserIds)
- 删除 dead 字段 inviterUserId(GroupRequestApprovedNotification / GroupRequestRejectedNotification):前端不再消费
前端
- 1505 / 1506 通知改静默:同意走群事件 1509 / 1510 渲染系统提示,拒绝不再打扰
- 修竞态:addByRequestId 校验 handleResult === UNHANDLED,避免 1503 在途时被 1505 / 1506 抢先后又把已处理记录塞回未处理列表
- 修复 dialog 复用记录刷新:watch key 含 inviterUserId / applyContent,同 id 不同内容也触发 refetch;actingId 期间跳过避免本端动作多余 RTT
- 修复 willGoApproval 误报:group.ownerUserId 兜底群主;members 未到位时保守按非审批处理
- unhandledCountMap memoized getter:O(N) 扫一次缓存到 Map,ConversationItem 直读 Map 消除 O(N×M) 重复 filter
|
2026-05-07 08:13:27 +08:00 |
YunaiV
|
cb26df3ca1
|
✨ feat(im): 初始化群申请 v0.4:第五把 review(多轮 finding 修复 + 通知静默化)
- 邀请路径写 addSource=INVITE;群主 / 管理员邀请绕过审批;inviteGroupMember 入参去重
- getGroupRequest 越权校验加成员有效状态判断;新增 list-by-group 接口
- 申请列表按 update_time 倒序,update(null, wrapper) 路径手动刷 updateTime
- addByRequestId 不再 skip 同 id,复用记录刷新并置顶
- GroupRequestListDialog 单群模式订阅 store 增量同步;GroupMemberAddDialog 审批分支文案区分
- ConversationItem 增加 [X 条进群申请] 红字前缀;MessagePanel 顶部胶囊横幅
- 1505 / 1506 通知改静默:同意走群事件渲染系统提示,拒绝不再打扰;清掉 dead inviterUserId 字段
|
2026-05-07 00:51:48 +08:00 |
YunaiV
|
b2ba42049b
|
✨ feat(im): 初始化群申请 v0.3:第四把 review(优化界面,进一步对齐微信界面)【之前提交错了】
|
2026-05-06 23:57:54 +08:00 |
YunaiV
|
f746aebe08
|
✨ feat(im): 初始化群申请 v0.3:第四把 review(优化界面,进一步对齐微信界面)
|
2026-05-06 23:57:03 +08:00 |
YunaiV
|
0eca952c6a
|
✨ feat(im): 初始化表情包 v0.3:第四把 review(增加表情管理的界面)
|
2026-05-06 23:00:08 +08:00 |
YunaiV
|
a98e32554c
|
✨ feat(im): 初始化表情包 v0.2:第三把 review
|
2026-05-06 21:08:46 +08:00 |
YunaiV
|
2f513f7b8f
|
✨ feat(im): 初始化群申请 v0.2:第三把 review
|
2026-05-06 20:51:45 +08:00 |
YunaiV
|
8eebfd4744
|
✨ feat(im): 初始化表情包 v0.1:第二把 review
|
2026-05-06 20:50:55 +08:00 |
YunaiV
|
1ed5dc7e6a
|
✨ feat(im): 初始化表情包 v0.0:第一把 review
|
2026-05-06 19:42:19 +08:00 |
YunaiV
|
8fc5273a88
|
✨ feat(im): 初始化群申请 v0.1:第二把 review
|
2026-05-06 18:52:30 +08:00 |
YunaiV
|
3be0daf115
|
✨ feat(im): 初始化群申请 v0.0:第一把 review
|
2026-05-06 14:53:47 +08:00 |
YunaiV
|
4868d69ed8
|
✨ feat(im): 优化名片消息类型 v0.4:增加转发成功失败的提示
|
2026-05-06 12:18:31 +08:00 |
YunaiV
|
1ac0650984
|
♻️ refactor(im):注释对齐 + patchMessage 复用 applyServerMessageUpdate
- recomputeConversationLast / videoCoverUrl / showSendingLoading 三处 JSDoc 跟实现对齐:
原描述还停留在旧设计(lastSendTime 不重算 / 占位 coverUrl 用 blob / 「外层 loading 多余」),
这轮一并改成当前事实,避免后续维护被误导
- patchMessage 删手写 revoke + Object.assign,改调 applyServerMessageUpdate,
与 ackMessage / insertMessage(existingIndex) 共用一份服务端字段合并语义;
「值未变早返回」保留在 patchMessage 顶部
- 抽 BLOB_URL_PREFIX 常量替代散落在 utils/message.ts 与 useMediaUploader.ts 的 3 处 'blob:' 字面量
|
2026-05-06 10:38:43 +08:00 |
YunaiV
|
30d695d702
|
🐛 fix(im):codex 评审修复发送中状态边角
- recomputeConversationLast 空 messages 时一并清 lastSendTime,
避免刷新后被 drop 的媒体占位让空会话仍按旧时间排在列表前面
- 视频占位 coverUrl 不再赋 blob URL:<video poster> 期待图片资源,
传 video blob 在部分浏览器会退化成黑底,cover 等 probe 出真实 URL 后由 commit 阶段一起 patch
- useMediaUploader 暴露 requireMediaHandler typed accessor,
消除 video 链路 mediaTypeHandlers[VIDEO]! 非空断言
- MessageItem 把外层 loading 的 (!isUploading || isVoice) 抽成 showSendingLoading computed
|
2026-05-06 10:18:49 +08:00 |
YunaiV
|
459eaa5428
|
♻️ refactor(im): 优化消息存储逻辑,减少不必要的处理
改进消息存储时的处理逻辑,通过提前检查是否存在 _localFile 来优化性能,避免不必要的全量映射操作。
|
2026-05-06 08:50:13 +08:00 |
YunaiV
|
59aab8ecdc
|
✨ feat(im): 优化名片消息类型 v0.3:增加表情选择
|
2026-05-06 08:47:18 +08:00 |
YunaiV
|
b17f7a57e5
|
✨ feat(im): 优化发送中的能力 v0.2:简化各种 kind、复用各种逻辑
|
2026-05-06 08:46:33 +08:00 |
YunaiV
|
957a63f8f4
|
✨ feat(im): 优化名片消息类型 v0.2:优化转发弹窗的界面样式
|
2026-05-06 08:33:03 +08:00 |
YunaiV
|
c15d75ba91
|
✨ feat(im): 优化发送中的能力 v0.1:各种清理时的边界
|
2026-05-06 08:22:41 +08:00 |
YunaiV
|
3836467481
|
✨ feat(im): 优化名片消息类型 v0.1:补充缺失的名片展示
|
2026-05-06 08:21:52 +08:00 |