feat(chart): 用量详情页显示服务标识;图例只显示当前时间范围内模型(含 tooltip 残留修复)

This commit is contained in:
WaterRain 2026-09-11 06:52:36 +00:00
parent eecf54986f
commit a079a0bfcb
No known key found for this signature in database
3 changed files with 31 additions and 6 deletions

View File

@ -551,7 +551,8 @@ internal fun StackedBarChart(
Text(stringResource(R.string.common_no_data), color = InkMuted, style = MaterialTheme.typography.bodySmall)
return
}
var tooltipBucket by remember { mutableStateOf(buckets.lastOrNull()) }
// key = buckets:切换时间范围/筛选后重置 tooltip,避免残留旧数据
var tooltipBucket by remember(buckets) { mutableStateOf(buckets.lastOrNull()) }
val density = LocalDensity.current
val d = density.density
val barCount = buckets.size
@ -681,7 +682,8 @@ internal fun LineChart(
Text(stringResource(R.string.common_no_data), color = InkMuted, style = MaterialTheme.typography.bodySmall)
return
}
var tooltipBucket by remember { mutableStateOf(buckets.lastOrNull()) }
// key = buckets:切换时间范围/筛选后重置 tooltip,避免残留旧数据
var tooltipBucket by remember(buckets) { mutableStateOf(buckets.lastOrNull()) }
val density = LocalDensity.current
val d = density.density
val barCount = buckets.size

View File

@ -153,10 +153,14 @@ class UsageChartViewModel @Inject constructor(
// 降级后或用户手动选择 → 关闭降级,正常显示
allowFallback = false
// 图例数据源:只保留当前显示范围内实际出现过的模型
val rangeModels = result.flatMap { it.byModel.keys }.distinct().sorted()
_state.update {
it.copy(
buckets = result,
allModels = allModels,
rangeModels = rangeModels,
loading = false
)
}
@ -262,6 +266,8 @@ data class ChartUiState(
val loading: Boolean = true,
val granularity: ChartGranularity = ChartGranularity.LAST_5H_HOURLY,
val allModels: List<String> = emptyList(),
/** 当前显示范围内实际出现过的模型(图例只显示这些) */
val rangeModels: List<String> = emptyList(),
val selectedModels: Set<String> = emptySet(), // empty = all
val buckets: List<ChartBucket> = emptyList(),
val useUtc8: Boolean = false,

View File

@ -53,6 +53,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
@ -110,7 +111,23 @@ fun UsageDetailScreen(
snackbarHost = { SnackbarHost(snackbarHostState) },
topBar = {
TopAppBar(
title = { Text(stringResource(R.string.title_usage_detail)) },
title = {
val serviceLabel = if (clearViewModel == null) "OCGO" else "CommandCode"
Column {
Text(
stringResource(R.string.title_usage_detail),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
serviceLabel,
style = MaterialTheme.typography.bodySmall,
color = InkMuted,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
},
navigationIcon = { IconButton(onClick = onBack) { Icon(Icons.Filled.ArrowBack, stringResource(R.string.action_back)) } },
actions = {
if (clearViewModel != null) {
@ -209,7 +226,7 @@ fun UsageDetailScreen(
if (wideEnough) {
// 面板够宽:前两张图表并排
item {
val models = state.selectedModels.ifEmpty { state.allModels.toSet() }
val models = state.rangeModels
val costTotal = state.buckets.sumOf { it.totalCost.toDouble() / 100_000_000.0 }
val reqTotal = state.buckets.sumOf { it.totalRequests }
Row(
@ -256,7 +273,7 @@ fun UsageDetailScreen(
} else {
// 窄面板:三张图表纵向堆叠
item {
val models = state.selectedModels.ifEmpty { state.allModels.toSet() }
val models = state.rangeModels
val costTotal = state.buckets.sumOf { it.totalCost.toDouble() / 100_000_000.0 }
ChartCard(stringResource(R.string.chart_cost), "$${String.format(Locale.US, "%.4f", costTotal)}", { showCostDetail = true }) {
StackedBarChart(state.buckets,
@ -331,7 +348,7 @@ fun UsageDetailScreen(
minDate = startDate
)
}
val models = state.selectedModels.ifEmpty { state.allModels.toSet() }
val models = state.rangeModels
if (showCostDetail) ChartDetailDialog(stringResource(R.string.chart_detail_cost), { showCostDetail = false }) {
models.forEach { model -> val t = state.buckets.sumOf { it.byModel[model]?.cost ?:0L }; if (t>0) DetailRow(model, "$${String.format(Locale.US, "%.4f", t/100_000_000.0)}") }
}