feat: Ollama详情页新增模型调用次数显示

在 OllamaUsageCard 的 5h 和每周用量窗口进度条下方,
新增模型级调用次数列表(按次数降序,品牌粉标色)。
数据来自已有的 extras[session.models]/[weekly.models],
新增 parseModelRequests() 解析 + ModelRequestList Composable。
仅改详情页,首页 Dashboard 未动。
This commit is contained in:
WaterRain 2026-07-07 21:46:59 +00:00
parent 75a5c8f81e
commit 9077605da6
No known key found for this signature in database

View File

@ -391,7 +391,7 @@ private fun UsageWindowRow(label: String, pct: Int?, resetInSec: Long?) {
}
/**
* Ollama Pro 专属:5h + 每周用量窗口卡。
* Ollama Pro 专属:5h + 每周用量窗口卡 + 模型级调用次数。
*/
@Composable
private fun OllamaUsageCard(state: State) {
@ -404,6 +404,9 @@ private fun OllamaUsageCard(state: State) {
val extras = balance?.extras ?: return
val plan = extras["plan"] ?: "—"
val sessionModels = parseModelRequests(extras["session.models"])
val weeklyModels = parseModelRequests(extras["weekly.models"])
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(20.dp),
@ -431,6 +434,10 @@ private fun OllamaUsageCard(state: State) {
pct = extras["session.pct"]?.toFloatOrNull()?.toInt(),
resetInSec = extras["session.resetAt"]?.toLongOrNull()?.let { (it - System.currentTimeMillis()) / 1000 }?.takeIf { it > 0 }
)
if (sessionModels.isNotEmpty()) {
Spacer(modifier = Modifier.height(10.dp))
ModelRequestList(models = sessionModels)
}
Spacer(modifier = Modifier.height(14.dp))
HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant)
Spacer(modifier = Modifier.height(14.dp))
@ -439,6 +446,60 @@ private fun OllamaUsageCard(state: State) {
pct = extras["weekly.pct"]?.toFloatOrNull()?.toInt(),
resetInSec = extras["weekly.resetAt"]?.toLongOrNull()?.let { (it - System.currentTimeMillis()) / 1000 }?.takeIf { it > 0 }
)
if (weeklyModels.isNotEmpty()) {
Spacer(modifier = Modifier.height(10.dp))
ModelRequestList(models = weeklyModels)
}
}
}
}
/**
* 解析 extras 中的模型调用次数字符串。
* 格式: "model1,count1;model2,count2"
*/
private fun parseModelRequests(raw: String?): List<Pair<String, Int>> {
if (raw.isNullOrBlank()) return emptyList()
return raw.split(";").mapNotNull { entry ->
val parts = entry.split(",")
if (parts.size == 2) {
val model = parts[0].trim()
val count = parts[1].trim().toIntOrNull()
if (model.isNotBlank() && count != null) model to count else null
} else null
}
}
/**
* 模型级调用次数列表。
* 每行显示模型名 + 调用次数,按次数降序排列。
*/
@Composable
private fun ModelRequestList(models: List<Pair<String, Int>>) {
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
Text(
text = "模型调用次数",
style = MaterialTheme.typography.labelSmall,
color = inkMuted()
)
models.sortedByDescending { it.second }.forEach { (model, count) ->
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = model,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurface,
modifier = Modifier.weight(1f)
)
Text(
text = count.toString(),
style = MaterialTheme.typography.bodySmall,
fontWeight = FontWeight.SemiBold,
color = StrawberryPink
)
}
}
}
}