fix(sub2api): 面板管理入口与余额齐平;用量磁贴压缩为两行

- 「面板管理」从卡片底部移到余额同一行右侧:给 BalanceMainArea 增加 balanceTrailing 槽,
  Sub2ApiBalanceWithUsage 用 Row(verticalAlignment=CenterVertically) 让入口与余额数字齐平,
  不再单独占一行并额外撑高卡片。
- 今日/近7天 磁贴由三行(周期名/Token/次数)改为两行:第一行「周期名 … 请求次数」左右分布,
  第二行 Token 数。磁贴高度 56dp → 44dp,卡片整体更紧凑。

真机验证(V2172A / Android 15):余额 359.01 位于 y958-1105,面板管理 y956-1037 与之同高;
磁贴两行 y1185-1243 / y1255-1339;点「面板管理」正常打开弹窗(弹窗内标题仍只有一个)。
compileDebugKotlin 与 lintDebug 均通过。
This commit is contained in:
Liuxinyu176 2026-09-12 10:18:19 +08:00
parent 56f85d296c
commit edc2a40dc1
2 changed files with 53 additions and 44 deletions

View File

@ -783,7 +783,31 @@ private fun DashboardCard(
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
// ─── 主体:服务特定的主信息 ─── // ─── 主体:服务特定的主信息 ───
BalanceMainArea(card) // Sub2API 把「面板管理」入口传入余额行,使其与余额数字齐平(见 Sub2ApiBalanceWithUsage)
val showPanelEntry = card.service == ServiceType.SUB2API &&
card.credentialState != CredentialStatus.State.NOT_CONFIGURED &&
onOpenPanelManagement != null
BalanceMainArea(
card = card,
balanceTrailing = if (showPanelEntry) {
{
TextButton(onClick = { onOpenPanelManagement!!.invoke() }) {
Text(
stringResource(R.string.sub2_panel_manage_title),
color = StrawberryPink,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.width(2.dp))
Icon(
imageVector = Icons.Filled.KeyboardArrowRight,
contentDescription = null,
tint = StrawberryPink
)
}
}
} else null
)
// 用量服务卡片底部:用量详情入口 + Token 活动快捷入口(仅当有凭证时显示) // 用量服务卡片底部:用量详情入口 + Token 活动快捷入口(仅当有凭证时显示)
if (onOpenUsageDetail != null && card.credentialState != com.rainy.token.domain.model.CredentialStatus.State.NOT_CONFIGURED) { if (onOpenUsageDetail != null && card.credentialState != com.rainy.token.domain.model.CredentialStatus.State.NOT_CONFIGURED) {
@ -827,29 +851,6 @@ private fun DashboardCard(
} }
} }
// Sub2API 面板管理快捷入口(仅已配置凭据时显示;按钮点击不会触发整卡点击)
if (card.service == ServiceType.SUB2API &&
card.credentialState != CredentialStatus.State.NOT_CONFIGURED &&
onOpenPanelManagement != null
) {
Spacer(modifier = Modifier.height(2.dp))
TextButton(onClick = onOpenPanelManagement) {
Text(
stringResource(R.string.sub2_panel_manage_title),
color = StrawberryPink,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.width(2.dp))
Icon(
imageVector = Icons.Filled.KeyboardArrowRight,
contentDescription = null,
tint = StrawberryPink,
modifier = Modifier.padding(top = 1.dp)
)
}
}
// ─── 底部:更新时间 / 错误信息 ─── // ─── 底部:更新时间 / 错误信息 ───
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
Text( Text(

View File

@ -51,7 +51,7 @@ import java.util.Locale
// ── Service-specific balance Composables ── // ── Service-specific balance Composables ──
@Composable @Composable
internal fun BalanceMainArea(card: DashboardCardUi) { internal fun BalanceMainArea(card: DashboardCardUi, balanceTrailing: (@Composable () -> Unit)? = null) {
val balance = card.displayBalance val balance = card.displayBalance
when { when {
card.credentialState == CredentialStatus.State.NOT_CONFIGURED -> { card.credentialState == CredentialStatus.State.NOT_CONFIGURED -> {
@ -99,9 +99,7 @@ internal fun BalanceMainArea(card: DashboardCardUi) {
OllamaUsageWindows(balance) OllamaUsageWindows(balance)
} }
card.service == ServiceType.SUB2API -> { card.service == ServiceType.SUB2API -> {
// 余额与「今日 / 近7天」并排:右侧两列紧凑展示,避免早先竖排时把卡片撑得过高、 Sub2ApiBalanceWithUsage(balance, balanceTrailing = balanceTrailing)
// 也避免在窄屏上把周期行挤到换行。
Sub2ApiBalanceWithUsage(balance)
} }
else -> { else -> {
Row(verticalAlignment = Alignment.Bottom) { Row(verticalAlignment = Alignment.Bottom) {
@ -649,9 +647,16 @@ internal fun usageUpdatedAtText(updatedAt: Long): String {
* 磁贴等宽 + 两行固定结构,保证 360dp 窄屏不换行、不同周期数值长度不一会错位。 * 磁贴等宽 + 两行固定结构,保证 360dp 窄屏不换行、不同周期数值长度不一会错位。
*/ */
@Composable @Composable
internal fun Sub2ApiBalanceWithUsage(balance: ServiceBalance) { internal fun Sub2ApiBalanceWithUsage(
balance: ServiceBalance,
balanceTrailing: (@Composable () -> Unit)? = null
) {
Column(modifier = Modifier.fillMaxWidth()) { Column(modifier = Modifier.fillMaxWidth()) {
Sub2ApiBalanceHero(balance) // 余额与右侧入口(面板管理)同处一行、垂直居中,使按钮与余额数字高度齐平
Row(verticalAlignment = Alignment.CenterVertically) {
Sub2ApiBalanceHero(balance, modifier = Modifier.weight(1f))
balanceTrailing?.invoke()
}
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
Sub2ApiUsageTiles(balance) Sub2ApiUsageTiles(balance)
} }
@ -717,12 +722,23 @@ private fun Sub2ApiUsageTiles(balance: ServiceBalance) {
.padding(horizontal = 12.dp, vertical = 10.dp), .padding(horizontal = 12.dp, vertical = 10.dp),
verticalArrangement = Arrangement.Center verticalArrangement = Arrangement.Center
) { ) {
Text( // 两行:第一行「周期 · 请求次数」,第二行 Token 数(避免占三行显得松散)
text = w.label, Row(verticalAlignment = Alignment.Bottom) {
style = MaterialTheme.typography.labelSmall, Text(
color = inkMuted(), text = w.label,
maxLines = 1 style = MaterialTheme.typography.labelSmall,
) color = inkMuted(),
maxLines = 1
)
Spacer(modifier = Modifier.weight(1f))
Text(
text = stringResource(R.string.sub2_home_requests, w.requests),
style = MaterialTheme.typography.labelSmall,
color = inkMuted(),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
Spacer(modifier = Modifier.height(3.dp)) Spacer(modifier = Modifier.height(3.dp))
Text( Text(
text = w.tokens, text = w.tokens,
@ -732,14 +748,6 @@ private fun Sub2ApiUsageTiles(balance: ServiceBalance) {
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
Spacer(modifier = Modifier.height(2.dp))
Text(
text = stringResource(R.string.sub2_home_requests, w.requests),
style = MaterialTheme.typography.labelSmall,
color = inkMuted(),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
} }
} }
} }