mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-06-05 23:51:39 +08:00
* fix: auto-reply not triggering when source_prefix is empty (#459) - Empty source_prefix now matches all senders (was short-circuiting as falsy) - Support regex matching with /pattern/ syntax in source_prefix - Backward compatible: plain strings still use startsWith - Use E2E_TEST_MODE switch to skip cloudflare:email import in tests - Track reply() calls in E2E mock for testability Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: update auto-reply UI labels for regex support Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update changelogs for auto-reply fix and regex feature Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: upgrade version to v1.5.0 - Update version number to 1.5.0 in all package.json files and constants.ts - Split CHANGELOG: v1.4.0 entries finalized, new v1.5.0(main) section with auto-reply changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add error logging for invalid regex in auto-reply source_prefix Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: address CodeRabbit review suggestions - Use const object instead of let for mock state tracking - Add log when auto-reply subject/message falls back to defaults Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add source_prefix regex syntax to auto-reply docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
140 lines
4.0 KiB
Vue
140 lines
4.0 KiB
Vue
<script setup>
|
|
import { useI18n } from 'vue-i18n'
|
|
import { onMounted, ref } from '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: 'Sender Filter',
|
|
sourcePrefixPlaceholder: 'Empty=all, prefix match, or /regex/',
|
|
name: 'Name',
|
|
enableAutoReply: 'Enable Auto Reply',
|
|
subject: 'Subject',
|
|
autoReply: 'Auto Reply',
|
|
save: 'Save',
|
|
},
|
|
zh: {
|
|
success: '成功',
|
|
settings: '设置',
|
|
sourcePrefix: '发件人过滤',
|
|
sourcePrefixPlaceholder: '留空=全部匹配,前缀匹配,或 /正则/',
|
|
name: '名称',
|
|
enableAutoReply: '启用自动回复',
|
|
subject: '主题',
|
|
autoReply: '自动回复',
|
|
save: '保存',
|
|
}
|
|
}
|
|
});
|
|
|
|
const fetchData = async () => {
|
|
try {
|
|
const res = await api.fetch("/api/auto_reply")
|
|
sourcePrefix.value = res.source_prefix || ""
|
|
enableAutoReply.value = res.enabled || false
|
|
name.value = res.name || ""
|
|
autoReplyMessage.value = res.message || ""
|
|
subject.value = res.subject || ""
|
|
} catch (error) {
|
|
message.error(error.message || "error");
|
|
}
|
|
}
|
|
|
|
const saveData = async () => {
|
|
try {
|
|
await api.fetch("/api/auto_reply", {
|
|
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(async () => {
|
|
await fetchData()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div class="center">
|
|
<n-card :bordered="false" embedded v-if="settings.address" :title='t("settings")'>
|
|
<div class="right">
|
|
<n-button type="primary" @click="saveData">{{ t('save') }}</n-button>
|
|
</div>
|
|
<div class="left">
|
|
<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"
|
|
:placeholder="t('sourcePrefixPlaceholder')" />
|
|
</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>
|
|
</div>
|
|
</n-card>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.n-card {
|
|
max-width: 800px;
|
|
}
|
|
|
|
.n-button {
|
|
text-align: left;
|
|
}
|
|
|
|
.center {
|
|
display: flex;
|
|
text-align: center;
|
|
place-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.left {
|
|
text-align: left;
|
|
place-items: left;
|
|
justify-content: left;
|
|
}
|
|
|
|
.right {
|
|
text-align: right;
|
|
place-items: right;
|
|
justify-content: right;
|
|
}
|
|
</style>
|