perf: 支持取消发送中的消息

This commit is contained in:
kuaifan 2024-03-19 15:57:07 +09:00
parent 915a5ed7d5
commit 99dca06d44
6 changed files with 187 additions and 90 deletions

View File

@ -55,7 +55,7 @@
"stylus-loader": "^7.1.0", "stylus-loader": "^7.1.0",
"tinymce": "^5.10.3", "tinymce": "^5.10.3",
"tui-calendar-hi": "^1.15.1-5", "tui-calendar-hi": "^1.15.1-5",
"view-design-hi": "^4.7.0-49", "view-design-hi": "^4.7.0-50",
"vite": "^2.9.15", "vite": "^2.9.15",
"vite-plugin-file-copy": "^1.0.0", "vite-plugin-file-copy": "^1.0.0",
"vite-plugin-require": "^1.1.10", "vite-plugin-require": "^1.1.10",

View File

@ -1970,30 +1970,57 @@ const localforage = require("localforage");
if (typeof params.success === 'undefined') params.success = () => { }; if (typeof params.success === 'undefined') params.success = () => { };
if (typeof params.error === 'undefined') params.error = () => { }; if (typeof params.error === 'undefined') params.error = () => { };
if (typeof params.header == 'undefined') params.header = {}; if (typeof params.header == 'undefined') params.header = {};
const key = $A.randomString(16);
// //
params.before(); params.before();
$A.ihttp({ $A.__ajaxList.push({
key,
id: params.requestId || null,
url: params.url, url: params.url,
data: params.data, request: $A.ihttp({
cache: params.cache, url: params.url,
headers: params.header, data: params.data,
method: params.method.toUpperCase(), cache: params.cache,
contentType: "OPTIONS", headers: params.header,
crossDomain: true, method: params.method.toUpperCase(),
dataType: params.dataType, contentType: "OPTIONS",
timeout: params.timeout, crossDomain: true,
success: function (data, status, xhr) { dataType: params.dataType,
params.complete(); timeout: params.timeout,
params.success(data, status, xhr); success: function (data, status, xhr) {
params.after(true); $A.__ajaxList = $A.__ajaxList.filter(val => val.key !== key);
}, params.complete();
error: function (xhr, status) { params.success(data, status, xhr);
params.complete(); params.after(true);
params.error(xhr, status); },
params.after(false); error: function (xhr, status) {
$A.__ajaxList = $A.__ajaxList.filter(val => val.key !== key);
params.complete();
params.error(xhr, status);
params.after(false);
}
})
});
},
ajaxcCancel(requestId) {
if (!requestId) {
return 0;
}
let num = 0;
$A.__ajaxList.forEach((val, index) => {
if (val.id === requestId) {
num++;
if (val.request) {
val.request.abort();
}
} }
}); });
} if (num > 0) {
$A.__ajaxList = $A.__ajaxList.filter(val => val.id !== requestId);
}
return num;
},
__ajaxList: [],
}); });
window.$A = $; window.$A = $;

View File

@ -187,6 +187,11 @@ export default {
//file //file
this.$refs.upload.upload(file); this.$refs.upload.upload(file);
}, },
cancel(uid) {
//
return this.$refs.upload.cancel(uid);
}
} }
} }
</script> </script>

View File

@ -437,9 +437,6 @@ export default {
methods: { methods: {
handleLongpress(event, el) { handleLongpress(event, el) {
if (!this.msgData.created_at) {
return;
}
this.$emit("on-longpress", {event, el, msgData: this.msgData}) this.$emit("on-longpress", {event, el, msgData: this.msgData})
}, },
@ -515,7 +512,7 @@ export default {
fileStyle(percentage) { fileStyle(percentage) {
if (percentage) { if (percentage) {
return { return {
width: (100 - percentage) + '%' width: `${percentage}%`
}; };
} }
return {}; return {};

View File

@ -273,74 +273,86 @@
transfer> transfer>
<div :style="{userSelect:operateVisible ? 'none' : 'auto', height: operateStyles.height}"></div> <div :style="{userSelect:operateVisible ? 'none' : 'auto', height: operateStyles.height}"></div>
<DropdownMenu slot="list"> <DropdownMenu slot="list">
<DropdownItem name="action"> <template v-if="!operateItem.created_at">
<ul class="operate-action"> <DropdownItem name="action">
<li v-if="msgId === 0" @click="onOperate('reply')"> <ul class="operate-action cancel">
<i class="taskfont">&#xe6eb;</i> <li @click="onOperate('cancel')">
<span>{{ $L('回复') }}</span> <i class="taskfont">&#xe6eb;</i>
</li> <span>{{ $L('取消发送') }}</span>
<li v-if="operateItem.userid == userId && operateItem.type === 'text'" @click="onOperate('update')">
<i class="taskfont">&#xe779;</i>
<span>{{ $L('编辑') }}</span>
</li>
<li v-for="item in operateCopys" @click="onOperate('copy', item)">
<i class="taskfont" v-html="item.icon"></i>
<span>{{ $L(item.label) }}</span>
</li>
<li v-if="operateItem.type !== 'word-chain' && operateItem.type !== 'vote'" @click="onOperate('forward')">
<i class="taskfont">&#xe638;</i>
<span>{{ $L('转发') }}</span>
</li>
<li v-if="operateItem.userid == userId" @click="onOperate('withdraw')">
<i class="taskfont">&#xe637;</i>
<span>{{ $L('撤回') }}</span>
</li>
<template v-if="operateItem.type === 'file'">
<li @click="onOperate('view')">
<i class="taskfont">&#xe77b;</i>
<span>{{ $L('查看') }}</span>
</li> </li>
<li @click="onOperate('down')"> </ul>
<i class="taskfont">&#xe7a8;</i> </DropdownItem>
<span>{{ $L('下载') }}</span> </template>
<template v-else>
<DropdownItem name="action">
<ul class="operate-action">
<li v-if="msgId === 0" @click="onOperate('reply')">
<i class="taskfont">&#xe6eb;</i>
<span>{{ $L('回复') }}</span>
</li> </li>
</template> <li v-if="operateItem.userid == userId && operateItem.type === 'text'" @click="onOperate('update')">
<li @click="onOperate('tag')"> <i class="taskfont">&#xe779;</i>
<i class="taskfont">&#xe61e;</i> <span>{{ $L('编辑') }}</span>
<span>{{ $L(operateItem.tag ? '取消标注' : '标注') }}</span> </li>
</li> <li v-for="item in operateCopys" @click="onOperate('copy', item)">
<li v-if="operateItem.type === 'text'" @click="onOperate('newTask')"> <i class="taskfont" v-html="item.icon"></i>
<i class="taskfont">&#xe7b8;</i> <span>{{ $L(item.label) }}</span>
<span>{{ $L('新任务') }}</span> </li>
</li> <li v-if="operateItem.type !== 'word-chain' && operateItem.type !== 'vote'" @click="onOperate('forward')">
<li @click="onOperate('todo')"> <i class="taskfont">&#xe638;</i>
<i class="taskfont">&#xe7b7;</i> <span>{{ $L('转发') }}</span>
<span>{{ $L(operateItem.todo ? '取消待办' : '设待办') }}</span> </li>
</li> <li v-if="operateItem.userid == userId" @click="onOperate('withdraw')">
<li @click="onOperate('top')"> <i class="taskfont">&#xe637;</i>
<i class="taskfont" v-html="dialogData.top_msg_id == operateItem.id ? '&#xe7e3;' : '&#xe7e6;'"></i> <span>{{ $L('撤回') }}</span>
<span>{{ $L(dialogData.top_msg_id == operateItem.id ? '取消置顶' : '置顶') }}</span> </li>
</li> <template v-if="operateItem.type === 'file'">
<li v-if="msgType !== ''" @click="onOperate('pos')"> <li @click="onOperate('view')">
<i class="taskfont">&#xee15;</i> <i class="taskfont">&#xe77b;</i>
<span>{{ $L('完整对话') }}</span> <span>{{ $L('查看') }}</span>
</li> </li>
</ul> <li @click="onOperate('down')">
</DropdownItem> <i class="taskfont">&#xe7a8;</i>
<DropdownItem name="emoji" class="dropdown-emoji"> <span>{{ $L('下载') }}</span>
<ul class="operate-emoji scrollbar-hidden"> </li>
<li </template>
v-for="(emoji, key) in operateEmojis" <li @click="onOperate('tag')">
:key="key" <i class="taskfont">&#xe61e;</i>
v-html="emoji" <span>{{ $L(operateItem.tag ? '取消标注' : '标注') }}</span>
class="no-dark-content" </li>
@click="onOperate('emoji', emoji)"></li> <li v-if="operateItem.type === 'text'" @click="onOperate('newTask')">
<li></li> <i class="taskfont">&#xe7b8;</i>
<li class="more-emoji" @click="onOperate('emoji', 'more')"> <span>{{ $L('新任务') }}</span>
<i class="taskfont">&#xe790;</i> </li>
</li> <li @click="onOperate('todo')">
</ul> <i class="taskfont">&#xe7b7;</i>
</DropdownItem> <span>{{ $L(operateItem.todo ? '取消待办' : '设待办') }}</span>
</li>
<li @click="onOperate('top')">
<i class="taskfont" v-html="dialogData.top_msg_id == operateItem.id ? '&#xe7e3;' : '&#xe7e6;'"></i>
<span>{{ $L(dialogData.top_msg_id == operateItem.id ? '取消置顶' : '置顶') }}</span>
</li>
<li v-if="msgType !== ''" @click="onOperate('pos')">
<i class="taskfont">&#xee15;</i>
<span>{{ $L('完整对话') }}</span>
</li>
</ul>
</DropdownItem>
<DropdownItem name="emoji" class="dropdown-emoji">
<ul class="operate-emoji scrollbar-hidden">
<li
v-for="(emoji, key) in operateEmojis"
:key="key"
v-html="emoji"
class="no-dark-content"
@click="onOperate('emoji', emoji)"></li>
<li></li>
<li class="more-emoji" @click="onOperate('emoji', 'more')">
<i class="taskfont">&#xe790;</i>
</li>
</ul>
</DropdownItem>
</template>
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>
</div> </div>
@ -1493,6 +1505,7 @@ export default {
this.$nextTick(this.onToBottom) this.$nextTick(this.onToBottom)
// //
this.$store.dispatch("call", { this.$store.dispatch("call", {
requestId: tempMsg.id,
url: 'dialog/msg/sendtext', url: 'dialog/msg/sendtext',
data: { data: {
dialog_id: tempMsg.dialog_id, dialog_id: tempMsg.dialog_id,
@ -1536,6 +1549,7 @@ export default {
this.$nextTick(this.onToBottom) this.$nextTick(this.onToBottom)
// //
this.$store.dispatch("call", { this.$store.dispatch("call", {
requestId: tempMsg.id,
url: 'dialog/msg/sendrecord', url: 'dialog/msg/sendrecord',
data: Object.assign(msg, { data: Object.assign(msg, {
dialog_id: this.dialogId, dialog_id: this.dialogId,
@ -1992,6 +2006,7 @@ export default {
} }
const tempMsg = { const tempMsg = {
id: file.tempId, id: file.tempId,
file_uid: file.uid,
dialog_id: this.dialogData.id, dialog_id: this.dialogData.id,
reply_id: this.quoteId, reply_id: this.quoteId,
type: 'file', type: 'file',
@ -2772,6 +2787,10 @@ export default {
this.operateVisible = false; this.operateVisible = false;
this.$nextTick(_ => { this.$nextTick(_ => {
switch (action) { switch (action) {
case "cancel":
this.onCancelSend()
break;
case "reply": case "reply":
this.onReply() this.onReply()
break; break;
@ -2833,6 +2852,39 @@ export default {
}) })
}, },
onCancelSend() {
$A.modalConfirm({
title: '取消发送',
content: '你确定要取消发送吗?',
loading: true,
onOk: () => {
return new Promise((resolve, reject) => {
if (this.operateItem.created_at) {
reject("消息已发送,不可取消");
return
}
if (this.operateItem.type === 'file') {
//
if (this.$refs.chatUpload.cancel(this.operateItem.file_uid)) {
this.forgetTempMsg(this.operateItem.id)
resolve();
} else {
reject("取消失败");
}
} else {
//
this.$store.dispatch('callCancel', this.operateItem.id).then(() => {
this.forgetTempMsg(this.operateItem.id)
resolve();
}).catch(() => {
reject("取消失败");
});
}
})
}
});
},
onReply(type) { onReply(type) {
this.setQuote(this.operateItem.id, type) this.setQuote(this.operateItem.id, type)
this.inputFocus() this.inputFocus()

View File

@ -325,6 +325,22 @@ export default {
}) })
}, },
/**
* 取消请求
* @param state
* @param requestId
* @returns {Promise<unknown>}
*/
callCancel({state}, requestId) {
return new Promise((resolve, reject) => {
if ($A.ajaxcCancel(requestId)) {
resolve()
} else {
reject()
}
})
},
/** /**
* 获取系统设置 * 获取系统设置
* @param dispatch * @param dispatch