EpoCanvas 活躍等級規範:釋出視窗、五級閾值與可複核評估

完整解釋 EpoCanvas 近 30 天釋出活躍度的計算方式、五級閾值、多語言去重、釋出日期邊界、熱力圖區別及目前實作差異。

版本 v1.2.1 发表于 10/17/26 更新于 10/18/26

站長活躍等級分級與評估規範

EES-002 釋出活躍度 不是服務健康評分

活躍等級用於描述近期公開內容的釋出頻次。它不評價作者投入的總工時,不把修改舊文當作新發文章,也不替代站點監控、程式碼貢獻統計或內容質量評審。

[!IMPORTANT] 當前原始碼實現存在兩種“近 30 天”時間下界演算法:全站核心指標使用前推 30 個日曆日後的零點,頁面發文明細列表使用嚴格前推 720 小時(即 30 × 24 小時毫秒差)。 本文分別對兩套演算法進行嚴謹解析,不掩蓋程式碼中存在的實現差異。

1. 活躍等級的度量目標與定位

活躍等級的核心輸入是指定時間滑動視窗內的有效新發文章總數。

該指標專門用於回答以下創作與維護節奏問題:

  1. 站點在最近一個月內是否釋出過新的公開技術文章?
  2. 近期內容的釋出節奏是處於偶發探索、穩態維護還是密集交付?
  3. 隨著歷史文章逐漸滑出統計視窗,站點的近期活躍指標如何呈現動態遷移?

該指標明確不用於解答以下工程或質量問題:

  • 維護者近期提交了多少次 Git Commit 或修改了多少行業務程式碼;
  • 維護者修復或潤色了多少篇歷史已歸檔文章;
  • 邊緣服務節點與資料庫的即時可用率(SLA)是否達標;
  • 是否及時處理了讀者評論、安全更新或基礎設施遷移;
  • 所釋出的文章是否具備學術嚴謹性、工業級正確性或獨創價值。

介面中使用的“站長活躍”屬於讀者端展示文案;其嚴格的技術定義應為“站點公開技術文章的近期釋出活躍度”。

1.1 規則來源與程式碼對映

活躍等級的計算邏輯分佈於以下核心程式碼模組中:

模組職責對應程式碼位置 / 介面說明
閾值與文案定義src/config/standards.ts匯出權威配置物件 standardsConfig
等級階梯匹配matchActivityTier()純函式:根據整數篇數匹配對應等級物件
頁面初始指標精算src/lib/site-metrics.ts 中的 calculateSiteMetrics()Astro 構建期對文章集合進行多語言歸組並統計
公開文章集合過濾src/lib/content.ts 中的 getPublicPosts()排除草稿與受限內容,依據 i18nKey 提取代表文章
構建快照生成scripts/sync-console-metrics.mjs生成 public/data/console-metrics.json
邊緣請求期動態重算functions/api/console/data.ts基於請求當前時刻校準近期發文與熱力圖

當前遵循的標準配置標識為 EES-2026.4,配置版本為 2.6.0。

2. 五級閾值完整階梯與技術定義

系統定義了連續、無空隙且互斥的五個活躍等級區間:

等級標識狀態程式碼徽章顯示近 30 天發文量範圍官方評級名稱創作節奏參考描述
Lv.0Status 0Lv.0 Idle恰好 0 篇維護休眠視窗內無新文章,系統處於底座休整或歷史文件維護期
Lv.1Status 1Lv.1 Low1–2 篇週期推送保持每月 1 至 2 篇的基礎技術沉澱分享節奏
Lv.2Status 2Lv.2 Standard3–4 篇穩定維護保持雙週更或每週一篇的穩定知識沉澱節奏
Lv.3Status 3Lv.3 High5–8 篇高頻迭代保持高密度周更或多專題並行交付節奏
Lv.4Status 4Lv.4 Ultra至少 9 篇極客狂熱保持極高頻技術輸出與體系化系列專欄集中交付

區間端點為閉區間定義(包含邊界值):

  • 2 篇屬於 Lv.1,達到 3 篇則躍遷至 Lv.2;
  • 4 篇屬於 Lv.2,達到 5 篇則躍遷至 Lv.3;
  • 8 篇屬於 Lv.3,達到 9 篇則躍遷至最高階 Lv.4。

2.1 創作節奏說明的正確理解

配置中給出的“周更 >= 2 篇”、“保持雙週更”等節奏描述,是對創作者技術分享節奏的工程參考,不是第二套動態判定規則。

最終等級判定唯一取決於統計時刻滑動視窗內累積的文章數量計數。

例如:若作者在同一天內集中釋出了 5 篇獨立的技術專欄文章,即使在其餘 29 天內未釋出新文章,當前演算法依然判定視窗內文章數為 5,從而匹配至 Lv.3(高頻迭代)。系統當前版本並未引入“發文日期方差”或“連續打卡天數加權”作為降級懲罰因子。

[!TIP] 創作者無需為了追求更高的等級而強行將一篇完整的系統性技術長文拆散為多篇碎片。 保持文章架構的完整性、論證的嚴密性與工程復現的高可靠性,遠比追求等級數字更具長遠價值。

3. 資料流向與決策流水線

# 釋出活躍度判定模型
## 輸入後設資料
- 唯一文章標識 slug
- 釋出日期 pubDate
- 草稿標記 draft
- 訪問控制配置 access
- 多語言關聯標識 i18nKey
## 集合過濾與清洗
- 剔除 draft === true
- 剔除存在 access 配置條目
- 多語言版本歸組
- 提取單一代表性文章
## 時間視窗裁決
- 確定判定時刻 now
- 計算時間下界 lowerBound
- 剔除晚於 now 的未來文章
## 離散計數統計
- 滿足下界與上界即計 1 篇
- 不受文章字數字符加權
- 不受歷史更新時間干擾
## 階梯匹配對映
- 0 篇 -> Lv.0 Idle
- 1-2 篇 -> Lv.1 Low
- 3-4 篇 -> Lv.2 Standard
- 5-8 篇 -> Lv.3 High
- >=9 篇 -> Lv.4 Ultra

3.1 釋出日期的來源與後設資料性質

統計所使用的文章釋出時間,嚴格讀取自 Markdown 或 MDX 檔案 Frontmatter 中的 pubDate 欄位:

---
title: "分散式事務一致性與本地訊息表實現"
pubDate: 2026-10-18
updatedDate: 2026-10-18
draft: false
lang: "zh-CN"
i18nKey: "distributed-transaction-local-message"
---

技術人員必須清楚認識到:Frontmatter 中的 pubDate 是由作者顯式宣告的內容後設資料。它不是 Git 版本庫底層的提交時間戳(Author Date / Commit Date),也不是外部不可篡改時間戳服務(TSA)簽發的時間證明。核驗釋出真實性時,應當對照 Git 提交歷史與生產環境的首次部署時間。

4. “近 30 天”時間視窗的精確數學建模

在工程實踐中,“最近 30 天”存在不同的物理時間建模方式。當前倉庫中並存著兩套計算邏輯,必須準確把握兩者的技術邊界。

4.1 核心指標視窗:自然日零點下界模型

在 src/lib/site-metrics.ts(頁面初始指標)與 scripts/sync-console-metrics.mjs(構建快照)中,採用的是前推 30 個日曆日並截斷至當天零點的演算法:

// 核心指標計算邏輯
const lowerBound = new Date(now);
lowerBound.setDate(now.getDate() - 30);
lowerBound.setHours(0, 0, 0, 0);

// 文章判定條件(閉區間)
const isInRecentWindow = pubDate >= lowerBound && pubDate <= now;

其數學模型可表示為:

Wcalendar=[midnight(Tnow−30d),Tnow]W_{\text{calendar}} = [\text{midnight}(T_{\text{now}} - 30\text{d}), T_{\text{now}}]

該演算法的核心特徵:

  • 下界被強制校準為 30 天前那一日的本地時間 00:00:00.000;
  • 實際覆蓋的物理時間跨度通常在 720 小時至 743.99 小時之間(取決於計算時刻 TnowT_{\text{now}} 所處的具體時刻);
  • 若在下午或晚間執行計算,該視窗能夠完整包含 30 天前那一整天的所有文章,即便那篇文章發生在 720 小時更早的時間點。

4.2 頁面明細視窗:嚴格 720 小時毫秒差模型

在 src/pages/standards/activity-level.astro 中渲染“近期實際文章清單”時,程式碼採用的是嚴格按 30 個物理日(720 小時)的毫秒差向前推算:

// 頁面明細列表過濾邏輯
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);

// 文章判定條件
const isRecentDetail = pubDate >= thirtyDaysAgo && pubDate <= now;

其數學模型可表示為:

Wepoch=[Tnow−2,592,000,000ms,Tnow]W_{\text{epoch}} = [T_{\text{now}} - 2{,}592{,}000{,}000\text{ms}, T_{\text{now}}]

4.3 邊界差異的可複核案例

以下案例展示當文章處於臨界時間點時,兩套演算法的判定差異:

假定計算基準時刻為 UTC 時間:

T_now = 2026-10-18T16:00:00.000Z

計算兩側演算法得出的下界:

  • 核心指標演算法下界:2026-09-18T00:00:00.000Z(前推 30 日曆日並取零點);
  • 頁面明細演算法下界:2026-09-18T16:00:00.000Z(嚴格前推 720 小時)。

若有一篇真實文章的釋出時間為:

pubDate = 2026-09-18T08:00:00.000Z

判定結果對比:

  • 核心指標演算法:pubDate >= 2026-09-18T00:00:00.000Z 成立,該文章計入近 30 天發文量;
  • 頁面明細演算法:pubDate < 2026-09-18T16:00:00.000Z,該文章被明細表格剔除。

[!WARNING] 當讀者發現“頁頭顯示的近 30 天發文篇數與下方明細表格中的文章行數存在 1 篇差異”時,屬於該時間視窗邊界效應的正常體現,絕非資料庫損壞或統計指令碼失控。 統一兩套時間視窗的底層純函式重構已列入架構演進規劃(參見 EES-001 GAP-03)。

5. 准入過濾與多語言去重準則

並非倉庫記憶體在的每一個 Markdown 檔案都會進入活躍等級統計。統計前必須通過准入過濾流水線:

檢視不同內容形態的准入處理規則

准入統計:未標記草稿(draft !== true)、未設定訪問控制密碼(無 access 屬性)且在多語言版本中勝出成為代表性文章的條目,擁有合法的統計資格。若其釋出日期落入滑動視窗內,計入 1 篇發文。

完全排除:草稿文章代表尚未完稿的內容,不計入公共活躍度;帶 access 密碼保護的私密文章屬於受限資源,頁面側統計將其完全排除。注意:快照指令碼目前尚未同步排除 access 內容,屬於 GAP-01。

單組單計:同一篇文章的不同語言翻譯版本(如中、英、德等),在統計模型中被歸為一個主題單元。一個多語言組別僅由單一代表性版本參與計數,嚴禁同一文章翻譯多份刷取發文量。

未來剔除:若文章的 pubDate 晚於當前計算時刻 now,在計算近 30 天發文量時會被顯式條件 pubDate <= now 攔截,不會提前透支計入活躍等級。

5.1 多語言歸組演算法的工程實現

在 src/lib/content.ts 的 getPublicPosts() 中,歸組規則按以下優先順序執行:

步驟 1:提取文章分組鍵
        IF (文章存在顯式 frontmatter.i18nKey) -> 使用 i18nKey
        ELSE -> 從檔名 slug 中使用正則移除語言字尾(如 .en, -en, .zh-CN, -de 等)

步驟 2:對具有相同分組鍵的文章候選列表排序
        優先保留:檔名不包含任何語言字尾的主文章(Canonical Base File)
        若無主文章:保留按檔名標識自然排序的第一篇作為代表版本

技術約束要點:

  • 歸組演算法並不對比翻譯正文的實質相似度,完全依賴後設資料鍵與檔案命名;
  • 歸組並不強行校驗組內各語言版本的 pubDate 是否絕對同一;若譯文補全時寫了新的日期,而該譯文在排序規則中未成為代表版本,則該譯文日期不會改變統計結果。

6. 修訂舊文章為何不增加發文量

活躍等級以“新發布文章”為唯一計量標尺。對既有歷史文章進行補充、修補或勘誤時:

  • 更新 updatedDate 後設資料,可以點亮 52 周熱力圖中對應日期的格子;
  • 保持 pubDate 為原首發日期不變,該文章絕不會重新進入近 30 天發文視窗;
  • 若創作者違規篡改舊文章的 pubDate 為今天,技術上雖可迫使指標上升,但這屬於虛假篡改後設資料行為,破壞了版本歷史的可信度。

6.1 推薦的日期維護最佳實踐

對於技術文件的長期維護,推薦採取以下規範:

  1. pubDate 鎖定:始終保留文章最初成文並公開發布的原始日期,一旦釋出嚴禁隨意更改;
  2. updatedDate 推進:在發生架構升級、依賴破壞性變更排查或實質性技術補充後,更新 updatedDate;
  3. 獨立成篇準則:若重構內容與原文章結論存在根本性顛覆,且篇幅完整自洽,應當新建獨立的演進復盤文章,而非將歷史文章強行全量重寫覆蓋。

7. 52 周動態熱力圖生成機制

與單維度的活躍等級不同,52 周熱力圖為讀者提供直觀的二維活動日曆全景。

7.1 矩陣結構與時間對齊

熱力圖矩陣具有固定的幾何形態與邊界:

矩陣總格數:364 個單元格(嚴格對應 52 個完整週,52 × 7 = 364)
列向排列:週日(Index 0)至 週六(Index 6)
起止對齊:
  - 矩陣第一格:當前計算時刻往前推算 52 周所對應的那個週日;
  - 矩陣最後一格:當前周所對應的週六。

7.2 事件判定與單日色階量化

熱力圖日曆所記錄的“內容活動事件(Events)”來源如下:

  1. 每一篇納入統計文章的 pubDate 貢獻 1 次釋出事件;
  2. 每一篇具備有效 updatedDate 且其年月日與 pubDate 不同的文章,為更新日期貢獻 1 次修訂事件;
  3. 同一天內釋出且更新的文章,不計為兩次同日事件,合併為 1 次活動。

單日聚合事件數到視覺色階(0 至 4 階)的對映邏輯由分段函式 C(E)C(E) 精確定義:

C(E)={0,E=01,E=12,2≤E≤33,4≤E≤64,E≥7C(E) = \begin{cases} 0, & E = 0 \\ 1, & E = 1 \\ 2, & 2 \le E \le 3 \\ 3, & 4 \le E \le 6 \\ 4, & E \ge 7 \end{cases}

單日色階量化對映矩陣表 (Daily Activity Color Level Mapping Table):

聚合事件區間 EE視覺色階 C(E)C(E)核心 CSS 類名色階飽和度與視覺語義典型行為特徵與維護指標
E=0E = 0Level 0 (休眠階).activity-cell.level-0無底色填充(灰階微光,透明度 0.15)當日無文章新增,亦無舊文版本修訂
E=1E = 1Level 1 (初階活躍).activity-cell.level-1淺綠微光底色(低飽和度,溫和呈現)單篇技術文章釋出或小節修訂
2≤E≤32 \le E \le 3Level 2 (常規活躍).activity-cell.level-2中淺明亮青綠(中等飽和度,穩定產出)當日釋出多篇內容或進行關鍵章節系統重構
4≤E≤64 \le E \le 6Level 3 (高頻活躍).activity-cell.level-3鮮亮飽滿翠綠(高對比度,密集交付)密集迭代、技術專欄批次推進或全站功能重寫
E≥7E \ge 7Level 4 (極高活躍).activity-cell.level-4極高飽和高亮翠綠(最高視覺層級與微光效果)重大架構釋出、全語系文件交付或高強度馬拉松式更新

在執行時矩陣生成中,該對映邏輯由 TypeScript 強型別判定函式保證嚴格執行:

/**
 * 將單日聚合事件數 E 對映為 0 至 4 階視覺色階
 * @param count 單日有效釋出與修訂事件聚合總數
 * @returns 0 | 1 | 2 | 3 | 4
 */
export function resolveHeatmapCellLevel(count: number): 0 | 1 | 2 | 3 | 4 {
  if (count <= 0) return 0;
  if (count === 1) return 1;
  if (count <= 3) return 2;
  if (count <= 6) return 3;
  return 4;
}

7.3 熱力圖與發文等級的核心差異

比較維度52 周動態熱力圖近 30 天活躍等級
考察時間範圍過去 52 周(約 364 天)最近 30 天
是否計入修訂更新計入(基於有效的 updatedDate)不計入(僅依據 pubDate)
輸出表現形式矩陣日曆格子色階分佈離散等級徽章(Lv.0 至 Lv.4)
反應的維護狀態全年內容釋出與維護的持續性短期(當月)技術產出密度

8. 等級隨時間的自然衰減與離散躍變

活躍等級沒有引入連續的數學指數衰減公式(例如放射性半衰期演算法),也沒有設定“活躍積分池”。

所謂活躍度衰減,完全是由於歷史文章的釋出時間脫離了近 30 天滑動視窗的下界,從而導致的離散計數減少。

8.1 為什麼每月 1 號不會自動歸零

活躍等級基於滾動時間視窗(Rolling Window),不按自然日曆月份(Calendar Month)劃分。

如果作者在上個月 25 號釋出了 4 篇文章,當時間行進到次月 1 號時,距離 25 號僅過去 6 天,這些文章依然穩穩落在近 30 天視窗內,等級依然維持在 Lv.2。

8.2 階梯跳變的突變現象分析

因為判定是離散的,系統可能出現計數突變:

假定作者在 9 月 10 日集中釋出了 6 篇文章,之後未再發布新文:

  • 在 10 月 9 日時,近 30 天發文量為 6,等級為 Lv.3(高頻迭代);
  • 當時間跨越到 10 月 11 日時,這 6 篇文章全部脫離滑動視窗,視窗內發文量瞬間由 6 跌至 0,等級直降為 Lv.0(維護休眠)。

這種跳變是時間視窗機制的固有數學性質,不代表系統出現異常。

9. 進度條與區間裡程碑計算原理

在頁面展示中,活躍等級附帶進度條(Progress Bar)與下一級里程碑提示:

近 30 天實測發文:4 篇
距離下一等級 (Lv.3 高頻迭代) 還需 1 篇
[██████████████████░░] 80%

9.1 當前區間的進度模型

進度條反映的是當前等級區間內的推進完成度,而非全站從零到終局的總完成率:

當前等級區間下界基準區間目標基準區間跨度進度計算參考公式
Lv.00 篇1 篇 (Lv.1)1 篇P=0%P = 0\%
Lv.11 篇3 篇 (Lv.2)2 篇P=N−12×100%P = \frac{N - 1}{2} \times 100\%
Lv.23 篇5 篇 (Lv.3)2 篇P=N−32×100%P = \frac{N - 3}{2} \times 100\%
Lv.35 篇9 篇 (Lv.4)4 篇P=N−54×100%P = \frac{N - 5}{4} \times 100\%
Lv.49 篇最高階—P=100%P = 100\%(鎖定滿格)

目前頁面程式以區間下界與下一級門檻計算進度。例如文章數為 4 篇時,位於 Lv.2(3–4 篇),依現行公式 ((4 - 3) / (5 - 3)) × 100 得到 50%;新增 1 篇達到 5 篇並進入 Lv.3 後,進度會依新區間重新計算。這不表示之前的產出被清空,而是座標系切換到了新的等級區間。

10. 時序資料流處理與併發邊界分析

在邊緣計算執行時(Cloudflare Pages Functions)中,活躍等級的時間視窗判定會受到請求處理時刻、快取內容與日期截斷方式影響。本節只描述目前程式可以確認的時間處理,不把平台的分散式時鐘、快取一致性或效能行為寫成未經觀測的保證。

10.1 請求時刻與日期邊界

目前可以確認的處理方式如下:

  1. 單一請求時刻:functions/api/console/data.ts 在處理請求時取得一次 now,並用它計算建站天數、近 30 天計數與 52 週熱力圖,避免同一函式內反覆取值造成內部比較不一致;
  2. 日期截斷仍有實作邊界:核心計算與邊緣 API 以 setDate(... - 30) 後再 setHours(0, 0, 0, 0) 產生下界;這是目前的程式行為,不應宣稱為完全 UTC 或跨時區一致。頁面明細仍有嚴格 720 小時的另一套規則,詳見本文開頭的 KNOWN-GAP 說明;
  3. 快照階段去重:建置快照腳本會在產生 public/data/console-metrics.json 前依 canonical slug 去重。請求期主要重算快照中的資料,這不等於客戶端併發請求具有跨請求的冪等寫入機制。

10.2 執行成本的證據邊界

目前原始碼沒有為活躍度重算宣告公開的 CPU 毫秒上限、記憶體上限或固定文章數容量。程式會建立 364 個日曆格,並遍歷快照中的文章資料;實際耗時與記憶體仍取決於部署平台、快照大小、快取狀態與請求環境。若要對外提供性能數字,必須以固定資料集、平台、版本與重複測量結果另行建立 TEST-VERIFIED 報告。

11. 邊界測試矩陣與自動化斷言

用於迴歸測試活躍度演算法的核心測試用例矩陣:

測試用例編號輸入發文量 NN預期等級程式碼預期徽章文案校驗重點說明
TC-ACT-010Status 0Lv.0 Idle零發文邊界
TC-ACT-021Status 1Lv.1 LowLv.1 最小邊界
TC-ACT-032Status 1Lv.1 LowLv.1 最大邊界
TC-ACT-043Status 2Lv.2 StandardLv.2 躍遷臨界點
TC-ACT-054Status 2Lv.2 StandardLv.2 最大邊界
TC-ACT-065Status 3Lv.3 HighLv.3 躍遷臨界點
TC-ACT-078Status 3Lv.3 HighLv.3 最大邊界
TC-ACT-089Status 4Lv.4 UltraLv.4 躍遷臨界點
TC-ACT-0950Status 4Lv.4 Ultra超大規模發文穩定性

11.1 時間下界毫秒級測試斷言

在單元測試中必須固定虛擬時間 now(例如 vi.setSystemTime),執行邊界毫秒級斷言:

  • 用例 A:pubDate = lowerBound - 1ms ── 必須斷言為 false(不計入);
  • 用例 B:pubDate = lowerBound ── 必須斷言為 true(計入);
  • 用例 C:pubDate = now ── 必須斷言為 true(計入);
  • 用例 D:pubDate = now + 1ms ── 必須斷言為 false(未來文章不計入)。

12. 常見疑問深度解析

為什麼我最近沒有任何刪文操作,活躍等級卻突然下降了?

這是因為活躍等級衡量的是“距今 30 天滑動視窗”內的文章數量。30 天前釋出的文章隨著自然時間的推移滑出了時間視窗下界,導致視窗內有效計數減少。這屬於滑動視窗模型的正常表現。

我本週對 10 篇歷史文章進行了深度重構與程式碼勘誤,為什麼等級還是 Lv.0?

活躍等級嚴格以 pubDate(首發日期)為統計基準。對舊文章更新 updatedDate 能夠豐富 52 周熱力圖中的活動點,但不能將歷史文章重新包裝為新發文章計入近 30 天發文量。

Lv.4(極客狂熱)是否意味著本站的技術含量在業內處於最高水平?

完全不是。Lv.4 僅代表最近 30 天內公開文章的釋出數量達到了 9 篇或以上,它是一個物理釋出頻度的度量標尺。文章的技術獨創性、工程深度和學術價值,必須由專業同行進行實質性閱讀與復現評估。

頁面頂部的近期發文數字與下方列表中的文章篇數偶爾相差 1 篇,原因何在?

這是由於兩套時間視窗演算法的邊界差異引起的:核心指標統計視窗取的是前推 30 天當天的 00:00:00 零點,而明細列表採用嚴格的 720 小時(30 × 24h) 毫秒差。如果恰好有一篇文章釋出於 30 天前的早晨,且計算時刻在下午,就會出現該邊界差異。