KI-AGENT: Mailantworten und Entitätsverknüpfungen ergänzen

This commit is contained in:
2026-09-07 19:00:08 +02:00
parent 4e4466ff11
commit f3384cfc74
10 changed files with 774 additions and 30 deletions

View File

@@ -52,9 +52,17 @@ type EmailMessage = {
contentType?: string | null
size?: number | null
}>
entityLinks?: Array<{
id: string
entityType: string
entityId: number
entityName: string
entityTypeLabel: string
}>
}
const { $api } = useNuxtApp()
const route = useRoute()
const runtimeConfig = useRuntimeConfig()
const toast = useToast()
@@ -74,6 +82,7 @@ const expandedMailboxPaths = ref<string[]>([])
const syncedMailboxPaths = ref<string[]>([])
const actionLoading = ref("")
const moveTargetMailboxPath = ref("")
let deepLinkApplied = false
const selectedAccount = computed(() =>
accounts.value.find((account) => account.id === selectedAccountId.value) || null
@@ -295,7 +304,10 @@ async function loadAccounts() {
loadingAccounts.value = true
try {
accounts.value = await $api("/api/email/accounts")
selectedAccountId.value = accounts.value[0]?.id || ""
const requestedAccountId = String(route.query.account || "")
selectedAccountId.value = accounts.value.some((account) => account.id === requestedAccountId)
? requestedAccountId
: accounts.value[0]?.id || ""
if (selectedAccountId.value) {
await loadMailboxes()
}
@@ -316,7 +328,9 @@ async function loadMailboxes() {
resetExpandedMailboxes()
const inbox = mailboxes.value.find((mailbox) => mailbox.specialUse === "\\Inbox" || mailbox.path.toUpperCase() === "INBOX")
const previousMailbox = mailboxes.value.find((mailbox) => mailbox.path === previousMailboxPath)
selectedMailboxPath.value = previousMailbox?.path || inbox?.path || mailboxes.value[0]?.path || "INBOX"
const requestedMailboxPath = String(route.query.mailbox || "")
const requestedMailbox = mailboxes.value.find((mailbox) => mailbox.path === requestedMailboxPath)
selectedMailboxPath.value = requestedMailbox?.path || previousMailbox?.path || inbox?.path || mailboxes.value[0]?.path || "INBOX"
expandMailboxAncestors(selectedMailboxPath.value)
await loadMessages()
} finally {
@@ -340,7 +354,10 @@ async function loadMessages(options: { syncIfEmpty?: boolean } = {}) {
}
if (messages.value.length) {
await selectMessage(messages.value[0])
const requestedMessageId = deepLinkApplied ? "" : String(route.query.message || "")
const requestedMessage = messages.value.find((message) => message.id === requestedMessageId)
await selectMessage(requestedMessage || messages.value[0])
deepLinkApplied = true
}
} finally {
loadingMessages.value = false
@@ -375,6 +392,22 @@ async function selectMessage(message: EmailMessage) {
}
}
function updateSelectedMessageEntityLinks(entityLinks: NonNullable<EmailMessage["entityLinks"]>) {
if (!selectedMessage.value) return
selectedMessage.value = { ...selectedMessage.value, entityLinks }
}
function openComposer(mode: "reply" | "replyAll" | "forward") {
if (!selectedMessage.value) return
navigateTo({
path: "/email/new",
query: {
mode,
source: selectedMessage.value.id,
},
})
}
function removeMessageFromCurrentList(messageId: string) {
const currentIndex = messages.value.findIndex((message) => message.id === messageId)
messages.value = messages.value.filter((message) => message.id !== messageId)
@@ -800,16 +833,26 @@ onMounted(loadAccounts)
color="neutral"
variant="soft"
size="sm"
@click="navigateTo(`/email/new?to=${encodeURIComponent(formatAddressList(selectedMessage.from))}&subject=${encodeURIComponent(`Re: ${selectedMessage.subject || ''}`)}`)"
@click="openComposer('reply')"
>
Antworten
</UButton>
<UButton
v-if="selectedMessage.cc?.length || (selectedMessage.to?.length || 0) > 1"
icon="i-heroicons-users"
color="neutral"
variant="ghost"
size="sm"
@click="openComposer('replyAll')"
>
Allen antworten
</UButton>
<UButton
icon="i-heroicons-arrow-uturn-right"
color="neutral"
variant="ghost"
size="sm"
@click="navigateTo(`/email/new?subject=${encodeURIComponent(`Fw: ${selectedMessage.subject || ''}`)}`)"
@click="openComposer('forward')"
>
Weiterleiten
</UButton>
@@ -831,6 +874,12 @@ onMounted(loadAccounts)
</p>
</div>
<EmailEntityLinks
:message-id="selectedMessage.id"
:entity-links="selectedMessage.entityLinks"
@updated="updateSelectedMessageEntityLinks"
/>
<div v-if="selectedMessage.attachments?.length" class="mt-4 flex flex-wrap gap-2">
<button
v-for="attachment in selectedMessage.attachments"