通知中心游标分页

This commit is contained in:
biss committed 2026-08-23 09:21:04 +08:00
1 parent 172577f668
commit f5db2f6e77
4 files changed
+160 -64

No files matched your search

+63 -24
View File
@@ -28,7 +28,6 @@ const activeTab = ref<'inbox' | 'compose' | 'sent'>('inbox')
const notifications = ref<any[]>([])
const sentMessages = ref<any[]>([])
const unreadCount = ref(0)
const sentTotal = ref(0)
const loading = ref(false)
const markingAllRead = ref(false)
const sending = ref(false)
@@ -39,7 +38,13 @@ const inboxCursors = ref<string[]>([])
const nextInboxCursor = ref<string>()
const inboxHasMore = ref(false)
const sentPage = ref(1)
const sentCursors = ref<string[]>([])
const nextSentCursor = ref<string>()
const sentHasMore = ref(false)
const recipientPage = ref(1)
const recipientCursors = ref<string[]>([])
const nextRecipientCursor = ref<string>()
const recipientHasMore = ref(false)
const pageSize = 20
const recipientPageSize = 30
const unreadOnly = ref(false)
@@ -169,14 +174,19 @@ async function previousInboxPage() {
}
async function loadSent(reset = false) {
if (reset) sentPage.value = 1
if (reset) {
sentPage.value = 1
sentCursors.value = []
nextSentCursor.value = undefined
}
loading.value = true
try {
const { data } = await http.get('/notifications/sent', {
params: { page: sentPage.value, pageSize },
params: { cursor: sentCursors.value.at(-1), pageSize },
})
sentMessages.value = data.items
sentTotal.value = data.total
sentHasMore.value = data.hasMore
nextSentCursor.value = data.nextCursor
} catch (error) {
ElMessage.error(apiErrorMessage(error))
} finally {
@@ -184,6 +194,20 @@ async function loadSent(reset = false) {
}
}
async function nextSentPage() {
if (!nextSentCursor.value || loading.value) return
sentCursors.value.push(nextSentCursor.value)
sentPage.value++
await loadSent()
}
async function previousSentPage() {
if (!sentCursors.value.length || loading.value) return
sentCursors.value.pop()
sentPage.value--
await loadSent()
}
async function loadComposer() {
if (!canSend.value || composer.value) return
composerLoading.value = true
@@ -206,14 +230,18 @@ function recipientParams() {
administrativeClassId: recipientFilters.administrativeClassId || undefined,
teachingTaskId: recipientFilters.teachingTaskId || undefined,
keyword: recipientFilters.keyword.trim() || undefined,
page: recipientPage.value,
cursor: recipientCursors.value.at(-1),
pageSize: recipientPageSize,
}
}
async function loadRecipients(reset = false) {
if (!isAdministratorComposer.value) return
if (reset) recipientPage.value = 1
if (reset) {
recipientPage.value = 1
recipientCursors.value = []
nextRecipientCursor.value = undefined
}
recipientLoading.value = true
try {
const { data } = await http.get('/notifications/recipients', {
@@ -221,6 +249,8 @@ async function loadRecipients(reset = false) {
})
recipientItems.value = data.items
recipientTotal.value = data.total
recipientHasMore.value = data.hasMore
nextRecipientCursor.value = data.nextCursor
} catch (error) {
ElMessage.error(apiErrorMessage(error))
} finally {
@@ -228,6 +258,20 @@ async function loadRecipients(reset = false) {
}
}
async function nextRecipientPage() {
if (!nextRecipientCursor.value || recipientLoading.value) return
recipientCursors.value.push(nextRecipientCursor.value)
recipientPage.value++
await loadRecipients()
}
async function previousRecipientPage() {
if (!recipientCursors.value.length || recipientLoading.value) return
recipientCursors.value.pop()
recipientPage.value--
await loadRecipients()
}
async function changeRecipientMode(value: 'Scope' | 'Filtered' | 'Selected') {
recipientMode.value = value
if (value !== 'Scope') await loadRecipients(true)
@@ -685,16 +729,11 @@ onMounted(() => load())
description="没有符合条件的可用账号"
/>
</div>
<el-pagination
v-if="recipientTotal > recipientPageSize"
v-model:current-page="recipientPage"
small
background
:page-size="recipientPageSize"
:total="recipientTotal"
layout="prev, pager, next"
@current-change="loadRecipients()"
/>
<div v-if="recipientCursors.length || recipientHasMore" class="cursor-pager">
<el-button size="small" :disabled="!recipientCursors.length || recipientLoading" @click="previousRecipientPage">上一批</el-button>
<span>第 {{ recipientPage }} 批</span>
<el-button size="small" type="primary" :disabled="!recipientHasMore || recipientLoading" @click="nextRecipientPage">下一批</el-button>
</div>
</div>
<div
@@ -828,14 +867,14 @@ onMounted(() => load())
<el-empty v-if="!loading && !sentMessages.length" description="还没有发送记录" />
</section>
<div v-if="sentTotal > pageSize" class="message-pager">
<el-pagination
v-model:current-page="sentPage"
:page-size="pageSize"
:total="sentTotal"
layout="prev, pager, next, total"
@current-change="loadSent()"
/>
<div v-if="sentCursors.length || sentHasMore" class="message-pager">
<el-button :disabled="!sentCursors.length || loading" @click="previousSentPage">
上一批
</el-button>
<span>第 {{ sentPage }} 批</span>
<el-button type="primary" :disabled="!sentHasMore || loading" @click="nextSentPage">
下一批
</el-button>
</div>
</template>
+30 -17
View File
@@ -19,7 +19,9 @@ const loading = ref(false)
const detecting = ref(false)
const filterType = ref('')
const recordsPage = ref(1)
const recordsTotal = ref(0)
const recordsCursors = ref<string[]>([])
const nextRecordsCursor = ref<string>()
const recordsHasMore = ref(false)
const recordsPageSize = 20
const riskCases = ref<any[]>([])
const riskDialogVisible = ref(false)
@@ -49,7 +51,11 @@ const ruleRows = reactive([
])
async function load(resetRecordsPage = false) {
if (resetRecordsPage) recordsPage.value = 1
if (resetRecordsPage) {
recordsPage.value = 1
recordsCursors.value = []
nextRecordsCursor.value = undefined
}
loading.value = true
try {
if (isWarningManager.value && termId.value) {
@@ -77,16 +83,13 @@ async function load(resetRecordsPage = false) {
params: {
academicTermId: termId.value || undefined,
type: filterType.value || undefined,
page: recordsPage.value,
cursor: recordsCursors.value.at(-1),
pageSize: recordsPageSize,
},
})
records.value = response.data.items
recordsTotal.value = response.data.total
if (records.value.length === 0 && recordsPage.value > 1) {
recordsPage.value--
await load()
}
recordsHasMore.value = response.data.hasMore
nextRecordsCursor.value = response.data.nextCursor
riskCases.value = (await http.get('/warnings/risk-cases', { params: { mineOnly: isCounselor.value } })).data
}
if (isStudent.value) {
@@ -96,6 +99,20 @@ async function load(resetRecordsPage = false) {
} catch (e) { ElMessage.error(apiErrorMessage(e)) } finally { loading.value = false }
}
async function nextRecordsPage() {
if (!nextRecordsCursor.value || loading.value) return
recordsCursors.value.push(nextRecordsCursor.value)
recordsPage.value++
await load()
}
async function previousRecordsPage() {
if (!recordsCursors.value.length || loading.value) return
recordsCursors.value.pop()
recordsPage.value--
await load()
}
async function saveRules() {
try {
const payload = ruleRows.map(r => ({ type: r.type, name: r.name, threshold: r.threshold, isEnabled: r.isEnabled, notifyStudent: r.notifyStudent, notifyCounselor: r.notifyCounselor, description: r.description, autoCheckEnabled: r.autoCheckEnabled, checkDayOfWeek: r.checkDayOfWeek, checkHour: r.checkHour, checkMinute: r.checkMinute }))
@@ -220,15 +237,11 @@ onMounted(async () => {
<el-table-column label="阈值/详情" min-width="200"><template #default="{row}"><span>{{ row.triggerValue }}</span><p style="margin:0;font-size:11px;color:var(--muted)">{{ row.detail }}</p></template></el-table-column>
<el-table-column label="状态" width="100"><template #default="{row}"><el-tag size="small" :type="row.status===1?'danger':row.status===2?'success':'info'">{{ statusLabels[row.status] }}</el-tag></template></el-table-column>
</el-table>
<el-pagination
v-if="recordsTotal > recordsPageSize"
v-model:current-page="recordsPage"
:page-size="recordsPageSize"
:total="recordsTotal"
layout="total, prev, pager, next"
class="table-pagination"
@current-change="() => load()"
/>
<div v-if="recordsCursors.length || recordsHasMore" class="table-pagination cursor-pager">
<el-button :disabled="!recordsCursors.length || loading" @click="previousRecordsPage">上一批</el-button>
<span>第 {{ recordsPage }} 批</span>
<el-button type="primary" :disabled="!recordsHasMore || loading" @click="nextRecordsPage">下一批</el-button>
</div>
<el-empty v-if="!records.length" description="暂无预警记录,请先执行检测。" />
</section>