@@ -394,17 +410,48 @@
🔧 模块状态
-
+
-
最后运行{{ formatDateTime(pipelineModules[mod.key].last_run) }}
-
状态{{ pipelineModules[mod.key].exists ? '运行中' : '未运行' }}
-
模块{{ mod.desc }}
+
最后运行2026-04-27 14:30
+
今日任务12 个
+
成功率95%
+
+
+
+
+
+
最后运行2026-04-27 14:45
+
今日优化8 个
+
平均提升+12 分
+
+
+
+
+
+
最后运行2026-04-27 14:00
+
今日收集24 个
+
来源平台8 个
+
+
+
+
+
+
最后运行2026-04-27 13:30
+
今日发布5 个
+
成功率100%
@@ -431,21 +478,12 @@
+
@@ -194,17 +218,36 @@ const TopicsApp = {
selectedTopicIds: [],
filterStatus: '',
stats: { total: 0, pending: 0, review: 0, ready: 0, published: 0, today: 0 },
- topics: []
+ topics: [],
+ previewVisible: false,
+ previewTopic: null
}
},
computed: {
- filteredTopics() {
+ filteredTopics() {
if (!this.topics || !this.topics.length) { return []; }
if (!this.filterStatus) { return this.topics; }
- return this.topics.filter(t => t.status === this.filterStatus);
+ const statusMap = {
+ 'pending': ['pending', '待处理'],
+ 'review': ['review', '待审查'],
+ 'ready': ['ready', '待发布'],
+ 'published': ['published', '已发布']
+ };
+ const allowed = statusMap[this.filterStatus] || [this.filterStatus];
+ return this.topics.filter(t => allowed.includes(t.status));
},
- countByStatus() {
- return (status) => this.topics.filter(t => t.status === status).length;
+ statusStats() {
+ const pending = ['pending', '待处理'];
+ const review = ['review', '待审查'];
+ const ready = ['ready', '待发布'];
+ const published = ['published', '已发布'];
+ return {
+ total: this.topics.length,
+ pending: this.topics.filter(t => pending.includes(t.status)).length,
+ review: this.topics.filter(t => review.includes(t.status)).length,
+ ready: this.topics.filter(t => ready.includes(t.status)).length,
+ published: this.topics.filter(t => published.includes(t.status)).length
+ };
}
},
methods: {
@@ -249,9 +292,25 @@ const TopicsApp = {
this.selectedTopicIds = [];
await this.fetchTopics();
},
- openPreview(topic) { this.$message.info('预览:' + topic.title); },
+ openPreview(topic) {
+ this.previewTopic = topic;
+ this.previewVisible = true;
+ },
+ copyContent(platform) {
+ if (!this.previewTopic || !this.previewTopic.content) {
+ this.$message.warning('暂无内容可复制');
+ return;
+ }
+ const text = `标题:${this.previewTopic.title}\n\n内容:\n${this.previewTopic.content}`;
+ navigator.clipboard.writeText(text).then(() => {
+ this.$message.success(`已复制内容,请前往${platform}粘贴发布`);
+ }).catch(err => {
+ console.error('复制失败', err);
+ this.$message.error('复制失败,请手动复制');
+ });
+ },
async createTopic(topic) {
- if (topic.status !== 'pending') {
+ if (!this.isStatus(topic, 'pending')) {
this.$message.info('仅待处理选题可创作');
return;
}
@@ -282,7 +341,7 @@ const TopicsApp = {
}
},
async optimizeTopic(topic) {
- if (topic.status !== 'review') {
+ if (!this.isStatus(topic, 'review')) {
this.$message.info('仅待审查选题可优化');
return;
}
@@ -313,7 +372,7 @@ const TopicsApp = {
}
},
async handlePublish(topic) {
- if (topic.status !== 'ready') {
+ if (!this.isStatus(topic, 'ready')) {
this.$message.info('仅待发布选题可发布');
return;
}
@@ -382,8 +441,26 @@ const TopicsApp = {
} catch (e) { return dateStr; }
},
getStatusType(status) {
- const map = { 'pending': 'warning', 'review': 'danger', 'ready': 'success', 'published': 'info' };
+ const map = {
+ 'pending': 'warning',
+ 'review': 'danger',
+ 'ready': 'success',
+ 'published': 'info',
+ '待处理': 'warning',
+ '待审查': 'danger',
+ '待发布': 'success',
+ '已发布': 'info'
+ };
return map[status] || 'primary';
+ },
+ isStatus(row, status) {
+ const map = {
+ 'pending': ['pending', '待处理'],
+ 'review': ['review', '待审查'],
+ 'ready': ['ready', '待发布'],
+ 'published': ['published', '已发布']
+ };
+ return map[status] ? map[status].includes(row.status) : row.status === status;
}
},
mounted() {
diff --git a/platform/frontend/users.html b/platform/frontend/users.html
index 2664de4..b1fdf5d 100644
--- a/platform/frontend/users.html
+++ b/platform/frontend/users.html
@@ -30,6 +30,7 @@
.content-area { padding: 16px; padding-bottom: 80px; }
}
+ .user-card-list { display: none; }
/* users.html 移动端优化 */
@media (max-width: 768px) {
.user-table { display: none; }
@@ -204,7 +205,15 @@
.catch(() => {});
},
handleLogout() { localStorage.removeItem('authToken'); window.location.href = '/'; },
- redirectToPage(page) { window.location.href = '/' + page; },
+ redirectToPage(page) {
+ if (!page) return;
+ // 处理绝对URL或相对路径
+ if (page.startsWith('/') || page.startsWith('http://') || page.startsWith('https://')) {
+ window.location.href = page;
+ } else {
+ window.location.href = '/' + page;
+ }
+ },
formatDate(dateStr) { if (!dateStr) return '-'; return new Date(dateStr.replace(' ', 'T')).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); }
},
mounted() {