diff --git a/resources/ai-kb/zh/howto/messenger/recall.md b/resources/ai-kb/zh/howto/messenger/recall.md index f665401f1..225f1a9c8 100644 --- a/resources/ai-kb/zh/howto/messenger/recall.md +++ b/resources/ai-kb/zh/howto/messenger/recall.md @@ -62,7 +62,7 @@ last_verified: v1.8.69 - 仅撤回**文本消息**(含 Markdown)时出现「你撤回了一条消息 **重新编辑**」占位 - 占位只有自己可见,且只保存在执行撤回操作的这台设备本地(换设备、其他成员都看不到) - 撤回后 **5 分钟内**有效,过期自动消失 -- 点「重新编辑」:原内容回填到输入框(会覆盖输入框中已有内容),占位随即消失 +- 点「重新编辑」:原内容回填到输入框(会覆盖输入框中已有内容);占位不会因此消失,5 分钟内可反复点击,到期才自动消失 ## 与「编辑」的区别 diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index c9071dca7..f32f66434 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -3786,6 +3786,20 @@ export default { loading: true, onOk: () => { return new Promise((resolve, reject) => { + // 请求前预存撤回记录:原消息还在列表时占位被去重压制不显示, + // 无论 WS 推送还是接口响应先移除消息,占位都在同一次列表重算中原地顶上,避免先删后加的闪动 + const preSaved = operateItem.type === 'text' && !!$A.getObject(operateItem.msg, 'text'); + if (preSaved) { + this.$store.dispatch("saveDialogWithdraw", { + id: operateItem.id, + dialog_id: operateItem.dialog_id, + prev_id: operateItem.prev_id, + msg: { + type: $A.getObject(operateItem.msg, 'type'), + text: $A.getObject(operateItem.msg, 'text'), + }, + }); + } this.$store.dispatch("call", { url: 'dialog/msg/withdraw', data: { @@ -3793,20 +3807,13 @@ export default { }, }).then(() => { resolve("消息已撤回"); - if (operateItem.type === 'text' && $A.getObject(operateItem.msg, 'text')) { - this.$store.dispatch("saveDialogWithdraw", { - id: operateItem.id, - dialog_id: operateItem.dialog_id, - prev_id: operateItem.prev_id, - msg: { - type: $A.getObject(operateItem.msg, 'type'), - text: $A.getObject(operateItem.msg, 'text'), - }, - }); - } this.$store.dispatch("forgetDialogMsg", operateItem); }).catch(({msg}) => { reject(msg); + // 撤回失败且消息未被删除(排除"接口报错但服务端实际已撤回")才清除预存记录 + if (preSaved && this.dialogMsgs.some(item => item.id == operateItem.id)) { + this.$store.dispatch("forgetDialogWithdraw", {id: operateItem.id}); + } }); }) } @@ -3825,7 +3832,6 @@ export default { this.$refs.input.setContent(text.replace(/\{\{RemoteURL\}\}/g, $A.mainUrl())) } !this.windowTouch && this.inputFocus() - this.$store.dispatch("forgetDialogWithdraw", {id: source.id}) }, onViewReply(data) {