388 lines
10 KiB
Vue
388 lines
10 KiB
Vue
<template>
|
|
<div class="box">
|
|
<div class="header-actions">
|
|
<Icon class="icon" icon="material-symbols-light:arrow-back-ios-new" width="20" height="20" @click="handleBack"/>
|
|
<Icon v-perm="'email:delete'" class="icon" icon="uiw:delete" width="16" height="16" @click="handleDelete"/>
|
|
<span class="star" v-if="emailStore.contentData.showStar">
|
|
<Icon class="icon" @click="changeStar" v-if="email.isStar" icon="fluent-color:star-16" width="21" height="20"/>
|
|
<Icon class="icon" @click="changeStar" v-else icon="solar:star-line-duotone" width="19" height="19"/>
|
|
</span>
|
|
<Icon class="icon" v-if="emailStore.contentData.showReply" @click="openReply" icon="carbon:reply" width="20" height="20" />
|
|
</div>
|
|
<div></div>
|
|
<el-scrollbar class="scrollbar">
|
|
<div class="container">
|
|
<div class="email-title">
|
|
{{ email.subject }}
|
|
</div>
|
|
<div class="content">
|
|
<div class="email-info">
|
|
<div>
|
|
<div class="send"><span class="send-source">发件人</span>
|
|
<div class="send-name">
|
|
<span class="send-name-title">{{ email.name }}</span>
|
|
<span><{{ email.sendEmail }}></span>
|
|
</div>
|
|
</div>
|
|
<div class="receive"><span class="source">收件人</span><span class="receive-email">{{ formateReceive(email.recipient) }}</span></div>
|
|
<div class="date">
|
|
<div>{{ formatDetailDate(email.createTime) }}</div>
|
|
</div>
|
|
</div>
|
|
<el-alert v-if="email.status === 3" :closable="false" :title="'发送失败: ' + toMessage(email.message)" class="email-msg" type="error" show-icon />
|
|
<el-alert v-if="email.status === 4" :closable="false" title="被标记为垃圾邮件" class="email-msg" type="warning" show-icon />
|
|
<el-alert v-if="email.status === 5" :closable="false" title="邮件发送被延迟" class="email-msg" type="warning" show-icon />
|
|
</div>
|
|
<el-scrollbar class="htm-scrollbar" :class="email.attList.length === 0 ? 'bottom-distance' : ''">
|
|
<ShadowHtml :html="formatImage(email.content)" v-if="email.content" />
|
|
<span v-else class="email-text" >{{email.text}}</span>
|
|
</el-scrollbar>
|
|
<div class="att" v-if="email.attList.length > 0">
|
|
<div class="att-title">
|
|
<span>附件列表</span>
|
|
<span>共 {{email.attList.length}} 个</span>
|
|
</div>
|
|
<div class="att-box">
|
|
|
|
<div class="att-item" v-for="att in email.attList" :key="att.attId">
|
|
<div class="att-icon" @click="showImage(att.key)">
|
|
<Icon :icon="getIconByName(att.filename)" width="20" height="20"/>
|
|
</div>
|
|
<div class="att-name" @click="showImage(att.key)">
|
|
{{ att.filename }}
|
|
</div>
|
|
<div style="color: rgba(24, 36, 48, 0.6);">{{ formatBytes(att.size) }}</div>
|
|
<div class="opt-icon att-icon">
|
|
<Icon v-if="isImage(att.filename)" icon="hugeicons:view" width="22" height="22" @click="showImage(att.key)"/>
|
|
<a :href="cvtR2Url(att.key)" download>
|
|
<Icon icon="system-uicons:push-down" width="22" height="22"/>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</el-scrollbar>
|
|
<el-image-viewer
|
|
v-if="showPreview"
|
|
:url-list="srcList"
|
|
show-progress
|
|
@close="showPreview = false"
|
|
/>
|
|
</div>
|
|
</template>
|
|
<script setup>
|
|
import ShadowHtml from '@/components/shadow-html/index.vue'
|
|
import {reactive, ref, watch} from "vue";
|
|
import {useRouter} from 'vue-router'
|
|
import {ElMessage, ElMessageBox} from 'element-plus'
|
|
import {emailDelete} from "@/request/email.js";
|
|
import {Icon} from "@iconify/vue";
|
|
import {useEmailStore} from "@/store/email.js";
|
|
import {useAccountStore} from "@/store/account.js";
|
|
import {formatDetailDate} from "@/utils/day.js";
|
|
import {starAdd, starCancel} from "@/request/star.js";
|
|
import {getExtName, formatBytes} from "@/utils/file-utils.js";
|
|
import {cvtR2Url} from "@/utils/convert.js";
|
|
import {getIconByName} from "@/utils/icon-utils.js";
|
|
import {useSettingStore} from "@/store/setting.js";
|
|
import {sysEmailDelete} from "@/request/sys-email.js";
|
|
import {useUiStore} from "@/store/ui.js";
|
|
|
|
const uiStore = useUiStore();
|
|
const settingStore = useSettingStore();
|
|
const accountStore = useAccountStore();
|
|
const emailStore = useEmailStore();
|
|
const router = useRouter()
|
|
const email = emailStore.contentData.email
|
|
const showPreview = ref(false)
|
|
const srcList = reactive([])
|
|
|
|
|
|
watch(() => accountStore.currentAccountId, () => {
|
|
handleBack()
|
|
})
|
|
|
|
function openReply() {
|
|
uiStore.writerRef.openReply(email)
|
|
}
|
|
|
|
function toMessage(message) {
|
|
return message ? JSON.parse(message).message : '';
|
|
}
|
|
|
|
function formatImage(content) {
|
|
content = content || ''
|
|
const domain = settingStore.settings.r2Domain;
|
|
return content.replace('{{domain}}', domain + '/');
|
|
}
|
|
|
|
function showImage(key) {
|
|
if (!isImage(key)) return;
|
|
const url = cvtR2Url(key)
|
|
srcList.length = 0
|
|
srcList.push(url)
|
|
showPreview.value = true
|
|
}
|
|
|
|
function isImage(filename) {
|
|
return ['png', 'jpg', 'jpeg', 'bmp', 'gif','jfif'].includes(getExtName(filename))
|
|
}
|
|
|
|
function formateReceive(recipient) {
|
|
recipient = JSON.parse(recipient)
|
|
return recipient.map(item => item.address).join(', ')
|
|
}
|
|
|
|
function changeStar() {
|
|
if (email.isStar) {
|
|
email.isStar = 0;
|
|
starCancel(email.emailId).then(() => {
|
|
email.isStar = 0;
|
|
emailStore.starScroll?.deleteEmail([email.emailId])
|
|
}).catch((e) => {
|
|
console.error(e)
|
|
email.isStar = 1;
|
|
})
|
|
} else {
|
|
email.isStar = 1;
|
|
starAdd(email.emailId).then(() => {
|
|
email.isStar = 1;
|
|
emailStore.starScroll?.addItem(email)
|
|
}).catch((e) => {
|
|
console.error(e)
|
|
email.isStar = 0;
|
|
})
|
|
}
|
|
}
|
|
|
|
const handleBack = () => {
|
|
router.back()
|
|
}
|
|
|
|
const handleDelete = () => {
|
|
ElMessageBox.confirm('确认删除该邮件吗?', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
if (emailStore.contentData.delType === 'logic') {
|
|
emailDelete(email.emailId).then(() => {
|
|
ElMessage({
|
|
message: '删除成功',
|
|
type: 'success',
|
|
plain: true,
|
|
})
|
|
emailStore.deleteIds = [email.emailId]
|
|
})
|
|
} else {
|
|
|
|
sysEmailDelete(email.emailId).then(() => {
|
|
ElMessage({
|
|
message: '删除成功',
|
|
type: 'success',
|
|
plain: true,
|
|
})
|
|
emailStore.deleteIds = [email.emailId]
|
|
})
|
|
}
|
|
|
|
router.back()
|
|
})
|
|
}
|
|
</script>
|
|
<style scoped lang="scss">
|
|
.box {
|
|
height: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.header-actions {
|
|
padding: 9px 15px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20px;
|
|
box-shadow: inset 0 -1px 0 0 rgba(100, 121, 143, 0.12);
|
|
font-size: 18px;
|
|
.star {
|
|
display: flex;
|
|
align-items: center;
|
|
min-width: 21px;
|
|
}
|
|
.icon {
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
|
|
|
|
.scrollbar {
|
|
height: calc(100% - 38px);
|
|
width: 100%;
|
|
}
|
|
|
|
.container {
|
|
font-size: 14px;
|
|
padding-left: 20px;
|
|
padding-right: 20px;
|
|
padding-top: 10px;
|
|
@media (max-width: 1023px) {
|
|
padding-left: 15px;
|
|
padding-right: 15px;
|
|
}
|
|
|
|
.email-title {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.htm-scrollbar {
|
|
}
|
|
|
|
.content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
.att {
|
|
margin-top: 30px;
|
|
margin-bottom: 30px;
|
|
border: 1px solid var(--el-border-color);
|
|
padding: 10px;
|
|
border-radius: 4px;
|
|
width: fit-content;
|
|
.att-box {
|
|
min-width: min(410px,calc(100vw - 53px));
|
|
display: grid;
|
|
gap: 10px;
|
|
grid-template-rows: 1fr;
|
|
}
|
|
|
|
.att-title {
|
|
margin-bottom: 5px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
span:first-child {
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
|
|
.att-item {
|
|
cursor: pointer;
|
|
div {
|
|
align-self: center;
|
|
}
|
|
|
|
padding: 5px 8px;
|
|
border-radius: 4px;
|
|
align-self: start;
|
|
border: 1px solid #e7e9ec;
|
|
display: grid;
|
|
grid-template-columns: auto 1fr auto auto;
|
|
gap: 10px;
|
|
|
|
.att-icon {
|
|
display: grid;
|
|
}
|
|
|
|
.att-name {
|
|
margin-right: 10px;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.att-image {
|
|
width: 60px;
|
|
height: 60px;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.opt-icon {
|
|
color: rgba(24, 36, 48, 0.6);
|
|
align-items: center;
|
|
display: flex;
|
|
gap: 8px;
|
|
cursor: pointer;
|
|
a {
|
|
color: rgba(24, 36, 48, 0.6);
|
|
align-items: center;
|
|
display: flex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.email-info {
|
|
|
|
border-bottom: 1px solid #e7e9ec;
|
|
margin-bottom: 20px;
|
|
padding-bottom: 8px;
|
|
@media (max-width: 1024px) {
|
|
margin-bottom: 15px;
|
|
}
|
|
.date {
|
|
color: #585d69;
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
.email-msg {
|
|
max-width: 400px;
|
|
width: fit-content;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.send {
|
|
display: flex;
|
|
margin-bottom: 6px;
|
|
|
|
.send-name {
|
|
color: #585d69;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.send-name-title {
|
|
padding-right: 5px;
|
|
}
|
|
}
|
|
|
|
.receive {
|
|
margin-bottom: 6px;
|
|
display: flex;
|
|
.receive-email {
|
|
max-width: 700px;
|
|
word-break: break-word;
|
|
}
|
|
span:nth-child(2) {
|
|
color: #585d69;
|
|
}
|
|
}
|
|
|
|
.send-source {
|
|
white-space: nowrap;
|
|
font-weight: bold;
|
|
padding-right: 10px;
|
|
}
|
|
|
|
.source {
|
|
white-space: nowrap;
|
|
font-weight: bold;
|
|
padding-right: 10px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.email-text {
|
|
white-space: pre-wrap;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.bottom-distance {
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
|
|
</style> |