diff --git a/src/dao.rs b/src/dao.rs index ef7d04c..c033d9f 100644 --- a/src/dao.rs +++ b/src/dao.rs @@ -74,14 +74,16 @@ pub fn create_api_key(conn: &Connection, user_id: i64, name: &str) -> Result Result> { let mut stmt = conn.prepare( - "SELECT id, key_value, name, status, created_at FROM api_keys \ + "SELECT id, key_value, name, status, created_at, last_used FROM api_keys \ WHERE user_id = ?1 AND status = 'active' ORDER BY id DESC", )?; let rows = stmt.query_map([user_id], |r| { let raw: String = r.get(1)?; let created_at: String = r.get(4)?; + let last_used: Option = r.get(5)?; Ok(serde_json::json!({ "id": r.get::<_, i64>(0)?, "key": auth::mask_api_key(&raw), @@ -89,6 +91,7 @@ pub fn list_api_keys(conn: &Connection, user_id: i64) -> Result(2)?, "status": r.get::<_, String>(3)?, "created_at": utc_iso(&created_at), + "last_used": last_used.as_deref().map(utc_iso), })) })?; let mut out = Vec::new(); diff --git a/src/routes/mod.rs b/src/routes/mod.rs index e44586e..3d529f4 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -749,6 +749,20 @@ mod tests { arr.iter().any(|k| k["full_key"] == new_key), "列表含新生成 key 的完整值 full_key" ); + // rant 2026-08-24T12:41:25:列表返回 last_used(新 key 未使用 → null;用过 → 时间串) + assert!( + arr.iter().all(|k| k["last_used"].is_null() + || k["last_used"] + .as_str() + .map(|s| !s.is_empty()) + .unwrap_or(false)), + "last_used 字段存在且为 null(未用)或时间串(已用)" + ); + assert!( + arr.iter() + .any(|k| k["full_key"] == new_key && k["last_used"].is_null()), + "新生成且未调用的 key last_used 应为 null" + ); assert!( arr.iter().all(|k| { k["full_key"] diff --git a/ui/index.html b/ui/index.html index 82edc7b..e00bcee 100644 --- a/ui/index.html +++ b/ui/index.html @@ -5,7 +5,7 @@ AITokenPool - + @@ -683,9 +683,9 @@

使用模型

- - - - + + + + diff --git a/ui/js/app.js b/ui/js/app.js index 55e97ab..56b97c5 100644 --- a/ui/js/app.js +++ b/ui/js/app.js @@ -1723,7 +1723,7 @@ name: k.name || T("common.unnamed"), key: k.key, created: String(k.created_at || "").slice(0, 10), - last: T("settings.ak.last.never"), + last: k.last_used || null, // rant 2026-08-24T12:41:25:真实最近使用时间(NULL=从未使用) status: k.status || "active", })); } else { @@ -1734,7 +1734,7 @@ "" + hl(k.name, rawQ) + "" + "" + esc(Live.apiKeys ? k.key : "") + "" + "" + esc(k.created) + "" + - "" + timeCell(k.last) + "" + + "" + (k.last ? timeCell(k.last) : esc(T("settings.ak.last.never"))) + "" + "" + (k.status === "active" ? '' + T("settings.ak.status.active") + "" : '' + esc(k.status || "—") + "") + "" + " " + " " +