This commit is contained in:
parent
81fcc6a0a9
commit
c9b95079a0
@ -5,7 +5,10 @@ import lang from '../i18n/i18n';
|
||||
const useGroupStore = defineStore('group', () => {
|
||||
const tag = ref("")
|
||||
const name = ref(lang.inbox)
|
||||
return { tag, name }
|
||||
const keyword = ref("")
|
||||
const revision = ref(0)
|
||||
const invalidate = () => { revision.value += 1 }
|
||||
return { tag, name, keyword, revision, invalidate }
|
||||
})
|
||||
|
||||
export default useGroupStore
|
||||
@ -26,6 +26,8 @@ export function usePage() {
|
||||
const groupList = ref([])
|
||||
const isRefreshing = ref(false)
|
||||
let refreshTimer = null
|
||||
let requestVersion = 0
|
||||
const currentPage = ref(1)
|
||||
|
||||
const taskTableDataRef = ref(null)
|
||||
|
||||
@ -49,8 +51,10 @@ export function usePage() {
|
||||
}
|
||||
})
|
||||
|
||||
watch(groupStore, async (newV) => {
|
||||
tag = newV.tag;
|
||||
watch([() => groupStore.tag, () => groupStore.keyword], () => {
|
||||
tag = groupStore.tag;
|
||||
currentPage.value = 1;
|
||||
taskTableDataRef.value?.clearSelection();
|
||||
if (tag === "") {
|
||||
tag = '{"type":0,"status":-1}'
|
||||
}
|
||||
@ -63,19 +67,33 @@ export function usePage() {
|
||||
const totalPage = ref(0)
|
||||
|
||||
const updateList = async function (silent = false) {
|
||||
if (silent && selectedRows.value.length > 0) return
|
||||
const version = ++requestVersion
|
||||
if (!silent) {
|
||||
isRefreshing.value = true
|
||||
}
|
||||
try {
|
||||
const res = await http.post("/api/v1/email/list", {tag: tag, page_size: 15})
|
||||
const res = await http.post("/api/v1/email/list", {
|
||||
tag, keyword: groupStore.keyword, current_page: currentPage.value, page_size: 15
|
||||
})
|
||||
if (version !== requestVersion) return
|
||||
if (res.errorNo !== 0) throw new Error(res.errorMsg)
|
||||
const available = new Set((res.data.list || []).map(row => row.id))
|
||||
selectedRows.value.filter(row => !available.has(row.id)).forEach(row => {
|
||||
taskTableDataRef.value?.toggleRowSelection(row, false)
|
||||
})
|
||||
data.value = res.data.list || []
|
||||
totalPage.value = res.data.total_page || 0
|
||||
if (currentPage.value > Math.max(1, totalPage.value)) {
|
||||
currentPage.value = Math.max(1, totalPage.value)
|
||||
await updateList(silent)
|
||||
}
|
||||
} catch (err) {
|
||||
if (!silent) {
|
||||
if (!silent && version === requestVersion) {
|
||||
ElMessage.error(err?.message || '获取邮件列表失败')
|
||||
}
|
||||
} finally {
|
||||
if (!silent) {
|
||||
if (!silent && version === requestVersion) {
|
||||
isRefreshing.value = false
|
||||
}
|
||||
}
|
||||
@ -97,6 +115,7 @@ export function usePage() {
|
||||
updateList()
|
||||
|
||||
updateGroupList()
|
||||
watch(() => groupStore.revision, updateGroupList)
|
||||
|
||||
// 定时刷新逻辑:已登录 60s,未登录 300s
|
||||
const getRefreshInterval = () => {
|
||||
@ -137,6 +156,7 @@ export function usePage() {
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
requestVersion += 1
|
||||
stopAutoRefreshTimer()
|
||||
})
|
||||
|
||||
@ -237,9 +257,9 @@ export function usePage() {
|
||||
}
|
||||
|
||||
const pageChange = function (p) {
|
||||
http.post("/api/v1/email/list", {tag: tag, page_size: 15, current_page: p}).then(res => {
|
||||
data.value = res.data.list || []
|
||||
})
|
||||
currentPage.value = p
|
||||
taskTableDataRef.value?.clearSelection()
|
||||
updateList()
|
||||
}
|
||||
|
||||
const trustSender = function (senderEmail) {
|
||||
@ -301,6 +321,7 @@ export function usePage() {
|
||||
tag,
|
||||
data,
|
||||
totalPage,
|
||||
currentPage,
|
||||
updateList,
|
||||
updateGroupList,
|
||||
rowClick,
|
||||
|
||||
@ -45,13 +45,14 @@
|
||||
<el-table height="100%"
|
||||
ref="taskTableDataRef"
|
||||
:data="data"
|
||||
row-key="id"
|
||||
:show-header="false"
|
||||
class="modern-mail-table"
|
||||
@row-click="rowClick"
|
||||
@selection-change="selectionChange"
|
||||
:row-style="rowStyle"
|
||||
>
|
||||
<el-table-column type="selection" width="40"/>
|
||||
<el-table-column type="selection" width="40" :reserve-selection="true"/>
|
||||
|
||||
<el-table-column width="30" class-name="status-col">
|
||||
<template #default="scope">
|
||||
@ -115,6 +116,7 @@
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:page-count="totalPage"
|
||||
v-model:current-page="currentPage"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
@ -152,6 +154,7 @@ const {
|
||||
rowStyle,
|
||||
formatShortDate,
|
||||
totalPage,
|
||||
currentPage,
|
||||
pageChange,
|
||||
isOutbox,
|
||||
trustSender,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { reactive } from "vue";
|
||||
import useGroupStore from '../../../stores/group';
|
||||
|
||||
import lang from "../../../i18n/i18n";
|
||||
|
||||
@ -10,6 +11,8 @@ import { Folder, Delete, Plus } from "@element-plus/icons-vue";
|
||||
|
||||
export function usePage() {
|
||||
const data = reactive([]);
|
||||
const groupStore = useGroupStore();
|
||||
const saving = new WeakSet();
|
||||
|
||||
http.get("/api/v1/group").then((res) => {
|
||||
data.push(...res.data);
|
||||
@ -21,6 +24,7 @@ export function usePage() {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage({ message: res.errorMsg, type: "error" });
|
||||
} else {
|
||||
groupStore.invalidate();
|
||||
const pc = node.parent.childNodes;
|
||||
for (let i = 0; i < pc.length; i++) {
|
||||
if (pc[i].id === node.id) {
|
||||
@ -63,18 +67,22 @@ export function usePage() {
|
||||
};
|
||||
|
||||
const onInputBlur = function (item) {
|
||||
if (item.label !== "") {
|
||||
if (item.id !== -1 || saving.has(item)) return;
|
||||
if (item.label.trim() !== "") {
|
||||
saving.add(item);
|
||||
http.post("/api/v1/group/add", { name: item.label, parent_id: item.parent_id })
|
||||
.then((res) => {
|
||||
if (res.errorNo !== 0) {
|
||||
ElMessage({ message: res.errorMsg, type: "error" });
|
||||
} else {
|
||||
http.get("/api/v1/group").then((res) => {
|
||||
groupStore.invalidate();
|
||||
return http.get("/api/v1/group").then((res) => {
|
||||
data.splice(0, data.length);
|
||||
data.push(...res.data);
|
||||
});
|
||||
}
|
||||
});
|
||||
}).catch(error => ElMessage.error(error.message))
|
||||
.finally(() => saving.delete(item));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -47,7 +47,11 @@ export function usePage() {
|
||||
|
||||
const data = ref([]);
|
||||
|
||||
const searchQuery = ref("");
|
||||
const searchQuery = ref(groupStore.keyword);
|
||||
const submitSearch = () => {
|
||||
groupStore.keyword = searchQuery.value.trim();
|
||||
router.push({ name: "list" });
|
||||
};
|
||||
|
||||
const activeGroup = ref(groupStore.tag);
|
||||
|
||||
@ -55,7 +59,7 @@ export function usePage() {
|
||||
activeGroup.value = newVal;
|
||||
});
|
||||
|
||||
http.get("/api/v1/group").then((res) => {
|
||||
const loadGroups = () => http.get("/api/v1/group").then((res) => {
|
||||
if (res.data) {
|
||||
// Attempting to flatten the tree for a simpler premium menu or keep it, el-tree is less beautiful.
|
||||
// For now we assume res.data is an array of items. If it's a tree, we flatten it.
|
||||
@ -68,8 +72,11 @@ export function usePage() {
|
||||
}
|
||||
traverse(res.data);
|
||||
data.value = list;
|
||||
|
||||
}
|
||||
});
|
||||
}).catch(error => ElMessage.error(error.message));
|
||||
watch(() => groupStore.revision, loadGroups);
|
||||
loadGroups();
|
||||
|
||||
const handleMenuSelect = function (index) {
|
||||
const selected = data.value.find(d => d.tag === index);
|
||||
@ -111,6 +118,7 @@ export function usePage() {
|
||||
router,
|
||||
data,
|
||||
searchQuery,
|
||||
submitSearch,
|
||||
activeGroup,
|
||||
handleMenuSelect,
|
||||
openSettings
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
<div class="search-box">
|
||||
<el-input
|
||||
v-model="searchQuery"
|
||||
@keyup.enter="submitSearch"
|
||||
@clear="submitSearch"
|
||||
:placeholder="lang.search"
|
||||
prefix-icon="Search"
|
||||
clearable
|
||||
@ -63,6 +65,7 @@ import { usePage, BrandLogo, Setting, SwitchButton } from './HomeAside.js'
|
||||
|
||||
const {
|
||||
searchQuery,
|
||||
submitSearch,
|
||||
lang,
|
||||
activeGroup,
|
||||
handleMenuSelect,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user