@@ -978,6 +979,7 @@ export default {
'dialogMsgs',
'dialogTodos',
'dialogMsgTops',
+ 'dialogWithdraws',
'dialogMsgTransfer',
'dialogMsgKeep',
'dialogIns',
@@ -1069,6 +1071,13 @@ export default {
return this.tempMsgs.filter(item => item.dialog_id == this.dialogId);
},
+ withdrawMsgList() {
+ if (!this.isReady) {
+ return [];
+ }
+ return this.dialogWithdraws.filter(item => item.dialog_id == this.dialogId);
+ },
+
allMsgList() {
if (this.isStaticMode) {
return this.staticMsgs || []
@@ -1088,6 +1097,25 @@ export default {
array.push(...tempMsgList)
}
}
+ if (this.withdrawMsgList.length > 0 && !this.msgType && !this.msgId) {
+ const ids = array.map(({id}) => id)
+ const minId = ids.length > 0 ? Math.min(...ids) : 0
+ // 撤回占位仅在已加载消息范围内显示,避免干扰向上翻页的 prev_id 判断
+ const withdrawMsgList = this.withdrawMsgList
+ .filter(item => !ids.includes(item.id) && (ids.length === 0 || item.id > minId))
+ .map(item => ({
+ id: item.id,
+ dialog_id: item.dialog_id,
+ prev_id: item.prev_id,
+ type: 'withdraw',
+ userid: this.userId,
+ msg: item.msg,
+ estimateSize: 42,
+ }))
+ if (withdrawMsgList.length > 0) {
+ array.push(...withdrawMsgList)
+ }
+ }
return array.sort((a, b) => {
return a.id - b.id;
})
@@ -3751,6 +3779,7 @@ export default {
},
onWithdraw() {
+ const operateItem = this.operateItem;
$A.modalConfirm({
content: `确定撤回此信息吗?`,
okText: '撤回',
@@ -3760,11 +3789,22 @@ export default {
this.$store.dispatch("call", {
url: 'dialog/msg/withdraw',
data: {
- msg_id: this.operateItem.id
+ msg_id: operateItem.id
},
}).then(() => {
resolve("消息已撤回");
- this.$store.dispatch("forgetDialogMsg", this.operateItem);
+ 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);
});
@@ -3773,6 +3813,21 @@ export default {
});
},
+ onWithdrawReEdit(source) {
+ if (this.operateVisible) {
+ return
+ }
+ this.cancelQuote()
+ const {type, text} = source.msg
+ if (type === 'md') {
+ this.$refs.input.setText(text)
+ } else {
+ this.$refs.input.setContent(text.replace(/\{\{RemoteURL\}\}/g, $A.mainUrl()))
+ }
+ !this.windowTouch && this.inputFocus()
+ this.$store.dispatch("forgetDialogWithdraw", {id: source.id})
+ },
+
onViewReply(data) {
if (this.operateVisible) {
return
diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js
index a18c08dd3..887c07128 100644
--- a/resources/assets/js/store/actions.js
+++ b/resources/assets/js/store/actions.js
@@ -7,6 +7,21 @@ import axios from "axios";
const dialogDraftState = { timer: {}, subTemp: null }
+// 撤回消息本地保留(重新编辑用),过期自动清除
+const dialogWithdrawState = {
+ timer: {},
+ expire: 5 * 60 * 1000,
+ schedule(commit, item) {
+ if (this.timer[item.id]) {
+ clearTimeout(this.timer[item.id])
+ }
+ this.timer[item.id] = setTimeout(() => {
+ delete this.timer[item.id]
+ commit('withdraw/remove', item.id)
+ }, Math.max(0, item.time + this.expire - new Date().getTime()))
+ }
+}
+
export default {
/**
* 预加载
@@ -1169,6 +1184,7 @@ export default {
'dialogMsgs',
'dialogDrafts',
'dialogQuotes',
+ 'dialogWithdraws',
'fileLists',
'callAt',
'cacheEmojis',
@@ -1212,6 +1228,15 @@ export default {
tag: !!item.content,
}));
+ // 特殊处理 dialogWithdraws(清除过期项,未过期的重新安排过期清除)
+ const withdrawNow = new Date().getTime()
+ const withdrawLength = state.dialogWithdraws.length
+ state.dialogWithdraws = state.dialogWithdraws.filter(item => item.time && withdrawNow - item.time < dialogWithdrawState.expire);
+ state.dialogWithdraws.forEach(item => dialogWithdrawState.schedule(commit, item));
+ if (state.dialogWithdraws.length !== withdrawLength) {
+ $A.IDBSave("dialogWithdraws", state.dialogWithdraws)
+ }
+
// TranslationLanguage 检查
if (typeof languageList[state.cacheTranslationLanguage] === "undefined") {
state.cacheTranslationLanguage = languageName;
@@ -4052,6 +4077,32 @@ export default {
commit('quote/remove', id)
},
+ /**
+ * 保存撤回消息(仅本地,撤回后显示"重新编辑"入口)
+ * @param commit
+ * @param data {id, dialog_id, prev_id, msg: {type, text}, ?time}
+ */
+ saveDialogWithdraw({commit}, data) {
+ data = Object.assign({time: new Date().getTime()}, data)
+ $A.syncDispatch("saveDialogWithdraw", data)
+ commit('withdraw/set', data)
+ dialogWithdrawState.schedule(commit, data)
+ },
+
+ /**
+ * 移除撤回消息
+ * @param commit
+ * @param data {id}
+ */
+ forgetDialogWithdraw({commit}, data) {
+ $A.syncDispatch("forgetDialogWithdraw", data)
+ if (dialogWithdrawState.timer[data.id]) {
+ clearTimeout(dialogWithdrawState.timer[data.id])
+ delete dialogWithdrawState.timer[data.id]
+ }
+ commit('withdraw/remove', data.id)
+ },
+
/** *****************************************************************************************/
/** ************************************** 消息 **********************************************/
/** *****************************************************************************************/
diff --git a/resources/assets/js/store/mutations.js b/resources/assets/js/store/mutations.js
index 78b55d97b..f67ba06d5 100644
--- a/resources/assets/js/store/mutations.js
+++ b/resources/assets/js/store/mutations.js
@@ -342,6 +342,25 @@ export default {
}
},
+ // 撤回消息管理(仅本地,用于撤回后重新编辑)
+ 'withdraw/set': function(state, data) {
+ const index = state.dialogWithdraws.findIndex(item => item.id === data.id)
+ if (index !== -1) {
+ state.dialogWithdraws.splice(index, 1, data)
+ } else {
+ state.dialogWithdraws.push(data)
+ }
+ $A.IDBSave("dialogWithdraws", state.dialogWithdraws)
+ },
+
+ 'withdraw/remove': function(state, id) {
+ const index = state.dialogWithdraws.findIndex(item => item.id === id)
+ if (index !== -1) {
+ state.dialogWithdraws.splice(index, 1)
+ $A.IDBSave("dialogWithdraws", state.dialogWithdraws)
+ }
+ },
+
// 长按事件
'longpress/set': function(state, {type, data, element}) {
state.longpressData = {type, data, element}
diff --git a/resources/assets/js/store/state.js b/resources/assets/js/store/state.js
index 8501dac63..abdb25829 100644
--- a/resources/assets/js/store/state.js
+++ b/resources/assets/js/store/state.js
@@ -162,6 +162,7 @@ export default {
dialogHistory: [],
dialogDrafts: [],
dialogQuotes: [],
+ dialogWithdraws: [],
dialogMsgTransfer: {time: 0},
dialogSseList: [],
dialogDroupWordChain: {},
diff --git a/resources/assets/sass/pages/components/dialog-wrapper.scss b/resources/assets/sass/pages/components/dialog-wrapper.scss
index 62f6fb828..dec2bdc7b 100644
--- a/resources/assets/sass/pages/components/dialog-wrapper.scss
+++ b/resources/assets/sass/pages/components/dialog-wrapper.scss
@@ -603,7 +603,8 @@
.dialog-tag,
.dialog-todo,
.dialog-top,
- .dialog-notice {
+ .dialog-notice,
+ .dialog-withdraw {
font-size: 12px;
max-width: 80%;
margin: 0 auto;
@@ -614,6 +615,15 @@
word-wrap: break-word;
}
+ .dialog-withdraw {
+ .withdraw-re-edit {
+ margin-left: 4px;
+ font-style: normal;
+ color: $primary-color;
+ cursor: pointer;
+ }
+ }
+
.dialog-top,
.dialog-tag {
cursor: pointer;