Add pagination to admin management tabs (cases/categories/sources/orgs)
This commit is contained in:
@@ -24,6 +24,13 @@
|
||||
.day-holiday { font-size: 8px; padding: 0 2px; }
|
||||
.day-entry { font-size: 10px; padding: 2px 3px; white-space: normal; line-height: 1.2; }
|
||||
.stats-bar { gap: 12px; font-size: 12px; }
|
||||
.calendar-guide { flex-direction: column; padding: 12px; }
|
||||
.calendar-guide-icon { font-size: 22px; }
|
||||
.calendar-guide-content h3 { font-size: 15px; }
|
||||
.calendar-guide-content li, .calendar-guide-content p { font-size: 12px; }
|
||||
.upcoming-section h3 { font-size: 14px; }
|
||||
.upcoming-item { width: 140px; padding: 10px; }
|
||||
.calendar-hint { font-size: 11px; }
|
||||
}
|
||||
|
||||
.calendar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; flex-wrap: wrap; gap: 12px; }
|
||||
@@ -51,6 +58,24 @@
|
||||
.entry-topic-status.published { background:#f0f9eb; color:#67c23a; }
|
||||
.entry-topic-status.pending { background:#f4f4f5; color:#909399; }
|
||||
|
||||
.calendar-guide { background: linear-gradient(135deg, #eef2ff, #e0e7ff); border: 1px solid #c7d2fe; border-radius: 12px; padding: 16px 20px; margin-bottom: 20px; display: flex; align-items: flex-start; gap: 12px; position: relative; }
|
||||
.calendar-guide-close { position: absolute; top: 8px; right: 8px; background: none; border: none; color: #6366f1; cursor: pointer; font-size: 18px; padding: 4px; border-radius: 4px; }
|
||||
.calendar-guide-close:hover { background: rgba(99,102,241,0.1); }
|
||||
.calendar-guide-icon { font-size: 28px; flex-shrink: 0; margin-top: 2px; }
|
||||
.calendar-guide-content { flex: 1; }
|
||||
.calendar-guide-content h3 { font-size: 16px; font-weight: 600; color: #4338ca; margin: 0 0 6px 0; }
|
||||
.calendar-guide-content p { font-size: 13px; color: #4f46e5; margin: 0; line-height: 1.6; }
|
||||
.calendar-guide-content ol { margin: 6px 0 0 0; padding-left: 20px; }
|
||||
.calendar-guide-content li { font-size: 13px; color: #4f46e5; line-height: 1.8; }
|
||||
.upcoming-section { margin-bottom: 20px; }
|
||||
.upcoming-section h3 { font-size: 16px; font-weight: 600; color: #303133; margin: 0 0 10px 0; display: flex; align-items: center; gap: 8px; }
|
||||
.upcoming-list { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 4px; }
|
||||
.upcoming-item { flex-shrink: 0; width: 180px; background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 10px; padding: 12px; cursor: pointer; transition: all 0.2s; }
|
||||
.upcoming-item:hover { border-color: #6366f1; box-shadow: 0 2px 8px rgba(99,102,241,0.15); }
|
||||
.upcoming-date { font-size: 12px; color: #6366f1; font-weight: 600; }
|
||||
.upcoming-title { font-size: 14px; color: #1f2937; font-weight: 500; margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.upcoming-meta { font-size: 12px; color: #9ca3af; margin-top: 6px; display: flex; gap: 8px; }
|
||||
.calendar-hint { text-align: center; font-size: 12px; color: #c0c4cc; margin-top: 8px; padding: 4px 0; }
|
||||
.stats-bar { display: flex; gap: 24px; margin-bottom: 24px; flex-wrap: wrap; }
|
||||
.stat-item { display: flex; align-items: center; gap: 8px; }
|
||||
.stat-dot { width: 10px; height: 10px; border-radius: 50%; }
|
||||
@@ -78,8 +103,42 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 使用指南 -->
|
||||
<div v-if="showGuide" class="calendar-guide">
|
||||
<div class="calendar-guide-icon">📅</div>
|
||||
<div class="calendar-guide-content">
|
||||
<h3>内容日历使用说明</h3>
|
||||
<p>规划和管理各平台的内容发布排期,一目了然看到每月发布计划。</p>
|
||||
<ol>
|
||||
<li><strong>点击日期</strong> — 查看该日所有日程,或点击"添加日程"新建</li>
|
||||
<li><strong>点击日程卡片</strong> — 编辑或删除已有日程</li>
|
||||
<li><strong>关联选题</strong> — 创建日程时可关联已有选题,跟踪从创作到发布的全流程</li>
|
||||
</ol>
|
||||
</div>
|
||||
<button class="calendar-guide-close" @click="showGuide = false; localStorage.setItem('calendarGuideDismissed', 'true')" title="不再显示">✕</button>
|
||||
</div>
|
||||
|
||||
<!-- 即将到来 -->
|
||||
<div v-if="upcomingEntries.length > 0" class="upcoming-section">
|
||||
<h3><el-icon><IconClock /></el-icon> 即将到来</h3>
|
||||
<div class="upcoming-list">
|
||||
<div v-for="entry in upcomingEntries" :key="entry.id" class="upcoming-item" @click="openEntryDialog(entry)">
|
||||
<div class="upcoming-date">{{ formatDate(entry.planned_date) }}</div>
|
||||
<div class="upcoming-title">{{ entry.title || '未命名' }}</div>
|
||||
<div class="upcoming-meta">
|
||||
<span>{{ platformName(entry.platform) }}</span>
|
||||
<el-tag :type="statusType(entry.status)" size="small">{{ statusLabel(entry.status) }}</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-bar">
|
||||
<div v-if="loadingCalendar" style="color:#909399;font-size:14px;">加载中...</div>
|
||||
<div v-else-if="errorMsg" class="empty-state" style="color:#F56C6C;">
|
||||
<el-icon style="font-size:36px;color:#F56C6C;"><IconClose /></el-icon>
|
||||
<div class="empty-text">{{ errorMsg }}</div>
|
||||
</div>
|
||||
<div v-else-if="!calendarDays.length" class="empty-state">
|
||||
<el-icon style="font-size:48px;color:#c0c4cc;"><IconCalendar /></el-icon>
|
||||
<div class="empty-text">暂无日历数据</div>
|
||||
@@ -113,15 +172,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="calendar-hint">💡 点击日期查看或添加日程 · 点击日程卡片编辑详情</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="dayDialogVisible" :title="selectedDay ? `${selectedDay.year}-${selectedDay.month}-${selectedDay.day} 日程` : ''" width="500px">
|
||||
<el-dialog v-model="dayDialogVisible" :title="selectedDay ? `${selectedDay.year}年${selectedDay.month}月${selectedDay.day}日 日程` : ''" width="500px">
|
||||
<div v-if="selectedDay">
|
||||
<el-button type="primary" @click="openCreateDialog" style="margin-bottom: 16px;">+ 添加日程</el-button>
|
||||
<el-table :data="selectedDayEntries" stripe>
|
||||
<div v-if="selectedDayEntries.length === 0" class="empty-state" style="padding:20px 0;">
|
||||
<el-icon style="font-size:36px;color:#c0c4cc;"><IconCalendar /></el-icon>
|
||||
<div class="empty-text">该日暂无日程</div>
|
||||
<p style="font-size:13px;color:#909399;margin:4px 0 0 0;">点击上方"添加日程"创建发布计划</p>
|
||||
</div>
|
||||
<el-table v-else :data="selectedDayEntries" stripe>
|
||||
<el-table-column prop="title" label="标题" min-width="120"></el-table-column>
|
||||
<el-table-column prop="platform" label="平台" width="100">
|
||||
<template #default="scope">{{ platformName(scope.row.platform) }}</template>
|
||||
@@ -321,11 +386,28 @@ function getDayMeta(year, month, day) {
|
||||
|
||||
const loadingCalendar = ref(false);
|
||||
const calendarError = ref('');
|
||||
const showGuide = ref(localStorage.getItem('calendarGuideDismissed') !== 'true');
|
||||
const errorMsg = ref('');
|
||||
|
||||
const upcomingEntries = computed(() => {
|
||||
const today = new Date(); today.setHours(0, 0, 0, 0);
|
||||
const end = new Date(today); end.setDate(end.getDate() + 7);
|
||||
return entries.value
|
||||
.filter(e => { const d = new Date(e.planned_date); return d >= today && d < end; })
|
||||
.sort((a, b) => new Date(a.planned_date) - new Date(b.planned_date))
|
||||
.slice(0, 10);
|
||||
});
|
||||
const formatDate = (dateStr) => {
|
||||
if (!dateStr) return '';
|
||||
const d = new Date(dateStr);
|
||||
return `${d.getMonth() + 1}月${d.getDate()}日`;
|
||||
};
|
||||
|
||||
const fetchEntries = async () => {
|
||||
loadingCalendar.value = true;
|
||||
calendarError.value = '';
|
||||
try { entries.value = await api(`/api/calendar?year=${currentYear.value}&month=${currentMonth.value}`); } catch (e) { console.error(e); calendarError.value = e.message; ElMessage.error('加载日历失败: ' + e.message); }
|
||||
errorMsg.value = '';
|
||||
try { entries.value = await api(`/api/calendar?year=${currentYear.value}&month=${currentMonth.value}`); } catch (e) { console.error(e); calendarError.value = e.message; errorMsg.value = '加载失败: ' + e.message; }
|
||||
finally { loadingCalendar.value = false; }
|
||||
};
|
||||
const fetchStats = async () => {
|
||||
@@ -398,7 +480,7 @@ function getDayMeta(year, month, day) {
|
||||
checkAuth();
|
||||
});
|
||||
|
||||
return { currentUser, isAdmin, currentYear, currentMonth, weekDays, calendarDays, entries, topics, stats, dayDialogVisible, entryDialogVisible, selectedDay, selectedDayEntries, isEdit, saving, entryForm, prevMonth, nextMonth, goToday, openDayDialog, openCreateDialog, openEntryDialog, saveEntry, deleteEntry, platformName, statusLabel, statusType, topicStatusLabel, handleLogout, redirectToPage };
|
||||
return { currentUser, isAdmin, currentYear, currentMonth, weekDays, calendarDays, entries, topics, stats, dayDialogVisible, entryDialogVisible, selectedDay, selectedDayEntries, isEdit, saving, entryForm, prevMonth, nextMonth, goToday, openDayDialog, openCreateDialog, openEntryDialog, saveEntry, deleteEntry, platformName, statusLabel, statusType, topicStatusLabel, handleLogout, redirectToPage, showGuide, errorMsg, upcomingEntries, formatDate };
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user