Add pagination to admin management tabs (cases/categories/sources/orgs)
This commit is contained in:
@@ -50,7 +50,7 @@
|
||||
<el-button size="default" :type="filterStatus === 'ready' ? 'primary' : ''" @click="filterStatus = 'ready'; fetchTopics()">待发布 ({{ statusStats.ready }})</el-button>
|
||||
<el-button size="default" :type="filterStatus === 'published' ? 'primary' : ''" @click="filterStatus = 'published'; fetchTopics()">已发布 ({{ statusStats.published }})</el-button>
|
||||
</div>
|
||||
<el-table :data="filteredTopics" stripe v-loading="loadingTable" @selection-change="selectedTopicIds = $event.map(item => item.id)">
|
||||
<el-table :data="paginatedTopics" stripe v-loading="loadingTable" @selection-change="selectedTopicIds = $event.map(item => item.id)">
|
||||
<el-table-column type="selection" width="55"></el-table-column>
|
||||
<el-table-column prop="id" label="ID" width="70" fixed></el-table-column>
|
||||
<el-table-column prop="title" label="标题" min-width="200"></el-table-column>
|
||||
@@ -76,7 +76,10 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="!loadingTable && filteredTopics.length === 0" class="empty-state" style="margin-top:20px;"><el-icon style="font-size:48px;color:#c0c4cc;"><IconTopic /></el-icon><div class="empty-text">暂无选题数据</div></div>
|
||||
<div v-if="!loadingTable && paginatedTopics.length === 0" class="empty-state" style="margin-top:20px;"><el-icon style="font-size:48px;color:#c0c4cc;"><IconTopic /></el-icon><div class="empty-text">暂无选题数据</div></div>
|
||||
<div v-if="filteredTopics.length > pageSize" style="display:flex;justify-content:center;margin:12px 0;">
|
||||
<el-pagination background layout="prev, pager, next" :total="filteredTopics.length" :page-size="pageSize" :current-page="currentPage" @current-change="currentPage = $event"></el-pagination>
|
||||
</div>
|
||||
<div class="topic-card-list" v-if="filteredTopics && filteredTopics.length > 0">
|
||||
<div v-for="topic in filteredTopics" :key="topic.id" class="topic-card" :class="{ 'is-checked': selectedTopicIds.includes(topic.id) }">
|
||||
<div class="topic-card-header">
|
||||
@@ -138,19 +141,26 @@
|
||||
<div style="display:flex; align-items:center; gap:12px; font-size:13px; color:#909399;">
|
||||
<span>创建:{{ formatDate(previewTopic.created_at) }}</span>
|
||||
<span>状态:{{ getStatusLabel(previewTopic.status) }}</span>
|
||||
<el-tag v-if="editing" type="warning" size="small">编辑模式</el-tag>
|
||||
<el-button size="small" @click="togglePreviewFullscreen">{{ previewFullscreen ? '退出全屏' : '全屏' }}</el-button>
|
||||
<el-button v-if="previewFullscreen" size="small" type="danger" @click="previewVisible = false">关闭</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin: 12px 0 16px; display: flex; justify-content: flex-end; gap: 8px;">
|
||||
<div style="margin: 12px 0 16px; display: flex; justify-content: space-between; align-items: center; gap: 8px;">
|
||||
<el-button-group>
|
||||
<el-button :type="previewPlatform === 'zhihu' ? 'primary' : 'default'" @click="previewPlatform = 'zhihu'">知乎</el-button>
|
||||
<el-button :type="previewPlatform === 'wechat' ? 'primary' : 'default'" @click="previewPlatform = 'wechat'">微信公众号</el-button>
|
||||
<el-button :type="previewPlatform === 'xiaohongshu' ? 'primary' : 'default'" @click="previewPlatform = 'xiaohongshu'">小红书</el-button>
|
||||
<el-button :type="previewPlatform === 'zhihu' ? 'primary' : 'default'" @click="switchPlatform('zhihu')">知乎</el-button>
|
||||
<el-button :type="previewPlatform === 'wechat' ? 'primary' : 'default'" @click="switchPlatform('wechat')">微信公众号</el-button>
|
||||
<el-button :type="previewPlatform === 'xiaohongshu' ? 'primary' : 'default'" @click="switchPlatform('xiaohongshu')">小红书</el-button>
|
||||
</el-button-group>
|
||||
<div>
|
||||
<el-button v-if="!editing" size="small" type="primary" @click="startEdit" plain><el-icon style="vertical-align:-2px;"><IconEdit /></el-icon> 编辑</el-button>
|
||||
<el-button v-if="editing" size="small" @click="cancelEdit">取消</el-button>
|
||||
<el-button v-if="editing" size="small" type="primary" @click="saveContent" :loading="savingContent">保存</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="max-width: 1000px; margin: 0 auto; width: 100%; height: 100%; display: flex; flex-direction: column;">
|
||||
<iframe :srcdoc="currentPreviewHtml" class="preview-iframe" style="flex:1; min-height:500px; border:1px solid #ebeef5; border-radius:8px; background:#fff; overflow:auto; padding:0; width:100%;" sandbox></iframe>
|
||||
<div style="max-width: 1000px; margin: 0 auto; width: 100%; display: flex; flex-direction: column;">
|
||||
<div v-if="!editing" class="preview-body" style="flex:1; min-height:500px; border:1px solid #ebeef5; border-radius:8px; background:#fff; padding:20px; overflow:auto; width:100%; line-height:1.8;" v-html="currentPreviewBody"></div>
|
||||
<div v-else ref="editor" contenteditable="true" style="flex:1; min-height:500px; border:1px solid #409eff; border-radius:8px; background:#fff; padding:20px; overflow:auto; width:100%; line-height:1.8; outline:none; box-shadow:0 0 0 2px rgba(64,158,255,0.2);" @input="editContent = $event.target.innerHTML"></div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
@@ -182,10 +192,11 @@ const TopicsApp = {
|
||||
stats: { total: 0, pending: 0, review: 0, ready: 0, published: 0, today: 0 },
|
||||
topics: [], allTopics: [], todayTopics: [], todayCount: 0,
|
||||
previewVisible: false, previewTopic: null, previewFullscreen: false,
|
||||
previewPlatform: 'zhihu', platformContents: {},
|
||||
previewPlatform: 'zhihu', platformContents: {}, editing: false, editContent: '',
|
||||
publishDialogVisible: false, publishTopic: null,
|
||||
publishPlatforms: { zhihu: true, wechat: true, xiaohongshu: true },
|
||||
publishing: false
|
||||
publishing: false,
|
||||
currentPage: 1, pageSize: 20
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -196,6 +207,10 @@ const TopicsApp = {
|
||||
const allowed = map[this.filterStatus] || [this.filterStatus];
|
||||
return this.topics.filter(t => allowed.includes(t.status));
|
||||
},
|
||||
paginatedTopics() {
|
||||
const start = (this.currentPage - 1) * this.pageSize;
|
||||
return this.filteredTopics.slice(start, start + this.pageSize);
|
||||
},
|
||||
statusStats() {
|
||||
const s = { total: this.topics.length, pending: 0, review: 0, ready: 0, published: 0 };
|
||||
const aliases = { 'pending': ['pending','待处理'], 'review': ['review','待审查'], 'ready': ['ready','待发布'], 'published': ['published','已发布'] };
|
||||
@@ -217,6 +232,18 @@ const TopicsApp = {
|
||||
return `<!DOCTYPE html><html><head>${headHtml}</head><body style="margin:0;padding:0;">${bodyHtml}${ending}</body></html>`;
|
||||
} catch (e) { console.error('生成预览 HTML 失败:', e); return html; }
|
||||
},
|
||||
currentPreviewBody() {
|
||||
const html = this.platformContents[this.previewPlatform];
|
||||
if (!html) return '';
|
||||
try {
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(html, 'text/html');
|
||||
const body = doc.body;
|
||||
if (!body) return html;
|
||||
body.querySelectorAll('script, nav, .header, footer, .interaction').forEach(el => el.remove());
|
||||
return body.innerHTML;
|
||||
} catch (e) { console.error('解析 HTML 失败:', e); return html; }
|
||||
},
|
||||
selectAllLabel() {
|
||||
const visible = this.filteredTopics.map(t => t.id);
|
||||
if (visible.length === 0) return '全选';
|
||||
@@ -234,6 +261,7 @@ const TopicsApp = {
|
||||
return res.json();
|
||||
},
|
||||
async fetchTopics() {
|
||||
this.currentPage = 1;
|
||||
this.loadingTable = true;
|
||||
try {
|
||||
const token = this.getToken();
|
||||
|
||||
Reference in New Issue
Block a user