mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-06-09 01:20:28 +08:00
feat: add auto reply (#49)
* feat: add auto reply * feat: add auto reply * feat: update readme * feat: add auto reply
This commit is contained in:
@@ -2,7 +2,8 @@ import { useGlobalState } from '../store'
|
||||
import axios from 'axios'
|
||||
|
||||
const API_BASE = import.meta.env.VITE_API_BASE || "";
|
||||
const { loading, auth, jwt, openSettings, showAuth, adminAuth, showAdminAuth } = useGlobalState();
|
||||
const { loading, auth, jwt, settings, openSettings } = useGlobalState();
|
||||
const { showAuth, adminAuth, showAdminAuth } = useGlobalState();
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL: API_BASE,
|
||||
@@ -65,9 +66,11 @@ const getSettings = async () => {
|
||||
if (typeof jwt.value != 'string' || jwt.value.trim() === '' || jwt.value === 'undefined') {
|
||||
return "";
|
||||
}
|
||||
loading.value = true;
|
||||
const res = await apiFetch("/api/settings");;
|
||||
return res["address"];
|
||||
settings.value = {
|
||||
address: res["address"],
|
||||
auto_reply: res["auto_reply"]
|
||||
};
|
||||
}
|
||||
|
||||
const adminShowPassword = async (id) => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import Index from '../views/Index.vue'
|
||||
import Settings from '../views/Settings.vue'
|
||||
import Admin from '../views/Admin.vue'
|
||||
|
||||
const router = createRouter({
|
||||
@@ -9,6 +10,10 @@ const router = createRouter({
|
||||
path: '/',
|
||||
component: Index
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
component: Settings
|
||||
},
|
||||
{
|
||||
path: '/admin',
|
||||
component: Admin
|
||||
|
||||
@@ -12,6 +12,16 @@ export const useGlobalState = createGlobalState(
|
||||
value: 'test.com'
|
||||
}]
|
||||
})
|
||||
const settings = ref({
|
||||
address: '',
|
||||
auto_reply: {
|
||||
subject: '',
|
||||
message: '',
|
||||
enabled: false,
|
||||
source_prefix: '',
|
||||
name: '',
|
||||
}
|
||||
})
|
||||
const showAuth = ref(false);
|
||||
const showAdminAuth = ref(false);
|
||||
const auth = useStorage('auth', '');
|
||||
@@ -21,6 +31,7 @@ export const useGlobalState = createGlobalState(
|
||||
const themeSwitch = useStorage('themeSwitch', false);
|
||||
return {
|
||||
loading,
|
||||
settings,
|
||||
openSettings,
|
||||
showAuth,
|
||||
auth,
|
||||
|
||||
@@ -12,8 +12,7 @@ import { api } from '../api'
|
||||
const { toClipboard } = useClipboard()
|
||||
const message = useMessage()
|
||||
|
||||
const address = ref("")
|
||||
const { jwt, openSettings } = useGlobalState()
|
||||
const { jwt, settings, openSettings } = useGlobalState()
|
||||
const autoRefresh = ref(false)
|
||||
const data = ref([])
|
||||
const timer = ref(null)
|
||||
@@ -84,7 +83,7 @@ watch([page, pageSize], async ([page, pageSize], [oldPage, oldPageSize]) => {
|
||||
})
|
||||
|
||||
const refresh = async () => {
|
||||
if (typeof address.value != 'string' || address.value.trim() === '') {
|
||||
if (typeof settings.value.address != 'string' || settings.value.address.trim() === '') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -105,7 +104,7 @@ const refresh = async () => {
|
||||
|
||||
const copy = async () => {
|
||||
try {
|
||||
await toClipboard(address.value)
|
||||
await toClipboard(settings.value.address)
|
||||
message.success('Copied');
|
||||
} catch (e) {
|
||||
message.error(e.message || "error");
|
||||
@@ -120,7 +119,7 @@ const newEmail = async () => {
|
||||
+ `&domain=${emailDomain.value || ''}`
|
||||
);
|
||||
jwt.value = res["jwt"];
|
||||
address.value = await api.getSettings();
|
||||
await api.getSettings();
|
||||
await refresh();
|
||||
showNewEmail.value = false;
|
||||
showPassword.value = true;
|
||||
@@ -132,7 +131,7 @@ const newEmail = async () => {
|
||||
onMounted(async () => {
|
||||
await api.getOpenSettings(message);
|
||||
emailDomain.value = openSettings.value.domains ? openSettings.value.domains[0].value : "";
|
||||
address.value = await api.getSettings();
|
||||
await api.getSettings();
|
||||
await refresh();
|
||||
});
|
||||
</script>
|
||||
@@ -140,9 +139,9 @@ onMounted(async () => {
|
||||
<template>
|
||||
<div>
|
||||
<n-layout>
|
||||
<n-alert :type='address ? "info" : "warning"' show-icon>
|
||||
<span v-if="address">
|
||||
{{ t('yourAddress') }} <b>{{ address }}</b>
|
||||
<n-alert :type='settings.address ? "info" : "warning"' show-icon>
|
||||
<span v-if="settings.address">
|
||||
{{ t('yourAddress') }} <b>{{ settings.address }}</b>
|
||||
<n-button @click="copy" size="small" tertiary round type="primary">
|
||||
{{ t('copy') }}
|
||||
</n-button>
|
||||
@@ -151,7 +150,7 @@ onMounted(async () => {
|
||||
{{ t('pleaseGetNewEmail') }}
|
||||
</span>
|
||||
</n-alert>
|
||||
<n-button v-if="address" class="center" @click="showPassword = true" tertiary round type="primary">
|
||||
<n-button v-if="settings.address" class="center" @click="showPassword = true" tertiary round type="primary">
|
||||
{{ t('showPassword') }}
|
||||
</n-button>
|
||||
<n-button v-else class="center" @click="showNewEmail = true" tertiary round type="primary">
|
||||
|
||||
@@ -59,6 +59,8 @@ const { t } = useI18n({
|
||||
logoutConfirm: 'Are you sure to logout?',
|
||||
auth: 'Auth',
|
||||
authTip: 'Please enter the correct auth code',
|
||||
settings: 'Settings',
|
||||
home: 'Home',
|
||||
},
|
||||
zh: {
|
||||
title: 'Cloudflare 临时邮件',
|
||||
@@ -69,12 +71,26 @@ const { t } = useI18n({
|
||||
logoutConfirm: '确定要登出吗?',
|
||||
auth: '授权',
|
||||
authTip: '请输入正确的授权码',
|
||||
settings: '设置',
|
||||
home: '主页',
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const menuOptions = computed(() => [
|
||||
{
|
||||
label: () => h(
|
||||
NButton,
|
||||
{
|
||||
tertiary: true,
|
||||
ghost: true,
|
||||
onClick: () => router.push('/')
|
||||
},
|
||||
{ default: () => t('home') }
|
||||
),
|
||||
key: "home"
|
||||
},
|
||||
{
|
||||
label: () => h(
|
||||
NButton,
|
||||
@@ -86,7 +102,7 @@ const menuOptions = computed(() => [
|
||||
{ default: () => "Admin" }
|
||||
),
|
||||
show: !!adminAuth.value,
|
||||
key: "home"
|
||||
key: "admin"
|
||||
},
|
||||
{
|
||||
label: () => h(
|
||||
@@ -127,6 +143,18 @@ const menuOptions = computed(() => [
|
||||
),
|
||||
show: !!jwt.value,
|
||||
key: "logout"
|
||||
},
|
||||
{
|
||||
label: () => h(
|
||||
NButton,
|
||||
{
|
||||
tertiary: true,
|
||||
ghost: true,
|
||||
onClick: () => { router.push('/settings') }
|
||||
},
|
||||
{ default: () => t('settings') }
|
||||
),
|
||||
key: "settings"
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -186,7 +214,7 @@ const menuOptionsMobile = [
|
||||
</template>
|
||||
<p>{{ t('logoutConfirm') }}</p>
|
||||
<template #action>
|
||||
<n-button @click="login" size="small" tertiary round type="primary">
|
||||
<n-button @click="logout" size="small" tertiary round type="primary">
|
||||
{{ t('logout') }}
|
||||
</n-button>
|
||||
</template>
|
||||
|
||||
102
frontend/src/views/Settings.vue
Normal file
102
frontend/src/views/Settings.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<script setup>
|
||||
import { NSpace, NFormItem, NInput, NSwitch, NButton } from 'naive-ui'
|
||||
import { useMessage } from 'naive-ui'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
import Header from './Header.vue'
|
||||
import { useGlobalState } from '../store'
|
||||
import { api } from '../api'
|
||||
|
||||
const message = useMessage()
|
||||
const sourcePrefix = ref("")
|
||||
const enableAutoReply = ref(false)
|
||||
const autoReplyMessage = ref("")
|
||||
const subject = ref("")
|
||||
const name = ref("")
|
||||
|
||||
const { settings } = useGlobalState()
|
||||
|
||||
|
||||
const { t } = useI18n({
|
||||
locale: 'zh',
|
||||
messages: {
|
||||
en: {
|
||||
success: 'Success',
|
||||
settings: 'Settings',
|
||||
sourcePrefix: 'Source Mail Prefix',
|
||||
name: 'Name',
|
||||
enableAutoReply: 'Enable Auto Reply',
|
||||
subject: 'Subject',
|
||||
autoReply: 'Auto Reply',
|
||||
save: 'Save',
|
||||
},
|
||||
zh: {
|
||||
success: '成功',
|
||||
settings: '设置',
|
||||
sourcePrefix: '来源邮件前缀',
|
||||
name: '名称',
|
||||
enableAutoReply: '启用自动回复',
|
||||
subject: '主题',
|
||||
autoReply: '自动回复',
|
||||
save: '保存',
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const getSettings = async () => {
|
||||
await api.getSettings()
|
||||
sourcePrefix.value = settings.value.auto_reply.source_prefix || ""
|
||||
enableAutoReply.value = settings.value.auto_reply.enabled || false
|
||||
name.value = settings.value.auto_reply.name || ""
|
||||
autoReplyMessage.value = settings.value.auto_reply.message || ""
|
||||
subject.value = settings.value.auto_reply.subject || ""
|
||||
}
|
||||
|
||||
const saveSettings = async () => {
|
||||
try {
|
||||
await api.fetch("/api/settings", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
auto_reply: {
|
||||
enabled: enableAutoReply.value,
|
||||
source_prefix: sourcePrefix.value,
|
||||
name: name.value,
|
||||
message: autoReplyMessage.value,
|
||||
subject: subject.value,
|
||||
}
|
||||
})
|
||||
})
|
||||
message.success(t("success"))
|
||||
} catch (error) {
|
||||
message.error(error.message || "error");
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getSettings()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-space vertical>
|
||||
<Header />
|
||||
<h1>{{ t("settings") }}</h1>
|
||||
<n-button type="primary" @click="saveSettings">{{ t('save') }}</n-button>
|
||||
<n-form-item :label="t('enableAutoReply')" label-placement="left">
|
||||
<n-switch v-model:value="enableAutoReply" />
|
||||
</n-form-item>
|
||||
<n-form-item :label="t('name')" label-placement="left">
|
||||
<n-input :disabled="!enableAutoReply" v-model:value="name" />
|
||||
</n-form-item>
|
||||
<n-form-item :label="t('sourcePrefix')" label-placement="left">
|
||||
<n-input :disabled="!enableAutoReply" v-model:value="sourcePrefix" />
|
||||
</n-form-item>
|
||||
<n-form-item :label="t('subject')" label-placement="left">
|
||||
<n-input :disabled="!enableAutoReply" v-model:value="subject" />
|
||||
</n-form-item>
|
||||
<n-form-item :label="t('autoReply')" label-placement="left">
|
||||
<n-input :disabled="!enableAutoReply" type="textarea" v-model:value="autoReplyMessage" />
|
||||
</n-form-item>
|
||||
</n-space>
|
||||
</template>
|
||||
Reference in New Issue
Block a user