mirror of
https://github.com/schroinerxy/cloud-mail.git
synced 2026-06-21 19:35:50 +08:00
新增点击复制邮箱功能
This commit is contained in:
@@ -45,6 +45,8 @@
|
||||
|
||||
- **📦附件收发**:支持收发附件,使用R2对象存储保存和下载文件
|
||||
|
||||
- **🔔邮件推送**:接收邮件后可以转发到TG机器人或其他服务商邮箱
|
||||
|
||||
- **📈数据可视化**:使用echarts对系统数据详情,用户邮件增长可视化显示
|
||||
|
||||
- **⭐星标邮件**:标记重要邮件,以便快速查阅
|
||||
@@ -186,6 +188,7 @@ cloud-mail
|
||||
│ │ ├── entity #数据库实体层
|
||||
│ │ ├── error #自定义异常
|
||||
│ │ ├── hono #web框架配置 拦截器等
|
||||
│ │ ├── init #数据库缓存初始化
|
||||
│ │ ├── model #响应体数据封装
|
||||
│ │ ├── security #身份认证层
|
||||
│ │ ├── service #服务层
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 207 KiB |
@@ -302,7 +302,7 @@ function htmlToText(email) {
|
||||
|
||||
function cleanSpace(text) {
|
||||
return text
|
||||
.replace(/[\u200B-\u200F\uFEFF\u034F\u200B-\u200F\u00A0\u3000]/g, '') // 移除零宽空格
|
||||
.replace(/[\u200B-\u200F\uFEFF\u034F\u200B-\u200F\u00A0\u3000\u00AD]/g, '')// 移除零宽空格
|
||||
.replace(/\s+/g, ' ') // 多空白合并成一个空格
|
||||
.trim();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,13 @@
|
||||
<el-scrollbar class="scrollbar">
|
||||
<div v-infinite-scroll="getAccountList" :infinite-scroll-distance="600" :infinite-scroll-immediate="false">
|
||||
<el-card class="item" :class="itemBg(item.accountId)" v-for="item in accounts" :key="item.accountId" @click="changeAccount(item)">
|
||||
<div class="account" @click.stop>
|
||||
{{ item.email }}
|
||||
<div class="account" @click.stop="copyAccount(item.email)">
|
||||
<el-tooltip v-if="showCopyInfo" effect="dark" :hide-after="0" :show-after="800" placement="top" content="点击复制">
|
||||
{{ item.email }}
|
||||
</el-tooltip>
|
||||
<template v-else >
|
||||
{{ item.email }}
|
||||
</template>
|
||||
</div>
|
||||
<div class="opt">
|
||||
<div class="send-email" @click.stop>
|
||||
@@ -142,6 +147,7 @@ const addRef = ref({})
|
||||
let account = null
|
||||
let turnstileId = null
|
||||
let verifyToken = ''
|
||||
let showCopyInfo = window.innerWidth > 1024
|
||||
const addForm = reactive({
|
||||
email: '',
|
||||
suffix: settingStore.domainList[0]
|
||||
@@ -264,6 +270,24 @@ function add() {
|
||||
},100)
|
||||
}
|
||||
|
||||
async function copyAccount(account) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(account);
|
||||
ElMessage({
|
||||
message: '复制成功',
|
||||
type: 'success',
|
||||
plain: true,
|
||||
})
|
||||
} catch (err) {
|
||||
console.error('复制失败:', err);
|
||||
ElMessage({
|
||||
message: '复制失败',
|
||||
type: 'error',
|
||||
plain: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getAccountList() {
|
||||
|
||||
if (loading.value || followLoading.value || noLoading.value) return;
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
<el-menu-item @click="router.push({name: 'star'})" index="star"
|
||||
:class="route.meta.name === 'star' ? 'choose-item' : ''">
|
||||
<Icon icon="solar:star-line-duotone" width="20" height="20" />
|
||||
<span class="menu-name" style="margin-left: 20px">星标邮件</span>
|
||||
<span class="menu-name" style="margin-left: 21px">星标邮件</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="router.push({name: 'setting'})" index="setting"
|
||||
:class="route.meta.name === 'setting' ? 'choose-item' : ''">
|
||||
<Icon icon="fluent:settings-48-regular" width="20" height="20" />
|
||||
<span class="menu-name" style="margin-left: 20px">个人设置</span>
|
||||
<span class="menu-name" style="margin-left: 21px">个人设置</span>
|
||||
</el-menu-item>
|
||||
<div class="manage-title" v-perm="['user:query','role:query','setting:query','analysis:query']">
|
||||
<div>管理</div>
|
||||
@@ -32,27 +32,27 @@
|
||||
<el-menu-item @click="router.push({name: 'analysis'})" index="analysis" v-perm="'analysis:query'"
|
||||
:class="route.meta.name === 'analysis' ? 'choose-item' : ''">
|
||||
<Icon icon="fluent:data-pie-20-regular" width="24" height="24" />
|
||||
<span class="menu-name" style="margin-left: 16px">分析页</span>
|
||||
<span class="menu-name" style="margin-left: 18px">分析页</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="router.push({name: 'user'})" index="setting" v-perm="'user:query'"
|
||||
:class="route.meta.name === 'user' ? 'choose-item' : ''">
|
||||
<Icon icon="iconoir:user" width="24" height="24" />
|
||||
<span class="menu-name" style="margin-left: 16px">用户列表</span>
|
||||
<Icon icon="si:user-alt-2-line" width="20" height="20" />
|
||||
<span class="menu-name" style="margin-left: 21px">用户列表</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="router.push({name: 'sys-email'})" index="sys-email" v-perm="'sys-email:query'"
|
||||
:class="route.meta.name === 'sys-email' ? 'choose-item' : ''">
|
||||
<Icon icon="fluent:mail-list-28-regular" width="22" height="22" />
|
||||
<span class="menu-name" style="margin-left: 18px">邮件列表</span>
|
||||
<span class="menu-name" style="margin-left: 20px">邮件列表</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="router.push({name: 'role'})" index="setting" v-perm="'role:query'"
|
||||
:class="route.meta.name === 'role' ? 'choose-item' : ''">
|
||||
<Icon icon="hugeicons:key-02" width="22" height="22" />
|
||||
<span class="menu-name" style="margin-left: 18px">权限控制</span>
|
||||
<span class="menu-name" style="margin-left: 20px">权限控制</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item @click="router.push({name: 'sys-setting'})" index="sys-setting" v-perm="'setting:query'"
|
||||
:class="route.meta.name === 'sys-setting' ? 'choose-item' : ''">
|
||||
<Icon icon="eos-icons:system-ok-outlined" width="18" height="18" />
|
||||
<span class="menu-name" style="margin-left: 23px">系统设置</span>
|
||||
<span class="menu-name" style="margin-left: 24px">系统设置</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</div>
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
</div>
|
||||
|
||||
<div class="settings-card">
|
||||
<div class="card-title">邮件转发通知</div>
|
||||
<div class="card-title">邮件推送</div>
|
||||
<div class="card-content">
|
||||
<div class="setting-item">
|
||||
<div><span>Telegram 机器人</span></div>
|
||||
@@ -362,7 +362,7 @@
|
||||
<template #header>
|
||||
<div class="forward-head">
|
||||
<span class="forward-set-title">第三方邮箱</span>
|
||||
<el-tooltip effect="dark" trigger="click" content="可以将邮件转到其他服务商邮箱,需要在cloudflare验证邮箱">
|
||||
<el-tooltip effect="dark" content="可以将邮件转到其他服务商邮箱,需要在cloudflare验证邮箱">
|
||||
<Icon class="warning" icon="fe:warning" width="18" height="18"/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
+27
-27
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
@@ -6,8 +6,8 @@
|
||||
<title></title>
|
||||
<link rel="icon" href="/assets/favicon-C5dAZutX.svg" type="image/svg+xml">
|
||||
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
|
||||
<script type="module" crossorigin src="/assets/index-Cgh0xJS2.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Cobuvpco.css">
|
||||
<script type="module" crossorigin src="/assets/index-DJSpSDrA.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-DuYAEzF2.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="loading-first">
|
||||
|
||||
@@ -115,7 +115,7 @@ export async function email(message, env, ctx) {
|
||||
<b>收件人:\u200B</b>${message.to}
|
||||
<b>时间:</b>${dayjs.utc(emailRow.createTime).tz('Asia/Shanghai').format('YYYY-MM-DD HH:mm')}
|
||||
|
||||
${emailUtils.htmlToText(params.content) || ''}
|
||||
${params.text || emailUtils.htmlToText(params.content) || ''}
|
||||
`;
|
||||
|
||||
const tgChatIds = tgChatId.split(',');
|
||||
|
||||
Reference in New Issue
Block a user