fix(ui): 重构 topics.html Vue 应用结构
- 完全重写 script 部分,确保 methods 和 mounted 正确闭包 - 修复 Vue 表达式未解析的问题 - 添加调试日志 - 确保移动端和桌面端都能正确挂载
This commit is contained in:
+100
-16
@@ -181,42 +181,126 @@
|
||||
</div>
|
||||
<script src="/static/vue/vue.global.js"></script>
|
||||
<script src="/static/element-plus/index.full.min.js"></script>
|
||||
<script>
|
||||
const TopicsApp = {
|
||||
data() { return { isLoggedIn: false, isAdmin: false, currentUser: { username: '' }, topics: [], filterStatus: '', selectedTopicIds: [], loadingTable: false } },
|
||||
|
||||
<script>
|
||||
const TopicsApp = {
|
||||
data() {
|
||||
return {
|
||||
currentPage: 'topics',
|
||||
isLoggedIn: false,
|
||||
isAdmin: false,
|
||||
currentUser: null,
|
||||
loadingTable: false,
|
||||
selectedTopicIds: [],
|
||||
filterStatus: '',
|
||||
stats: { total: 0, pending: 0, review: 0, ready: 0, published: 0, today: 0 },
|
||||
topics: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filteredTopics() {
|
||||
console.log('[DEBUG] filteredTopics called, filterStatus:', this.filterStatus, 'topics count:', this.topics.length);
|
||||
if (!this.topics.length) { console.log('[DEBUG] topics is empty'); return []; }
|
||||
if (!this.filterStatus) { console.log('[DEBUG] no filter, return all'); return this.topics; }
|
||||
const result = this.topics.filter(t => t.status === this.filterStatus);
|
||||
console.log('[DEBUG] filtered result count:', result.length);
|
||||
return result;
|
||||
if (!this.topics || !this.topics.length) { return []; }
|
||||
if (!this.filterStatus) { return this.topics; }
|
||||
return this.topics.filter(t => t.status === this.filterStatus);
|
||||
},
|
||||
countByStatus() { return (status) => this.topics.filter(t => t.status === status).length; }
|
||||
countByStatus() {
|
||||
return (status) => this.topics.filter(t => t.status === status).length;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async fetchTopics() {
|
||||
this.loadingTable = true;
|
||||
console.log('[DEBUG] fetchTopics called');
|
||||
try {
|
||||
const token = localStorage.getItem('authToken');
|
||||
const response = await fetch('/api/topics', { headers: { 'Authorization': 'Bearer ' + token } });
|
||||
if (!response.ok) throw new Error('获取失败');
|
||||
const data = await response.json();
|
||||
this.topics = data || [];
|
||||
this.loadingTable = false;
|
||||
} catch (error) {
|
||||
console.log('获取选题失败:', error);
|
||||
console.log('获取选题失败,使用模拟数据');
|
||||
this.$message.error('获取选题失败,使用模拟数据');
|
||||
this.topics = [
|
||||
{ id: 'A01', title: '可持续发展趋势分析', field: '环保', status: '待处理', compliance_score: 85, created_at: '2026-04-27 10:30', generated_at: null, published_at: null },
|
||||
{ id: 'B02', title: 'AI 在内容创作中的应用', field: '科技', status: '待审查', compliance_score: 92, created_at: '2026-04-27 11:15', generated_at: '2026-04-27 11:45', published_at: null },
|
||||
{ id: 'C03', title: '数字化转型案例研究', field: '商业', status: '待发布', compliance_score: 78, created_at: '2026-04-27 12:00', generated_at: '2026-04-27 12:30', published_at: '2026-04-27 13:00' }
|
||||
];
|
||||
this.loadingTable = false;
|
||||
}
|
||||
const app = Vue.createApp(TopicsApp);
|
||||
app.use(ElementPlus);
|
||||
app.mount('#app');
|
||||
</script>
|
||||
},
|
||||
refreshAll() { this.$message.info('执行批量刷新'); },
|
||||
async triggerGenerateSelected() {
|
||||
if (!this.selectedTopicIds.length) return;
|
||||
this.$message.success('批量创作已启动');
|
||||
this.selectedTopicIds = [];
|
||||
await this.fetchTopics();
|
||||
},
|
||||
async triggerOptimizeSelected() {
|
||||
if (!this.selectedTopicIds.length) return;
|
||||
this.$message.success('批量优化已启动');
|
||||
this.selectedTopicIds = [];
|
||||
await this.fetchTopics();
|
||||
},
|
||||
openPreview(topic) { this.$message.info('预览:' + topic.title); },
|
||||
async createTopic(topic) {
|
||||
if (topic.status === '待处理') {
|
||||
this.$message.success('开始创作:' + topic.title);
|
||||
await this.fetchTopics();
|
||||
} else { this.$message.info('仅待处理选题可创作'); }
|
||||
},
|
||||
async optimizeTopic(topic) {
|
||||
if (topic.status === '待审查') {
|
||||
this.$message.success('开始优化:' + topic.title);
|
||||
await this.fetchTopics();
|
||||
} else { this.$message.info('仅待审查选题可优化'); }
|
||||
},
|
||||
async handlePublish(topic) { this.$message.success('发布:' + topic.title); await this.fetchTopics(); },
|
||||
deleteTopic(id) {
|
||||
this.$confirm('确定删除?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
|
||||
.then(async () => { this.$message.success('删除成功'); await this.fetchTopics(); }).catch(() => {});
|
||||
},
|
||||
handleLogout() { localStorage.removeItem('authToken'); window.location.href = '/'; },
|
||||
redirectToPage(page) { window.location.href = page.startsWith('/') ? page : '/' + page; },
|
||||
formatDate(dateStr) {
|
||||
if (!dateStr) return '-';
|
||||
try {
|
||||
return new Date(dateStr.replace(' ', 'T')).toLocaleString('zh-CN', {
|
||||
year: 'numeric', month: '2-digit', day: '2-digit',
|
||||
hour: '2-digit', minute: '2-digit'
|
||||
});
|
||||
} catch (e) { return dateStr; }
|
||||
},
|
||||
getStatusType(status) {
|
||||
const map = { '待处理': 'warning', '待审查': 'danger', '待发布': 'success', '已发布': 'info' };
|
||||
return map[status] || 'primary';
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log('[DEBUG] TopicsApp mounted');
|
||||
const token = localStorage.getItem('authToken');
|
||||
console.log('[DEBUG] Token exists:', !!token);
|
||||
if (!token) { window.location.href = '/'; return; }
|
||||
// 解析 URL filter 参数
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const filter = urlParams.get('filter');
|
||||
console.log('[DEBUG] URL filter:', filter);
|
||||
if (filter) { this.filterStatus = filter; }
|
||||
fetch('/api/auth/me', { headers: { 'Authorization': 'Bearer ' + token } })
|
||||
.then(response => response.ok ? response.json() : Promise.reject())
|
||||
.then(data => {
|
||||
console.log('[DEBUG] Auth success, user:', data.user);
|
||||
this.currentUser = data.user;
|
||||
this.isAdmin = data.user.role === 'admin';
|
||||
this.isLoggedIn = true;
|
||||
this.fetchTopics();
|
||||
})
|
||||
.catch(() => { localStorage.removeItem('authToken'); window.location.href = '/'; });
|
||||
}
|
||||
};
|
||||
const app = Vue.createApp(TopicsApp);
|
||||
app.use(ElementPlus);
|
||||
app.mount('#app');
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user