mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-05-12 02:20:12 +08:00
feat: all mail use MailBox Component (#173)
This commit is contained in:
@@ -3,7 +3,6 @@ import { watch, onMounted, ref } from "vue";
|
||||
import { useMessage } from 'naive-ui'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useGlobalState } from '../store'
|
||||
import { api } from '../api'
|
||||
import { CloudDownloadRound } from '@vicons/material'
|
||||
import { useIsMobile } from '../utils/composables'
|
||||
import { processItem, getDownloadEmlUrl } from '../utils/email-parser'
|
||||
@@ -11,7 +10,30 @@ import { processItem, getDownloadEmlUrl } from '../utils/email-parser'
|
||||
const message = useMessage()
|
||||
const isMobile = useIsMobile()
|
||||
|
||||
const { settings, openSettings, themeSwitch } = useGlobalState()
|
||||
const props = defineProps({
|
||||
enableUserDeleteEmail: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
requried: false
|
||||
},
|
||||
showEMailTo: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
requried: false
|
||||
},
|
||||
fetchMailData: {
|
||||
type: Function,
|
||||
default: () => { },
|
||||
requried: true
|
||||
},
|
||||
deleteMail: {
|
||||
type: Function,
|
||||
default: () => { },
|
||||
requried: false
|
||||
},
|
||||
})
|
||||
|
||||
const { themeSwitch } = useGlobalState()
|
||||
const autoRefresh = ref(false)
|
||||
const autoRefreshInterval = ref(30)
|
||||
const data = ref([])
|
||||
@@ -29,6 +51,7 @@ const { t } = useI18n({
|
||||
locale: 'zh',
|
||||
messages: {
|
||||
en: {
|
||||
success: 'Success',
|
||||
autoRefresh: 'Auto Refresh',
|
||||
refreshAfter: 'Refresh After {msg} Seconds',
|
||||
refresh: 'Refresh',
|
||||
@@ -39,6 +62,7 @@ const { t } = useI18n({
|
||||
deleteMailTip: 'Are you sure you want to delete this mail?'
|
||||
},
|
||||
zh: {
|
||||
success: '成功',
|
||||
autoRefresh: '自动刷新',
|
||||
refreshAfter: '{msg}秒后刷新',
|
||||
refresh: '刷新',
|
||||
@@ -80,10 +104,8 @@ watch([page, pageSize], async ([page, pageSize], [oldPage, oldPageSize]) => {
|
||||
|
||||
const refresh = async () => {
|
||||
try {
|
||||
const { results, count: totalCount } = await api.fetch(
|
||||
`/api/mails`
|
||||
+ `?limit=${pageSize.value}`
|
||||
+ `&offset=${(page.value - 1) * pageSize.value}`
|
||||
const { results, count: totalCount } = await props.fetchMailData(
|
||||
pageSize.value, (page.value - 1) * pageSize.value
|
||||
);
|
||||
data.value = await Promise.all(results.map(async (item) => {
|
||||
return await processItem(item);
|
||||
@@ -115,9 +137,7 @@ const mailItemClass = (row) => {
|
||||
|
||||
const deleteMail = async () => {
|
||||
try {
|
||||
await api.fetch(`/api/mails/${curMail.value.id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
await props.deleteMail(curMail.value.id);
|
||||
message.success(t("success"));
|
||||
curMail.value = null;
|
||||
await refresh();
|
||||
@@ -133,48 +153,129 @@ onMounted(async () => {
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<n-layout v-if="settings.address">
|
||||
<n-split class="left" v-if="!isMobile" direction="horizontal" :max="0.75" :min="0.25" :default-size="0.3">
|
||||
<template #1>
|
||||
<div class="center">
|
||||
<div style="display: inline-block; margin-top: 10px; margin-bottom: 10px;">
|
||||
<n-pagination v-model:page="page" v-model:page-size="pageSize" :item-count="count" simple size="small" />
|
||||
</div>
|
||||
<n-switch v-model:value="autoRefresh" size="small" :round="false">
|
||||
<template #checked>
|
||||
{{ t('refreshAfter', { msg: autoRefreshInterval }) }}
|
||||
<n-split class="left" v-if="!isMobile" direction="horizontal" :max="0.75" :min="0.25" :default-size="0.3">
|
||||
<template #1>
|
||||
<div class="center">
|
||||
<div style="display: inline-block; margin-top: 10px; margin-bottom: 10px;">
|
||||
<n-pagination v-model:page="page" v-model:page-size="pageSize" :item-count="count" simple size="small" />
|
||||
</div>
|
||||
<n-switch v-model:value="autoRefresh" size="small" :round="false">
|
||||
<template #checked>
|
||||
{{ t('refreshAfter', { msg: autoRefreshInterval }) }}
|
||||
</template>
|
||||
<template #unchecked>
|
||||
{{ t('autoRefresh') }}
|
||||
</template>
|
||||
</n-switch>
|
||||
<n-button @click="refresh" size="small" type="primary">
|
||||
{{ t('refresh') }}
|
||||
</n-button>
|
||||
</div>
|
||||
<div style="overflow: auto; height: 80vh;">
|
||||
<n-list hoverable clickable>
|
||||
<n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)"
|
||||
:class="mailItemClass(row)">
|
||||
<n-thing :title="row.subject">
|
||||
<template #description>
|
||||
<n-tag type="info">
|
||||
ID: {{ row.id }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
{{ row.created_at }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
FROM: {{ row.source }}
|
||||
</n-tag>
|
||||
<n-tag v-if="showEMailTo" type="info">
|
||||
TO: {{ row.address }}
|
||||
</n-tag>
|
||||
</template>
|
||||
</n-thing>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
</div>
|
||||
</template>
|
||||
<template #2>
|
||||
<n-card v-if="curMail" class="mail-item" :title="curMail.subject" style="overflow: auto; max-height: 100vh;">
|
||||
<n-space>
|
||||
<n-tag type="info">
|
||||
ID: {{ curMail.id }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
{{ curMail.created_at }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
FROM: {{ curMail.source }}
|
||||
</n-tag>
|
||||
<n-tag v-if="showEMailTo" type="info">
|
||||
TO: {{ curMail.address }}
|
||||
</n-tag>
|
||||
<n-popconfirm v-if="enableUserDeleteEmail" @positive-click="deleteMail">
|
||||
<template #trigger>
|
||||
<n-button tertiary type="error" size="small">{{ t('delete') }}</n-button>
|
||||
</template>
|
||||
<template #unchecked>
|
||||
{{ t('autoRefresh') }}
|
||||
</template>
|
||||
</n-switch>
|
||||
<n-button @click="refresh" size="small" type="primary">
|
||||
{{ t('refresh') }}
|
||||
{{ t('deleteMailTip') }}
|
||||
</n-popconfirm>
|
||||
<n-button v-if="curMail.attachments && curMail.attachments.length > 0" size="small" tertiary type="info"
|
||||
@click="getAttachments(curMail.attachments)">
|
||||
{{ t('attachments') }}
|
||||
</n-button>
|
||||
</div>
|
||||
<div style="overflow: auto; height: 80vh;">
|
||||
<n-list hoverable clickable>
|
||||
<n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)"
|
||||
:class="mailItemClass(row)">
|
||||
<n-thing :title="row.subject">
|
||||
<template #description>
|
||||
<n-tag type="info">
|
||||
ID: {{ row.id }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
{{ row.created_at }}
|
||||
</n-tag>
|
||||
<div style="word-break: break-all; font-size: small;">
|
||||
FROM: {{ row.source }}
|
||||
</div>
|
||||
</template>
|
||||
</n-thing>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
</div>
|
||||
</template>
|
||||
<template #2>
|
||||
<n-card v-if="curMail" class="mail-item" :title="curMail.subject" style="overflow: auto; max-height: 100vh;">
|
||||
<n-button tag="a" target="_blank" tertiary type="info" size="small" :download="curMail.id + '.eml'"
|
||||
:href="getDownloadEmlUrl(curMail.raw)">
|
||||
<n-icon :component="CloudDownloadRound" />
|
||||
{{ t('downloadMail') }}
|
||||
</n-button>
|
||||
</n-space>
|
||||
<div v-html="curMail.message" style="margin-top: 10px;"></div>
|
||||
<!-- <iframe :srcdoc="curMail.message" style="width: 100%; height: 100%;"></iframe> -->
|
||||
</n-card>
|
||||
<n-card class="mail-item" v-else>
|
||||
<n-result status="info" :title="t('pleaseSelectMail')">
|
||||
</n-result>
|
||||
</n-card>
|
||||
</template>
|
||||
</n-split>
|
||||
<div class="left" v-else>
|
||||
<div class="center">
|
||||
<div style="display: inline-block; margin-top: 10px; margin-bottom: 10px;">
|
||||
<n-pagination v-model:page="page" v-model:page-size="pageSize" :item-count="count" simple size="small" />
|
||||
</div>
|
||||
<n-switch v-model:value="autoRefresh" size="small">
|
||||
<template #checked>
|
||||
{{ t('autoRefresh') }}
|
||||
</template>
|
||||
<template #unchecked>
|
||||
{{ t('autoRefresh') }}
|
||||
</template></n-switch>
|
||||
<n-button @click="refresh" size="small" type="primary">
|
||||
{{ t('refresh') }}
|
||||
</n-button>
|
||||
</div>
|
||||
<div id="drawer-target" style="overflow: auto; height: 80vh;">
|
||||
<n-list hoverable clickable>
|
||||
<n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)">
|
||||
<n-thing :title="row.subject">
|
||||
<template #description>
|
||||
<n-tag type="info">
|
||||
ID: {{ row.id }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
{{ row.created_at }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
FROM: {{ row.source }}
|
||||
</n-tag>
|
||||
<n-tag v-if="showEMailTo" type="info">
|
||||
TO: {{ row.address }}
|
||||
</n-tag>
|
||||
</template>
|
||||
</n-thing>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
</div>
|
||||
<n-drawer v-model:show="curMail" width="100%" :trap-focus="false" :block-scroll="false" to="#drawer-target">
|
||||
<n-drawer-content :title="curMail ? curMail.subject : ''" closable>
|
||||
<n-card style="overflow: auto;">
|
||||
<n-space>
|
||||
<n-tag type="info">
|
||||
ID: {{ curMail.id }}
|
||||
@@ -185,7 +286,10 @@ onMounted(async () => {
|
||||
<n-tag type="info">
|
||||
FROM: {{ curMail.source }}
|
||||
</n-tag>
|
||||
<n-popconfirm v-if="openSettings.enableUserDeleteEmail" @positive-click="deleteMail">
|
||||
<n-tag v-if="showEMailTo" type="info">
|
||||
TO: {{ curMail.address }}
|
||||
</n-tag>
|
||||
<n-popconfirm v-if="enableUserDeleteEmail" @positive-click="deleteMail">
|
||||
<template #trigger>
|
||||
<n-button tertiary type="error" size="small">{{ t('delete') }}</n-button>
|
||||
</template>
|
||||
@@ -196,89 +300,16 @@ onMounted(async () => {
|
||||
{{ t('attachments') }}
|
||||
</n-button>
|
||||
<n-button tag="a" target="_blank" tertiary type="info" size="small" :download="curMail.id + '.eml'"
|
||||
:href="getDownloadEmlUrl(curMail.raw)">
|
||||
:href="getDownloadEmlUrl(curMail)">
|
||||
<n-icon :component="CloudDownloadRound" />
|
||||
{{ t('downloadMail') }}
|
||||
</n-button>
|
||||
</n-space>
|
||||
<div v-html="curMail.message" style="margin-top: 10px;"></div>
|
||||
</n-card>
|
||||
<n-card class="mail-item" v-else>
|
||||
<n-result status="info" :title="t('pleaseSelectMail')">
|
||||
</n-result>
|
||||
</n-card>
|
||||
</template>
|
||||
</n-split>
|
||||
<div class="left" v-else>
|
||||
<div class="center">
|
||||
<div style="display: inline-block; margin-top: 10px; margin-bottom: 10px;">
|
||||
<n-pagination v-model:page="page" v-model:page-size="pageSize" :item-count="count" simple size="small" />
|
||||
</div>
|
||||
<n-switch v-model:value="autoRefresh" size="small">
|
||||
<template #checked>
|
||||
{{ t('autoRefresh') }}
|
||||
</template>
|
||||
<template #unchecked>
|
||||
{{ t('autoRefresh') }}
|
||||
</template></n-switch>
|
||||
<n-button @click="refresh" size="small" type="primary">
|
||||
{{ t('refresh') }}
|
||||
</n-button>
|
||||
</div>
|
||||
<div id="drawer-target" style="overflow: auto; height: 80vh;">
|
||||
<n-list hoverable clickable>
|
||||
<n-list-item v-for="row in data" v-bind:key="row.id" @click="() => clickRow(row)">
|
||||
<n-thing :title="row.subject">
|
||||
<template #description>
|
||||
<n-tag type="info">
|
||||
ID: {{ row.id }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
{{ row.created_at }}
|
||||
</n-tag>
|
||||
<div style="word-break: break-all; font-size: small;">
|
||||
FROM: {{ row.source }}
|
||||
</div>
|
||||
</template>
|
||||
</n-thing>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
</div>
|
||||
<n-drawer v-model:show="curMail" width="100%" :trap-focus="false" :block-scroll="false" to="#drawer-target">
|
||||
<n-drawer-content :title="curMail.subject" closable>
|
||||
<n-card style="overflow: auto;">
|
||||
<n-space>
|
||||
<n-tag type="info">
|
||||
ID: {{ curMail.id }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
{{ curMail.created_at }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
FROM: {{ curMail.source }}
|
||||
</n-tag>
|
||||
<n-popconfirm @positive-click="deleteMail">
|
||||
<template #trigger>
|
||||
<n-button tertiary type="error" size="small">{{ t('delete') }}</n-button>
|
||||
</template>
|
||||
{{ t('deleteMailTip') }}
|
||||
</n-popconfirm>
|
||||
<n-button v-if="curMail.attachments && curMail.attachments.length > 0" size="small" tertiary type="info"
|
||||
@click="getAttachments(curMail.attachments)">
|
||||
{{ t('attachments') }}
|
||||
</n-button>
|
||||
<n-button tag="a" target="_blank" tertiary type="info" size="small" :download="curMail.id + '.eml'"
|
||||
:href="getDownloadEmlUrl(curMail)">
|
||||
<n-icon :component="CloudDownloadRound" />
|
||||
{{ t('downloadMail') }}
|
||||
</n-button>
|
||||
</n-space>
|
||||
<div v-html="curMail.message" style="margin-top: 10px;"></div>
|
||||
</n-card>
|
||||
</n-drawer-content>
|
||||
</n-drawer>
|
||||
</div>
|
||||
</n-layout>
|
||||
</n-drawer-content>
|
||||
</n-drawer>
|
||||
</div>
|
||||
<n-modal v-model:show="showAttachments" preset="dialog" title="Dialog">
|
||||
<template #header>
|
||||
<div>{{ t("attachments") }}</div>
|
||||
@@ -302,8 +333,6 @@ onMounted(async () => {
|
||||
</template>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
<template #action>
|
||||
</template>
|
||||
</n-modal>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,11 +1,22 @@
|
||||
<script setup>
|
||||
import MailBox from './MailBox.vue';
|
||||
import MailBox from '../components/MailBox.vue';
|
||||
import { useGlobalState } from '../store'
|
||||
const { settings } = useGlobalState()
|
||||
import { api } from '../api'
|
||||
|
||||
const { settings, openSettings } = useGlobalState()
|
||||
|
||||
const fetchMailData = async (limit, offset) => {
|
||||
return await api.fetch(`/api/mails?limit=${limit}&offset=${offset}`);
|
||||
};
|
||||
|
||||
const deleteMail = async (curMailId) => {
|
||||
await api.fetch(`/api/mails/${curMailId}`, { method: 'DELETE' });
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<MailBox v-if="settings.address" />
|
||||
<div v-if="settings.address">
|
||||
<MailBox :showEMailTo="false" :enableUserDeleteEmail="openSettings.enableUserDeleteEmail"
|
||||
:fetchMailData="fetchMailData" :deleteMail="deleteMail" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -20,7 +20,7 @@ const { t } = useI18n({
|
||||
en: {
|
||||
name: 'Name',
|
||||
created_at: 'Created At',
|
||||
update_at: 'Update At',
|
||||
updated_at: 'Update At',
|
||||
mail_count: 'Mail Count',
|
||||
send_count: 'Send Count',
|
||||
showPass: 'Show Passwrod',
|
||||
@@ -39,7 +39,7 @@ const { t } = useI18n({
|
||||
zh: {
|
||||
name: '名称',
|
||||
created_at: '创建时间',
|
||||
update_at: '更新时间',
|
||||
updated_at: '更新时间',
|
||||
mail_count: '邮件数量',
|
||||
send_count: '发送数量',
|
||||
showPass: '显示密码',
|
||||
|
||||
@@ -1,63 +1,43 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useGlobalState } from '../../store'
|
||||
import { api } from '../../api'
|
||||
import { processItem } from '../../utils/email-parser'
|
||||
import MailBox from '../../components/MailBox.vue';
|
||||
|
||||
const {
|
||||
localeCache, adminAuth, showAdminAuth,
|
||||
adminMailTabAddress
|
||||
} = useGlobalState()
|
||||
const message = useMessage()
|
||||
|
||||
const { t } = useI18n({
|
||||
locale: localeCache.value || 'zh',
|
||||
messages: {
|
||||
en: {
|
||||
mails: 'Emails',
|
||||
itemCount: 'itemCount',
|
||||
addressQueryTip: 'Leave blank to query all addresses',
|
||||
query: 'Query',
|
||||
},
|
||||
zh: {
|
||||
mails: '邮件',
|
||||
itemCount: '总数',
|
||||
addressQueryTip: '留空查询所有地址',
|
||||
query: '查询',
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const mailData = ref([])
|
||||
const mailCount = ref(0)
|
||||
const mailPage = ref(1)
|
||||
const mailPageSize = ref(20)
|
||||
const mailBoxKey = ref("")
|
||||
|
||||
watch([mailPage, mailPageSize, adminMailTabAddress], async () => {
|
||||
await fetchMailData()
|
||||
})
|
||||
const queryAddress = () => {
|
||||
mailBoxKey.value = adminMailTabAddress.value;
|
||||
}
|
||||
|
||||
const fetchMailData = async () => {
|
||||
if (!adminMailTabAddress.value) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const { results, count } = await api.fetch(
|
||||
`/admin/mails`
|
||||
+ `?address=${adminMailTabAddress.value}`
|
||||
+ `&limit=${mailPageSize.value}`
|
||||
+ `&offset=${(mailPage.value - 1) * mailPageSize.value}`
|
||||
);
|
||||
mailData.value = await Promise.all(results.map(async (item) => {
|
||||
return await processItem(item);
|
||||
}));
|
||||
if (count > 0) {
|
||||
mailCount.value = count;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
message.error(error.message || "error");
|
||||
}
|
||||
const fetchMailData = async (limit, offset) => {
|
||||
return await api.fetch(
|
||||
`/admin/mails`
|
||||
+ `?limit=${limit}`
|
||||
+ `&offset=${offset}`
|
||||
+ (adminMailTabAddress.value ? `&address=${adminMailTabAddress.value}` : '')
|
||||
);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -65,48 +45,17 @@ onMounted(async () => {
|
||||
showAdminAuth.value = true;
|
||||
return;
|
||||
}
|
||||
await fetchMailData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<n-input-group>
|
||||
<n-input v-model:value="adminMailTabAddress" />
|
||||
<n-button @click="fetchMailData" type="primary" ghost>
|
||||
<n-input v-model:value="adminMailTabAddress" :placeholder="t('addressQueryTip')" />
|
||||
<n-button @click="queryAddress" type="primary" ghost>
|
||||
{{ t('query') }}
|
||||
</n-button>
|
||||
</n-input-group>
|
||||
<n-list hoverable clickable>
|
||||
<div style="display: inline-block; margin-bottom: 10px;">
|
||||
<n-pagination v-model:page="mailPage" v-model:page-size="mailPageSize" :item-count="mailCount" simple>
|
||||
<template #prefix="{ itemCount }">
|
||||
{{ t('itemCount') }}: {{ itemCount }}
|
||||
</template>
|
||||
</n-pagination>
|
||||
</div>
|
||||
<n-list-item v-for="row in mailData" v-bind:key="row.id">
|
||||
<n-thing class="center" :title="row.subject">
|
||||
<template #description>
|
||||
<n-space>
|
||||
<n-tag type="info">
|
||||
FROM: {{ row.source }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
ID: {{ row.id }}
|
||||
</n-tag>
|
||||
</n-space>
|
||||
</template>
|
||||
<div v-html="row.message"></div>
|
||||
</n-thing>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
<MailBox :key="mailBoxKey" :enableUserDeleteEmail="false" :fetchMailData="fetchMailData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.n-pagination {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,56 +1,18 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
import { useGlobalState } from '../../store'
|
||||
import { api } from '../../api'
|
||||
import { processItem } from '../../utils/email-parser'
|
||||
import MailBox from '../../components/MailBox.vue';
|
||||
|
||||
const {
|
||||
localeCache, adminAuth, showAdminAuth
|
||||
} = useGlobalState()
|
||||
const message = useMessage()
|
||||
const { adminAuth, showAdminAuth } = useGlobalState()
|
||||
|
||||
const { t } = useI18n({
|
||||
locale: localeCache.value || 'zh',
|
||||
messages: {
|
||||
en: {
|
||||
itemCount: 'itemCount',
|
||||
refresh: 'Refresh'
|
||||
},
|
||||
zh: {
|
||||
itemCount: '总数',
|
||||
refresh: '刷新'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const mailUnknowData = ref([])
|
||||
const mailUnknowCount = ref(0)
|
||||
const mailUnknowPage = ref(1)
|
||||
const mailUnknowPageSize = ref(20)
|
||||
|
||||
watch([mailUnknowPage, mailUnknowPageSize], async () => {
|
||||
await fetchMailUnknowData()
|
||||
})
|
||||
|
||||
const fetchMailUnknowData = async () => {
|
||||
try {
|
||||
const { results, count } = await api.fetch(
|
||||
`/admin/mails_unknow`
|
||||
+ `?limit=${mailUnknowPageSize.value}`
|
||||
+ `&offset=${(mailUnknowPage.value - 1) * mailUnknowPage.value}`
|
||||
);
|
||||
mailUnknowData.value = await Promise.all(results.map(async (item) => {
|
||||
return await processItem(item);
|
||||
}));
|
||||
if (count > 0) {
|
||||
mailUnknowCount.value = count;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
message.error(error.message || "error");
|
||||
}
|
||||
const fetchMailUnknowData = async (limit, offset) => {
|
||||
return await api.fetch(
|
||||
`/admin/mails_unknow`
|
||||
+ `?limit=${limit}`
|
||||
+ `&offset=${offset}`
|
||||
);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -58,49 +20,11 @@ onMounted(async () => {
|
||||
showAdminAuth.value = true;
|
||||
return;
|
||||
}
|
||||
await fetchMailUnknowData();
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<n-button @click="fetchMailUnknowData" type="primary" ghost>
|
||||
{{ t('refresh') }}
|
||||
</n-button>
|
||||
<n-list hoverable clickable>
|
||||
<div style="display: inline-block; margin-bottom: 10px;">
|
||||
<n-pagination v-model:page="mailUnknowPage" v-model:page-size="mailUnknowPageSize"
|
||||
:item-count="mailUnknowCount" simple>
|
||||
<template #prefix="{ itemCount }">
|
||||
{{ t('itemCount') }}: {{ itemCount }}
|
||||
</template>
|
||||
</n-pagination>
|
||||
</div>
|
||||
<n-list-item v-for="row in mailUnknowData" v-bind:key="row.id">
|
||||
<n-thing class="center" :title="row.subject">
|
||||
<template #description>
|
||||
<n-space>
|
||||
<n-tag type="info">
|
||||
FROM: {{ row.source }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
ID: {{ row.id }}
|
||||
</n-tag>
|
||||
<n-tag type="info">
|
||||
TO: {{ row.address }}
|
||||
</n-tag>
|
||||
</n-space>
|
||||
</template>
|
||||
<div v-html="row.message"></div>
|
||||
</n-thing>
|
||||
</n-list-item>
|
||||
</n-list>
|
||||
<div v-if="adminAuth">
|
||||
<MailBox :enableUserDeleteEmail="false" :fetchMailData="fetchMailUnknowData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.n-pagination {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -100,6 +100,22 @@ api.get('/admin/mails', async (c) => {
|
||||
if (!offset || offset < 0) {
|
||||
return c.text("Invalid offset", 400)
|
||||
}
|
||||
if (!address) {
|
||||
const { results } = await c.env.DB.prepare(
|
||||
`SELECT * FROM raw_mails order by id desc limit ? offset ?`
|
||||
).bind(limit, offset).all();
|
||||
let count = 0;
|
||||
if (offset == 0) {
|
||||
const { count: mailCount } = await c.env.DB.prepare(
|
||||
`SELECT count(*) as count FROM raw_mails`
|
||||
).first();
|
||||
count = mailCount;
|
||||
}
|
||||
return c.json({
|
||||
results: results,
|
||||
count: count
|
||||
})
|
||||
}
|
||||
const { results } = await c.env.DB.prepare(
|
||||
`SELECT * FROM raw_mails where address = ? order by id desc limit ? offset ?`
|
||||
).bind(address, limit, offset).all();
|
||||
|
||||
@@ -18,7 +18,7 @@ api.get('/api/mails', async (c) => {
|
||||
return c.text("Invalid offset", 400)
|
||||
}
|
||||
const { results } = await c.env.DB.prepare(
|
||||
`SELECT id, source, raw, created_at FROM raw_mails where address = ? order by id desc limit ? offset ?`
|
||||
`SELECT * FROM raw_mails where address = ? order by id desc limit ? offset ?`
|
||||
).bind(address, limit, offset).all();
|
||||
let count = 0;
|
||||
if (offset == 0) {
|
||||
|
||||
Reference in New Issue
Block a user