feat(ingest): API Push 前端层 + 文档 + 端到端联通
后端(支持 api_push source 创建/调度): - schemas/source.py:SourceIn.url 改成 str(允许 api_push 的 api-push:// 占位) - admin.py create_source 简化 url 传递 - workers/__main__.py:_rebuild_jobs 跳过 api_push 源(它是被动接收,不抓取) - workers/pipeline.py:run_once 也加同条件,api_push 不进抓取循环 前端: - api/articles.ts:ArticleListItem 加 is_short_news(required)/source_ref; ArticleDetail 加 external_id;导出 IngestTokenOut;adminApi 加 list/create/revoke ingest token 三个方法 - views/Feed.vue:卡片根 class 短新闻加 short-card(淡蓝底 #f6f9fc + 左侧 3px 蓝色色条 #4f9eff);元信息栏加 📰 短讯 角标;长新闻摘要 body_zh_text 截前 200 字,短新闻不截取保留换行(white-space: pre-wrap); 短新闻不显示 AI 插图 - views/ArticleDetail.vue:tag 行加 📰 短讯 + source_ref 角标;短新闻 路径下隐藏翻译状态/重译/原文链接按钮;正文区短新闻直接渲染 body_zh_text,跳过译文/原文/AI 配图卡片;Angel + 美团双评论卡片 都保留 - views/AdminSources.vue:kind 加 api_push 选项;api_push 源 URL 字段 变只读占位、隐藏抓取间隔;列表操作列加 🔑 Token 按钮; 弹窗支持生成(raw_token 一次性显示 + 复制)/列表/撤销 文档: - docs/api-push.md:调用方契约 + 三层去重 + 限速 + lifecycle + owner 操作手册 + curl/Python 示例 + 重试策略 + 故障排查 - README.md:关键特性加 API Push;API 概览加 /api/v1/ingest 和 3 个 /admin/.../ingest-tokens 端点
This commit is contained in:
@@ -156,9 +156,13 @@ function commentaryState(status?: string | null, content?: string | null): Comme
|
||||
return 'waiting'
|
||||
}
|
||||
|
||||
// 正文摘要(取 body_zh_text 前 N 字;没有就 fallback 到 summary_zh)
|
||||
function bodyExcerpt(text?: string | null, max = 200): string {
|
||||
// 正文摘要:长新闻截前 200 字(把多空白合并),短新闻保留原始换行不截取
|
||||
function bodyExcerpt(text?: string | null, max = 200, keepNewlines = false): string {
|
||||
if (!text) return ''
|
||||
if (keepNewlines) {
|
||||
// 短新闻:不去空白,保留 \n 让前端 white-space: pre-wrap 换行
|
||||
return text.length > max ? text.slice(0, max) + '…' : text
|
||||
}
|
||||
const trimmed = text.replace(/\s+/g, ' ').trim()
|
||||
return trimmed.length > max ? trimmed.slice(0, max) + '…' : trimmed
|
||||
}
|
||||
@@ -209,7 +213,10 @@ onMounted(async () => {
|
||||
v-for="a in items"
|
||||
:key="a.id"
|
||||
class="article-card"
|
||||
:class="{ 'article-card-read': a.is_read }"
|
||||
:class="{
|
||||
'article-card-read': a.is_read,
|
||||
'short-card': a.is_short_news,
|
||||
}"
|
||||
hoverable
|
||||
@click="open(a)"
|
||||
>
|
||||
@@ -235,6 +242,17 @@ onMounted(async () => {
|
||||
>
|
||||
{{ c }}
|
||||
</NTag>
|
||||
<!-- 短新闻(API Push)角标:固定显示 -->
|
||||
<NTag
|
||||
v-if="a.is_short_news"
|
||||
size="tiny"
|
||||
type="info"
|
||||
:bordered="false"
|
||||
round
|
||||
class="feed-short-tag"
|
||||
>
|
||||
📰 短讯
|
||||
</NTag>
|
||||
<!-- 已读/未读小标签 -->
|
||||
<NTag
|
||||
v-if="a.is_read"
|
||||
@@ -273,9 +291,9 @@ onMounted(async () => {
|
||||
{{ a.title }}
|
||||
</div>
|
||||
|
||||
<!-- AI 插图(若有) -->
|
||||
<!-- AI 插图(若有;短新闻不显示) -->
|
||||
<img
|
||||
v-if="a.image_ai_url || a.image_url"
|
||||
v-if="!a.is_short_news && (a.image_ai_url || a.image_url)"
|
||||
:src="a.image_ai_url || a.image_url || ''"
|
||||
style="
|
||||
display: block;
|
||||
@@ -290,9 +308,14 @@ onMounted(async () => {
|
||||
loading="lazy"
|
||||
/>
|
||||
|
||||
<!-- 翻译后正文摘要 -->
|
||||
<!--
|
||||
正文摘要:
|
||||
- 长新闻:body_zh_text 截前 200 字(去多余空白)
|
||||
- 短新闻:body_zh_text(=body_text)完整展示,保留换行
|
||||
-->
|
||||
<div
|
||||
v-if="a.body_zh_text || a.summary_zh"
|
||||
:class="{ 'short-body': a.is_short_news }"
|
||||
style="
|
||||
margin-top: 4px;
|
||||
color: var(--color-letter);
|
||||
@@ -300,7 +323,11 @@ onMounted(async () => {
|
||||
line-height: 1.75;
|
||||
"
|
||||
>
|
||||
{{ bodyExcerpt(a.body_zh_text || a.summary_zh, 220) }}
|
||||
{{
|
||||
a.is_short_news
|
||||
? bodyExcerpt(a.body_zh_text || a.summary_zh || '', 5000, true)
|
||||
: bodyExcerpt(a.body_zh_text || a.summary_zh, 200)
|
||||
}}
|
||||
</div>
|
||||
|
||||
<!-- 评论钩子(双 provider:Angel + 美团,三态显式显示:有内容 / 等待中 / 失败) -->
|
||||
@@ -590,6 +617,36 @@ onMounted(async () => {
|
||||
color: var(--color-text-faint);
|
||||
}
|
||||
|
||||
/* === 短新闻(API Push)卡片差异化 ===
|
||||
长新闻:卡片色调不变
|
||||
短新闻:淡蓝底 + 左侧 3px 蓝色竖线条,便于一眼区分
|
||||
*/
|
||||
.article-card.short-card {
|
||||
background: #f6f9fc;
|
||||
border-left: 3px solid #4f9eff;
|
||||
}
|
||||
.article-card.short-card:hover {
|
||||
background: #eef4fb;
|
||||
}
|
||||
/* 已读 + 短新闻:已读底色优先,左边色条仍保留作为"短讯"标识 */
|
||||
.article-card.short-card.article-card-read {
|
||||
background: #fafafa;
|
||||
border-left-color: #4f9eff;
|
||||
border-left-width: 3px;
|
||||
}
|
||||
|
||||
/* 短新闻正文:保留换行 */
|
||||
.short-body {
|
||||
white-space: pre-wrap;
|
||||
font-size: 13.5px;
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
/* 短讯角标 */
|
||||
.feed-short-tag {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* === 底部操作栏(浮在卡片右下角)=== */
|
||||
.feed-actions {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user