diff --git a/frontend/src/i18n/i18n.js b/frontend/src/i18n/i18n.js index 79a2c359..152ff0c2 100644 --- a/frontend/src/i18n/i18n.js +++ b/frontend/src/i18n/i18n.js @@ -11,6 +11,7 @@ const lang = { "plugin_settings": "插件配置", "lang": "zhCn", "submit": "提交", + "refresh": "刷新", "compose": "发件", "new": "新", "account": "账号", diff --git a/frontend/src/views/List/List.css b/frontend/src/views/List/List.css index ebb41c92..e1991e25 100644 --- a/frontend/src/views/List/List.css +++ b/frontend/src/views/List/List.css @@ -66,6 +66,15 @@ transform: translateY(-1px); } +.refresh-btn { + margin-left: 4px; +} + +.refresh-btn:hover .el-icon { + transform: rotate(90deg); + transition: transform 0.3s ease-in-out; +} + .compose-btn { border-radius: 999px; font-weight: 600; diff --git a/frontend/src/views/List/List.js b/frontend/src/views/List/List.js index c80bc5a5..19297c81 100644 --- a/frontend/src/views/List/List.js +++ b/frontend/src/views/List/List.js @@ -2,13 +2,14 @@ import './List.js' import {EpArrowDownBold} from "vue-icons-plus/ep"; -import {Delete, View, Folder, EditPen, Warning, CircleCheck, Switch, Check} from "@element-plus/icons-vue"; +import {Delete, View, Folder, EditPen, Warning, CircleCheck, Switch, Check, Refresh} from "@element-plus/icons-vue"; import {useRouter} from 'vue-router' -import {ref, watch, computed} from 'vue' +import {ref, watch, computed, onMounted, onUnmounted} from 'vue' import useGroupStore from '../../stores/group' +import {useGlobalStatusStore} from '../../stores/useGlobalStatusStore' import lang from '../../i18n/i18n'; @@ -20,8 +21,11 @@ export function usePage() { const router = useRouter(); const groupStore = useGroupStore() + const globalStatus = useGlobalStatusStore() const groupList = ref([]) + const isRefreshing = ref(false) + let refreshTimer = null const taskTableDataRef = ref(null) @@ -58,11 +62,23 @@ export function usePage() { const totalPage = ref(0) - const updateList = function () { - http.post("/api/v1/email/list", {tag: tag, page_size: 15}).then(res => { + const updateList = async function (silent = false) { + if (!silent) { + isRefreshing.value = true + } + try { + const res = await http.post("/api/v1/email/list", {tag: tag, page_size: 15}) data.value = res.data.list || [] totalPage.value = res.data.total_page || 0 - }) + } catch (err) { + if (!silent) { + ElMessage.error(err?.message || '获取邮件列表失败') + } + } finally { + if (!silent) { + isRefreshing.value = false + } + } } const updateGroupList = async function () { @@ -81,6 +97,48 @@ export function usePage() { updateList() updateGroupList() + + // 定时刷新逻辑:已登录 60s,未登录 300s + const getRefreshInterval = () => { + return globalStatus.isLogin ? 60000 : 300000 + } + + const startAutoRefreshTimer = () => { + stopAutoRefreshTimer() + const interval = getRefreshInterval() + refreshTimer = setInterval(() => { + updateList(true) + updateGroupList() + }, interval) + } + + const stopAutoRefreshTimer = () => { + if (refreshTimer) { + clearInterval(refreshTimer) + refreshTimer = null + } + } + + const manualRefresh = async () => { + await Promise.all([ + updateList(false), + updateGroupList() + ]) + ElMessage.success('已刷新') + startAutoRefreshTimer() + } + + watch(() => globalStatus.isLogin, () => { + startAutoRefreshTimer() + }) + + onMounted(() => { + startAutoRefreshTimer() + }) + + onUnmounted(() => { + stopAutoRefreshTimer() + }) const rowClick = function (row) { router.push("/detail/" + row.id) @@ -259,7 +317,9 @@ export function usePage() { trustSender, showError, errorDialogVisible, - currentErrorMsg + currentErrorMsg, + isRefreshing, + manualRefresh } } @@ -272,5 +332,6 @@ export { EpArrowDownBold, EditPen, Warning, - Check + Check, + Refresh } diff --git a/frontend/src/views/List/List.vue b/frontend/src/views/List/List.vue index dc4c51b8..f4173b01 100644 --- a/frontend/src/views/List/List.vue +++ b/frontend/src/views/List/List.vue @@ -32,6 +32,9 @@ + + {{ lang.refresh }} + {{ lang.compose }} @@ -121,7 +124,7 @@