SpringBoot3+Flowable+IM 审批打通在线聊天:催办、沟通不用切微信,点办理人直接对话
🌐 文档地址:https://ruoyioffice.com
📦 源码1·GitHub:https://github.com/yuqing2026/ruoyi-office
📦 源码2·GitCode:https://gitcode.com/zhouzhongyan/ruoyi-office
📦 源码3·Gitee:https://gitee.com/yqzy1688/ruoyi-office
💬 微信:17156169080(备注「RuoYi Office」)
催审批还在复制姓名去微信搜人,会话和待办对不上号。RuoYi Office 把开聊钉在任务表办理人格子上:点「与审批人沟通」,只带这个人的 userId。完整 IM 先认好友,轻聊进
/oa/im,聊完待办还在。底栏评论是另一套盒子,不要点错。
▲ 用车单停在李经理。虚线从办理人格子甩出三句私聊:发票补上了、聊天过不了单、不用切微信。底栏通过 / 拒绝还在
引言:催办若只是再开一个聊天 App,单据会丢
企业里「问一句油费」看起来像即时通讯功能,落地时却会拆成四件互不相让的事:从哪点、跟谁聊、走哪套 IM、聊完任务还在不在。四件塞进底栏同一个气泡图标,评论、拒绝意见和私聊会互相踩。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
正确的形状是:任务表格子只负责指出这个人;开聊助手只负责通道和好友;任务完成仍走同意 / 拒绝。 昨天那篇写资料卡拨打和 LiveKit 房间,本篇只写「点办理人进私聊」。不要把两篇读成一篇 IM 大全。
连接性也要画清:Vue3 从 assigneeUser.id 取出人;租户 imMode 决定走 /im/home 还是 /oa/im;完整 IM 先 getFriend,不是好友就发「工作沟通」。少任何一环,都会变成「点了没反应」或「聊完待办消失了」。
不要写成「会话顶栏挂着这张单」。当前实现是带着人,不带着单。单据还停在原来的待办页。
一、先把三套字和两个入口画清
1.1 评论、意见、私聊不是同一个图标
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
reason 跟任务走
|
|
|
|
|
09-01 那篇流程评论已经写过前两套。本篇只写第三套。底栏那个 message-circle 是评论,格子里那个 message-circle-more 才是开聊。图标长得像,职责不能并。
1.2 两种 IM,开聊要认租户开关
|
|
|
|
|---|---|---|
|
|
/oa/im |
router.push,带 conversationId
|
|
|
/im/home |
window.open
type + targetId
|
开关来自登录权限里的 imMode,写入 office-im store。isIm 为真才走完整 IM。客户只要审批旁边问一句油费,不要上 LiveKit,也不要弹资料卡视频按钮。
1.3 手机审批详情暂时没有同按钮
UniApp 待办详情能看单、能通过拒绝,格子旁没有「与审批人沟通」。标题因此不加 UniApp。若演示站能续上同一私聊,手机只用来证明「聊出去的是会话,不是通话页」。不要把移动端画成已经对齐。
二、系统设计
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/im/home
|
|
|
|
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
assigneeUser
ownerUser
|
|
|
|
|
|
|
|
|
|
|
|
|
|
三、PC 端:从格子点到会话
3.1 任务表办理人旁的按钮
待办详情里,任务列表不是只读轨迹。审批人列把昵称和开聊画在同一格。有 id 才出按钮,没人办理的节点不画空图标。
▲ 合同待办详情。底栏「评论」是流程评论;开聊在「审批信息」任务表办理人格子,不在这排按钮里
3.2 点开后的私聊
完整 IM 会新开 /im/home 会话窗,对方是刚才那个人。轻聊则仍在本页切到 /oa/im。两种形态都不要指望顶栏出现单据编号。
▲ /im/home 会话列表。任务表格子只带 userId,顶栏不会出现单据编号
3.3 对照底栏评论
同一张办理页,底栏再点「评论」,弹出的是流程评论表单。发一条之后任务状态仍是审批中——和私聊一样不办结,但字留在时间线,不进 IM。
▲ 「流程评论」Tab。系统自动写过一条通过原因。发评论不 completeTask,和私聊同一条红线
四、通道怎么分,好友怎么拦
startConversationWithUser 只传 userId。另有一条 startConversationFromProcessInstance 会先拉审批详情再猜对象,给通知跳转用;任务表格子不走那条,避免「猜错人」。
租户开了完整 IM,助手不再创建轻聊会话,改去查好友。查到就新窗打开;查不到就申请,文案写死「工作沟通」。自动通过未开时,申请人只能等到对方点头。
手机审批详情没有同按钮。若要在手机上续聊,从消息 Tab 进已经存在的会话即可。不要在移动端审批底栏临时画一个电话键,那会和昨天的 LiveKit 入口搅在一起。
五、后端与前端核心实现
任务表不调业务单据接口。它只读流程任务上的办理人,再把 id 交给助手。
function getApproverUser(row: BpmTaskApi.TaskManager) {return row.assigneeUser || row.ownerUser;}async function handleStartConversation(row: BpmTaskApi.TaskManager) {const approverUser = getApproverUser(row);if (!approverUser?.id) {return;}await startConversationWithUser(Number(approverUser.id));}
格子只认人。formId 那一列的「查看表单」是另一件事,不要把开聊绑到表单按钮上。
助手先拦自己点自己,再按 imMode 分流。轻聊创建会话时,通知跳转可以塞 processInstanceId;任务表这条路径故意不塞,避免轻聊顶栏出现半截单据名。
export async function openEmployeeChat(targetUserId: number,extraQuery?: Record<string, number | string | undefined>,) {const currentUserId = Number(useUserStore().userInfo?.id || 0) || undefined;if (currentUserId && targetUserId === currentUserId) {message.warning('当前审批人为自己,无需发起单聊');return;}if (useOfficeImStore().isIm) {await openFullImWithUser(targetUserId);return;}const conversation = await createSingleConversation({ targetUserId });await router.push({name: 'OaImIndex',query: { conversationId: conversation.id, ...extraQuery },});}
完整 IM 的好友门禁必须先查再申请。申请失败或对方未自动通过,只 toast,不打开空会话。
async function openFullImWithUser(targetUserId: number) {try {const friend = await getFriend(targetUserId);if (friend?.friendUserId) {openImHomeConversation(targetUserId);return;}} catch {// 非好友:发申请}try {await applyFriendRequest({toUserId: targetUserId,applyContent: '工作沟通',addSource: ImFriendAddSource.SEARCH,});} catch {message.info('已发送好友申请,对方通过后即可聊天');return;}message.info('已发送好友申请,对方通过后即可聊天');}
登录时 authPermissionInfo.imMode 写入 store。没有这个字段,默认按轻聊处理,审批找人不会弹摄像头。
六、几个容易做错的点
不要把开聊画进流程图 Viewer。 Viewer 是看节点颜色的,点节点不应弹出微信式聊天。入口只在任务表。
不要让聊完触发 completeTask。 发 IM 和发评论同一条红线:字可以走,任务不能走。结论只认通过 / 拒绝。
不要在完整 IM 里跳过好友。 组织里能看见这个人,不等于已经是好友。跳过申请会撞上会话接口 403,按钮像坏了。
不要给只开轻聊的客户露出视频键。 轻聊会话没有 LiveKit。催办问油费,不该弹出摄像头授权。
不要宣称手机审批已经对齐。 移动端详情现在没有同按钮。写进文档当规划可以,写成已上线会挨打。
七、数据结构
开聊本身不落一张「审批会话」表。认的是已有的人、好友和会话。
任务行:assigneeUser / ownerUser 带 id 和昵称。没有这两人,格子不渲染按钮。
好友:getFriend(targetUserId) 认 friendUserId。没有就走申请,applyContent 固定「工作沟通」,来源是搜索。
轻聊会话:createSingleConversation({ targetUserId }) 返回 conversationId。完整 IM 不走这条,改用 type=PRIVATE + targetId。
imMode:登录权限字段,值是 im 或空。空当轻聊。不要把这个开关写进每张单据。
八、技术亮点
|
|
|
|
|---|---|---|
|
|
|
|
|
|
startConversationWithUser |
|
|
|
|
|
|
|
|
|
|
|
office-im.isIm |
|
|
|
|
|
|
|
window.open/im/home |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
startConversationFromProcessInstance |
|
九、快速体验
在线演示:https://ruoyioffice.com/web/(账号 admin / admin123)
-
打开流程中心待办,进一张审批中的详情。 -
找到任务表「审批人」列,看办理人右侧气泡。 -
点「与审批人沟通」。完整 IM 应新开会话;轻聊应跳到 /oa/im。 -
发一句「附件补了」,回到待办详情,任务状态仍应是审批中。 -
再点底栏「评论」,确认弹的是评论表单,不是同一个会话。 -
若对方还不是好友,应看到「已发送好友申请」,而不是空白窗。 -
进 /oa/im轻聊核对这些会话没有视频按钮。
演示站公共数据只看、少改。认的是「格子能开聊、聊完待办还在」,不是死背某个办理人姓名。
源码仓库:GitHub:https://github.com/yuqing2026/ruoyi-office | GitCode:https://gitcode.com/zhouzhongyan/ruoyi-office | Gitee:https://gitee.com/yqzy1688/ruoyi-office
十、结语
审批催办的难度不在会不会发消息,而在从哪点、跟谁聊、聊完任务还在不在。RuoYi Office 把开聊钉在办理人格子上,只带 userId,通道看租户,好友先申请,结论仍走同意 / 拒绝。底栏评论负责留痕,资料卡拨打负责通话,三件事不要做成一个图标。
读者能带走的三句:入口认格子,不认底栏气泡;带着人,不带着单;聊完不等于同意。
你们现在催审批是切微信搜姓名,还是待办里能直接点人?评论区对照一下轻聊和完整 IM,比空泛「上了即时通讯」有用。
相关阅读:同目录流程评论讲三套字;音视频通话讲 LiveKit 房间。那些文章不替代本页的格子和好友门禁。
💡 想要体验 RuoYi Office 的强大功能?
🌐 在线演示:https://ruoyioffice.com/web/(账号 admin / admin123)
📦 源码仓库:GitHub:https://github.com/yuqing2026/ruoyi-office | GitCode:https://gitcode.com/zhouzhongyan/ruoyi-office | Gitee:https://gitee.com/yqzy1688/ruoyi-office
💬 技术咨询:添加微信 17156169080,备注「RuoYi Office」
⭐ 如果觉得不错,请给个 Star 支持一下!

