feat(mira/feed): WikiStatusBadge — 顯示貼文 wiki 合成狀態 (leo 2026-05-17 反饋)
leo 反饋:「沒有符號顯示是否已建立 wiki,不知道是出錯了還是要等下一批」 新 component WikiStatusBadge 顯示在 PostCard header 來源/時間旁邊: - ✅ wiki — tags 含 wiki-processed - ⏳ 處理中 — 貼 < 6 分鐘前(cron 5 分鐘一輪,可能還沒撈到) - ○ 排隊 — 6-30 分鐘(等下一個 tick) - ⚠️ 漏了? — > 30 分鐘還沒處理(可能 wiki_synthesis 失敗) Mira 自己貼文(type=wiki-page from showMira)不顯示 — 它本身就是 wiki。 資料來源純 client-side:mainBlocksList[0].tags_json + doc.created_at。 未來可加 click → 跳對應 wiki page,或 hover 顯示 entity 預覽。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1139,6 +1139,18 @@ function DocCard({
|
||||
<SourceBadge source={postSource} />
|
||||
<span>·</span>
|
||||
<RelTime when={doc.updated_at} />
|
||||
{(() => {
|
||||
const badge = (
|
||||
<WikiStatusBadge
|
||||
mainBlock={mainBlocksList[0]}
|
||||
createdAt={doc.created_at}
|
||||
showMira={showMira}
|
||||
/>
|
||||
);
|
||||
return !showMira && mainBlocksList[0]
|
||||
? (<><span>·</span>{badge}</>)
|
||||
: null;
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
<MoreMenu items={cardMenu} />
|
||||
@@ -2046,6 +2058,81 @@ function SourceBadge({ source }: { source: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
// WikiStatusBadge:顯示這篇 raw 是否已合成 wiki
|
||||
// - ✅ 已合成(tags 含 wiki-processed)
|
||||
// - ⏳ 處理中(< 6 分鐘前貼,可能還沒被 cron 撈到 / wiki_synthesis 正在跑)
|
||||
// - ○ 排隊中(> 6 分鐘但 < 30 分鐘,等下一個 cron tick)
|
||||
// - ⚠️ 可能漏了(> 30 分鐘還沒處理)
|
||||
// 對應 leo 2026-05-17 反饋:「沒有符號顯示是否已建立 wiki」
|
||||
function WikiStatusBadge({
|
||||
mainBlock,
|
||||
createdAt,
|
||||
showMira,
|
||||
}: {
|
||||
mainBlock: KBDBBlock | undefined;
|
||||
createdAt: number | string;
|
||||
showMira: boolean;
|
||||
}) {
|
||||
// Mira 自己貼的(type=wiki-page)就是 wiki,不需要狀態
|
||||
if (showMira) return null;
|
||||
if (!mainBlock) return null;
|
||||
|
||||
let processed = false;
|
||||
try {
|
||||
const tags = JSON.parse(mainBlock.tags_json || '[]') as string[];
|
||||
processed = Array.isArray(tags) && tags.includes('wiki-processed');
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
|
||||
if (processed) {
|
||||
return (
|
||||
<span
|
||||
className="wiki-status wiki-status-done"
|
||||
title="已合成 wiki — click 看詳細 entity"
|
||||
style={{ color: '#3a8a3a', fontSize: '0.85em' }}
|
||||
>
|
||||
✅ wiki
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
const ageMs = Date.now() - toDate(createdAt).getTime();
|
||||
const minutes = ageMs / 60_000;
|
||||
|
||||
if (minutes < 6) {
|
||||
return (
|
||||
<span
|
||||
className="wiki-status wiki-status-pending"
|
||||
title="處理中(mira_feed_watcher 每 5 分鐘掃一次)"
|
||||
style={{ color: '#888', fontSize: '0.85em' }}
|
||||
>
|
||||
⏳ 處理中
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (minutes < 30) {
|
||||
return (
|
||||
<span
|
||||
className="wiki-status wiki-status-queued"
|
||||
title="排隊中等下一個 cron tick"
|
||||
style={{ color: '#aaa', fontSize: '0.85em' }}
|
||||
>
|
||||
○ 排隊
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span
|
||||
className="wiki-status wiki-status-stuck"
|
||||
title={`已 ${Math.floor(minutes)} 分鐘未處理 — 可能失敗,看 wiki/ 確認或 trigger watcher`}
|
||||
style={{ color: '#c66', fontSize: '0.85em' }}
|
||||
>
|
||||
⚠️ 漏了?
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function RelTime({ when }: { when: number | string }) {
|
||||
const d = toDate(when);
|
||||
const now = Date.now();
|
||||
|
||||
Reference in New Issue
Block a user