fix: pipeline content tracking + topic article preview
db_helper.py: save_article now calculates and persists word_count generator.py: run_creator_blocking sets word_count for HTML-imported articles writer.py: fix title regex stripping content-leading numbers (35岁后→岁后) trends.py: fix Baidu hot_score str/int type comparison crash database.py: add missing content_tasks.org_id ALTER TABLE migration schemas.py + topics.py: topic list API returns article_count + articles[] previews topics.html: table view and card view show article badges with word counts, clickable to open preview Ultraworked with Sisyphus Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -109,6 +109,17 @@
|
||||
<el-table-column prop="status" label="状态" width="90">
|
||||
<template #default="scope"><span class="status-badge"><span class="status-dot" :class="scope.row.status"></span>{{ getStatusLabel(scope.row.status) }}</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文章" width="140">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.article_count > 0" style="display:flex;gap:4px;flex-wrap:wrap;">
|
||||
<el-tag v-for="a in (scope.row.articles || [])" :key="a.platform" :type="a.status === 'published' ? 'success' : 'warning'" size="small" style="cursor:pointer;" @click="openTopicArticlePreview(scope.row, a)">
|
||||
{{ platformShort(a.platform) }}
|
||||
<span v-if="a.word_count" style="margin-left:2px;opacity:0.7;">{{ fmtWordCount(a.word_count) }}</span>
|
||||
</el-tag>
|
||||
</div>
|
||||
<span v-else style="color:#c0c4cc;font-size:12px;">无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="compliance_score" label="合规分" width="90">
|
||||
<template #default="scope"><el-progress :percentage="scope.row.compliance_score || 0" :format="() => scope.row.compliance_score || '-'" :stroke-width="15"></el-progress></template>
|
||||
</el-table-column>
|
||||
@@ -145,6 +156,10 @@
|
||||
<div class="topic-card-tags">
|
||||
<el-tag size="small" type="info">{{ topic.field }}</el-tag>
|
||||
<el-tag size="small" type="warning">合规{{ topic.compliance_score }}</el-tag>
|
||||
<el-tag v-for="a in (topic.articles || [])" :key="a.platform" size="small" :type="a.status === 'published' ? 'success' : 'warning'" style="cursor:pointer;" @click="openTopicArticlePreview(topic, a)">
|
||||
{{ platformShort(a.platform) }}{{ a.word_count ? ' ' + fmtWordCount(a.word_count) : '' }}
|
||||
</el-tag>
|
||||
<el-tag v-if="topic.article_count === 0" size="small" type="info" effect="plain">无文章</el-tag>
|
||||
</div>
|
||||
<div class="topic-card-meta">
|
||||
<div>创建: {{ formatDate(topic.created_at) }}</div>
|
||||
@@ -534,6 +549,20 @@ const TopicsApp = {
|
||||
});
|
||||
},
|
||||
platformName(platform) { return { zhihu: '知乎', wechat: '微信公众号', xiaohongshu: '小红书' }[platform] || platform; },
|
||||
platformShort(platform) { return { zhihu: '知', wechat: '公', xiaohongshu: '红' }[platform] || platform; },
|
||||
fmtWordCount(wc) { if (!wc) return ''; if (wc >= 1000) return (wc / 1000).toFixed(wc >= 10000 ? 0 : 1) + 'k'; return wc + ''; },
|
||||
openTopicArticlePreview(topic, article) {
|
||||
this.previewTopic = topic;
|
||||
this.previewPlatform = article.platform;
|
||||
this.previewVisible = true;
|
||||
this.platformContents = {};
|
||||
this.previewImages = {};
|
||||
const token = this.getToken();
|
||||
if (!token) return;
|
||||
fetch(`/api/articles/${topic.id}/preview?platform=${article.platform}`, { headers: { 'Authorization': 'Bearer ' + token } })
|
||||
.then(r => r.ok ? r.json() : null).then(d => { if (d && d.html) { this.platformContents[article.platform] = d.html; if (d.images) this.previewImages[article.platform] = d.images; } })
|
||||
.catch(e => console.error(`加载${article.platform}预览失败:`, e));
|
||||
},
|
||||
copyContent(platform) {
|
||||
const html = this.platformContents[platform];
|
||||
if (!html) { this.$message.warning('暂无内容可复制'); return; }
|
||||
|
||||
Reference in New Issue
Block a user