fix: complete gemini frontend and usage follow-up
This commit is contained in:
+53
-20
@@ -152,7 +152,12 @@ pub async fn list_users(
|
||||
.fetch_one(&*state.db)
|
||||
.await?;
|
||||
|
||||
let items: Vec<UserResponse> = users.into_iter().map(|u| UserResponse::from(u)).collect();
|
||||
let mut items = Vec::with_capacity(users.len());
|
||||
for user in users {
|
||||
let mut item = UserResponse::from(user);
|
||||
attach_usage_summary(&state, &mut item).await?;
|
||||
items.push(item);
|
||||
}
|
||||
Ok(Json(json!({
|
||||
"data": items,
|
||||
"users": items,
|
||||
@@ -182,7 +187,9 @@ pub async fn get_user(
|
||||
.fetch_optional(&*state.db)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound(format!("User {} not found", id)))?;
|
||||
Ok(Json(json!({ "data": UserResponse::from(user) })))
|
||||
let mut item = UserResponse::from(user);
|
||||
attach_usage_summary(&state, &mut item).await?;
|
||||
Ok(Json(json!({ "data": item })))
|
||||
}
|
||||
|
||||
/// POST /api/admin/users
|
||||
@@ -228,13 +235,15 @@ pub async fn create_user(
|
||||
let key = format!("sk-user-{}", uuid::Uuid::new_v4());
|
||||
let key_name = format!("{} 的默认密钥", payload.username.trim());
|
||||
|
||||
sqlx::query("INSERT INTO downstream_api_keys (name, key, user_id, enabled) VALUES (?, ?, ?, ?)")
|
||||
.bind(&key_name)
|
||||
.bind(&key)
|
||||
.bind(user_id)
|
||||
.bind(true)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
sqlx::query(
|
||||
"INSERT INTO downstream_api_keys (name, key, user_id, enabled) VALUES (?, ?, ?, ?)",
|
||||
)
|
||||
.bind(&key_name)
|
||||
.bind(&key)
|
||||
.bind(user_id)
|
||||
.bind(true)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
|
||||
tx.commit().await?;
|
||||
|
||||
@@ -264,11 +273,11 @@ pub async fn get_user_usage(
|
||||
r#"
|
||||
SELECT
|
||||
COUNT(l.id) as total_requests,
|
||||
SUM(l.cost) as total_cost
|
||||
COALESCE(SUM(l.cost), 0.0) as total_cost
|
||||
FROM usage_logs l
|
||||
JOIN downstream_api_keys k ON l.downstream_key_id = k.id
|
||||
WHERE k.user_id = ?
|
||||
"#
|
||||
"#,
|
||||
)
|
||||
.bind(id)
|
||||
.fetch_one(&*state.db)
|
||||
@@ -277,11 +286,11 @@ pub async fn get_user_usage(
|
||||
// Last 7 days cost
|
||||
let last_7_days_cost: f64 = sqlx::query_scalar(
|
||||
r#"
|
||||
SELECT SUM(cost)
|
||||
SELECT COALESCE(SUM(l.cost), 0.0)
|
||||
FROM usage_logs l
|
||||
JOIN downstream_api_keys k ON l.downstream_key_id = k.id
|
||||
WHERE k.user_id = ? AND l.created_at >= datetime('now', '-7 days')
|
||||
"#
|
||||
"#,
|
||||
)
|
||||
.bind(id)
|
||||
.fetch_one(&*state.db)
|
||||
@@ -299,7 +308,7 @@ pub async fn get_user_usage(
|
||||
WHERE k.user_id = ? AND l.created_at >= datetime('now', '-30 days')
|
||||
GROUP BY day
|
||||
ORDER BY day ASC
|
||||
"#
|
||||
"#,
|
||||
)
|
||||
.bind(id)
|
||||
.fetch_all(&*state.db)
|
||||
@@ -314,7 +323,7 @@ pub async fn get_user_usage(
|
||||
WHERE k.user_id = ?
|
||||
ORDER BY l.id DESC
|
||||
LIMIT 50
|
||||
"#
|
||||
"#,
|
||||
)
|
||||
.bind(id)
|
||||
.fetch_all(&*state.db)
|
||||
@@ -325,10 +334,10 @@ pub async fn get_user_usage(
|
||||
json!({
|
||||
"id": row.get::<i64, _>("id"),
|
||||
"model": row.get::<Option<String>, _>("model"),
|
||||
"prompt_tokens": row.get::<i64, _>("prompt_tokens"),
|
||||
"completion_tokens": row.get::<i64, _>("completion_tokens"),
|
||||
"total_tokens": row.get::<i64, _>("total_tokens"),
|
||||
"cost": row.get::<f64, _>("cost"),
|
||||
"prompt_tokens": row.get::<Option<i64>, _>("prompt_tokens").unwrap_or(0),
|
||||
"completion_tokens": row.get::<Option<i64>, _>("completion_tokens").unwrap_or(0),
|
||||
"total_tokens": row.get::<Option<i64>, _>("total_tokens").unwrap_or(0),
|
||||
"cost": row.get::<Option<f64>, _>("cost").unwrap_or(0.0),
|
||||
"created_at": row.get::<Option<String>, _>("created_at"),
|
||||
})
|
||||
})
|
||||
@@ -345,7 +354,6 @@ pub async fn get_user_usage(
|
||||
})))
|
||||
}
|
||||
|
||||
|
||||
/// PUT /api/admin/users/{id}
|
||||
pub async fn update_user(
|
||||
State(state): State<AppState>,
|
||||
@@ -468,3 +476,28 @@ async fn ensure_email_available(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn attach_usage_summary(state: &AppState, item: &mut UserResponse) -> AppResult<()> {
|
||||
let (total_requests, total_cost, last_7_days_cost): (i64, f64, f64) = sqlx::query_as(
|
||||
r#"
|
||||
SELECT
|
||||
COUNT(l.id) AS total_requests,
|
||||
COALESCE(SUM(l.cost), 0.0) AS total_cost,
|
||||
COALESCE(SUM(CASE
|
||||
WHEN l.created_at >= datetime('now', '-7 days') THEN l.cost
|
||||
ELSE 0.0
|
||||
END), 0.0) AS last_7_days_cost
|
||||
FROM usage_logs l
|
||||
JOIN downstream_api_keys k ON l.downstream_key_id = k.id
|
||||
WHERE k.user_id = ?
|
||||
"#,
|
||||
)
|
||||
.bind(item.id)
|
||||
.fetch_one(&*state.db)
|
||||
.await?;
|
||||
|
||||
item.total_requests = Some(total_requests);
|
||||
item.total_cost = Some(total_cost);
|
||||
item.last_7_days_cost = Some(last_7_days_cost);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user