Add pagination to admin management tabs (cases/categories/sources/orgs)

This commit is contained in:
Yuzhiran Dev
2026-05-18 19:18:09 +08:00
parent 7169ddb678
commit a09e7e6671
14 changed files with 455 additions and 340 deletions
+53 -1
View File
@@ -24,6 +24,11 @@
.module-content div { display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px dashed var(--color-border); }
.module-content div:last-child { border-bottom: none; }
.stat-title { font-size: var(--font-size-small); color: var(--color-text-secondary); margin-bottom: var(--spacing-md); text-transform: uppercase; letter-spacing: 0.5px; font-weight: 500; }
.plan-list { display: flex; flex-direction: column; gap: 8px; }
.plan-item { display: flex; align-items: center; gap: 12px; padding: 10px 14px; background: var(--color-bg-raised); border: 1px solid var(--color-border); border-radius: var(--radius-md); transition: all 0.2s; }
.plan-item:hover { border-color: var(--color-primary); }
.plan-date { font-size: var(--font-size-caption); color: var(--color-text-secondary); font-weight: 600; min-width: 36px; }
.plan-title { flex: 1; font-size: var(--font-size-body); color: var(--color-text-primary); }
@media (max-width: 768px) { .module-grid { grid-template-columns: 1fr; } }
</style>
@@ -102,6 +107,26 @@
</div>
</div>
</div>
<!-- 近期计划 -->
<h3 style="font-size: var(--font-size-h2); font-weight: 600; margin-bottom: var(--spacing-lg); color: var(--color-text-primary);">
<el-icon style="vertical-align:-2px;"><IconCalendar /></el-icon> 近期计划
</h3>
<div v-if="loadingPlan" style="text-align:center;padding:20px 0;color:#909399;">
<el-icon style="font-size:24px;" class="is-loading"><IconLoading /></el-icon>
<div style="margin-top:8px;">加载中...</div>
</div>
<div v-else-if="upcomingEntries.length === 0" class="empty-state" style="padding:20px;">
<el-icon style="font-size:36px;color:#c0c4cc;"><IconCalendar /></el-icon>
<div class="empty-text">近期暂无计划</div>
</div>
<div v-else class="plan-list">
<div v-for="entry in upcomingEntries" :key="entry.id || entry.date" class="plan-item">
<span class="plan-date">{{ entry.date.slice(5) }}</span>
<span class="plan-title">{{ entry.title }}</span>
<el-tag v-if="entry.status" :type="entry.status === 'published' ? 'success' : 'warning'" size="small">{{ entry.status === 'published' ? '已发布' : '计划' }}</el-tag>
</div>
</div>
</div>
</main>
</div>
@@ -131,7 +156,9 @@
},
modules: [],
schedulerStatus: '',
schedulerRunning: false
schedulerRunning: false,
upcomingEntries: [],
loadingPlan: false
};
},
methods: {
@@ -221,6 +248,30 @@
this.$message.error('获取模块状态失败: ' + e.message);
}
},
async fetchUpcomingPlan() {
this.loadingPlan = true;
try {
const token = localStorage.getItem('authToken');
const now = new Date();
const year = now.getFullYear();
const month = now.getMonth() + 1;
const resp = await fetch(`/api/calendar?year=${year}&month=${month}`, {
headers: { 'Authorization': 'Bearer ' + token }
});
if (resp.ok) {
const all = await resp.json();
const today = new Date();
today.setHours(0, 0, 0, 0);
const end = new Date(today);
end.setDate(end.getDate() + 7);
this.upcomingEntries = (all || [])
.filter(e => { const d = new Date(e.date); return d >= today && d < end; })
.sort((a, b) => a.date.localeCompare(b.date));
}
} catch (e) {
console.error('获取近期计划失败:', e);
} finally { this.loadingPlan = false; }
},
goToTopics(filter) {
const url = filter ? '/topics.html?filter=' + encodeURIComponent(filter) : '/topics.html';
window.location.href = url;
@@ -246,6 +297,7 @@
this.currentPage = 'overview';
this.fetchStats();
this.fetchModules();
this.fetchUpcomingPlan();
})
.catch(() => {
localStorage.removeItem('authToken');