fix(conversations): 修复会话标识与解决后跳转

This commit is contained in:
Rogee
2026-08-06 11:19:39 +08:00
parent b78f963472
commit 8d002d1dbe
8 changed files with 173 additions and 12 deletions
@@ -182,6 +182,7 @@ const onDeleteConversation = () => {
<!-- Expanded layout: wide screen + expanded setting -->
<ConversationCardExpanded
v-if="showExpanded"
:data-conversation-id="source.id"
:chat="source"
:current-contact="currentContact"
:assignee="assignee"
@@ -200,6 +201,7 @@ const onDeleteConversation = () => {
<!-- Default (condensed) layout -->
<ConversationCard
v-else
:data-conversation-id="source.id"
:chat="source"
:current-contact="currentContact"
:assignee="assignee"
@@ -22,7 +22,10 @@ import Button from 'dashboard/components-next/button/Button.vue';
import ConversationResolveAttributesModal from 'dashboard/components-next/ConversationWorkflow/ConversationResolveAttributesModal.vue';
import {
conversationListPageURL,
conversationUrl,
frontendURL,
} from 'dashboard/helper/URLHelper';
import { getAdjacentConversationId } from 'dashboard/helper/conversationNavigation';
import {
isOnMentionsView,
isOnParticipatingView,
@@ -47,6 +50,37 @@ const openDropdown = () => toggleDropdown(true);
const currentChat = computed(() => getters.getSelectedChat.value);
const openConversation = conversationId => {
if (!conversationId) {
redirectToConversationList();
return;
}
const {
params: { accountId, inbox_id: inboxId, label, teamId, id: customViewId },
name,
} = route;
let conversationType = '';
if (isOnMentionsView({ route: { name } })) conversationType = 'mention';
else if (isOnParticipatingView({ route: { name } })) {
conversationType = 'participating';
} else if (isOnUnattendedView({ route: { name } })) {
conversationType = 'unattended';
}
router.push({
path: frontendURL(
conversationUrl({
accountId,
activeInbox: inboxId,
id: conversationId,
label,
teamId,
foldersId: isOnFoldersView({ route: { name } }) ? customViewId : 0,
conversationType,
})
),
});
};
const redirectToConversationList = () => {
const {
params: { accountId, inbox_id: inboxId, label, teamId, id: customViewId },
@@ -112,6 +146,15 @@ const getConversationParams = () => {
};
};
const getAdjacentConversationID = conversationId => {
const conversationIds = [
...document.querySelectorAll('.conversations-list .conversation'),
]
.map(element => Number(element.dataset.conversationId))
.filter(Boolean);
return getAdjacentConversationId(conversationIds, conversationId);
};
const openSnoozeModal = () => {
const ninja = document.querySelector('ninja-keys');
ninja.open({ parent: 'snooze_conversation' });
@@ -121,9 +164,7 @@ const toggleStatus = (status, snoozedUntil, customAttributes = null) => {
closeDropdown();
isLoading.value = true;
const conversationId = currentChat.value.id;
const { all, activeIndex, lastIndex } = getConversationParams();
const adjacentConversation =
activeIndex < lastIndex ? all[activeIndex + 1] : all[activeIndex - 1];
const adjacentConversationId = getAdjacentConversationID(conversationId);
const payload = {
conversationId,
@@ -140,11 +181,7 @@ const toggleStatus = (status, snoozedUntil, customAttributes = null) => {
.then(() => {
useAlert(t('CONVERSATION.CHANGE_STATUS'));
if (status !== wootConstants.STATUS_TYPE.OPEN) {
if (adjacentConversation) {
adjacentConversation.click();
} else {
redirectToConversationList();
}
openConversation(adjacentConversationId);
}
})
.finally(() => {
@@ -0,0 +1,10 @@
export const getAdjacentConversationId = (conversationIds, currentId) => {
const currentIndex = conversationIds.indexOf(currentId);
if (currentIndex === -1) return null;
return (
conversationIds[currentIndex + 1] ??
conversationIds[currentIndex - 1] ??
null
);
};
@@ -0,0 +1,21 @@
import { getAdjacentConversationId } from '../conversationNavigation';
describe('getAdjacentConversationId', () => {
const conversationIds = [15, 19, 25];
it('selects the immediate next conversation', () => {
expect(getAdjacentConversationId(conversationIds, 15)).toBe(19);
});
it('selects the previous conversation for the last item', () => {
expect(getAdjacentConversationId(conversationIds, 25)).toBe(19);
});
it('returns null for a single-item list', () => {
expect(getAdjacentConversationId([15], 15)).toBeNull();
});
it('returns null when the current conversation is absent', () => {
expect(getAdjacentConversationId(conversationIds, 99)).toBeNull();
});
});