Files
pangolin/client/lib/widgets/plan_badge_card.dart
T
wangjia f35bbea0a0
ci-pangolin / Lint — shellcheck (push) Has been cancelled
ci-pangolin / OpenAPI Sync Check (push) Has been cancelled
ci-pangolin / Redline Scan — 脱敏 (UI 文案) (push) Has been cancelled
ci-pangolin / Flutter — analyze + test (push) Has been cancelled
fix(client): 连接后延迟用内核 urltest 实测 + 侧栏套餐到期日接真
- 延迟:TCP 探针在隧道开启时会被路由进隧道而测不到(显示 —)。改为连接后
  (phase==on)取内核 statsStream 的 urltest delayMs 最小正值(代理真实 RTT),
  未连接时仍用节点 TCP 探针。连接页 _SpeedRow/_NodePill/_CurrentNodeCard
  与统计页平均延迟统一此口径。
- plan_badge_card(侧栏)接 me.expiresAt 显示真实到期日(原只显示「有效期至」
  无日期);account_page 之外漏改的最后一处。

flutter analyze 0 error;114 tests passed。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 00:44:46 +08:00

71 lines
2.5 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// plan_badge_card.dart — 侧栏底部套餐卡(对照 dapp.jsx 侧栏底部)
//
// surface 底 + border + radius-md;左 30×30 crown 渐变(clay500→700)
// 右两行:套餐名 + 额度/有效期。免费/PRO 两态。
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../pangolin_theme.dart';
import '../state/account_providers.dart';
import '../state/app_providers.dart';
import 'pangolin_icons.dart';
class PlanBadgeCard extends ConsumerWidget {
const PlanBadgeCard({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final c = context.pangolin;
final t = ref.watch(appTextProvider);
final isFree = ref.watch(isFreePlanProvider);
final exp = ref.watch(meProvider).valueOrNull?.expiresAt;
String two(int v) => v.toString().padLeft(2, '0');
final expLine = exp == null
? t.expires
: '${t.expires} ${exp.toLocal().year}-${two(exp.toLocal().month)}-${two(exp.toLocal().day)}';
return Container(
padding: const EdgeInsets.symmetric(horizontal: 11, vertical: 9),
decoration: BoxDecoration(
color: c.surface,
border: Border.all(color: c.border),
borderRadius: BorderRadius.circular(PangolinRadius.md),
),
child: Row(children: [
Container(
width: 30,
height: 30,
decoration: const BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [PangolinColors.clay500, PangolinColors.clay700],
),
),
child: const Icon(PangolinIcons.crown, size: 15, color: PangolinColors.white),
),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
isFree ? t.freePlanName : t.proMember,
overflow: TextOverflow.ellipsis,
style: PangolinText.caption.copyWith(color: c.fg1, fontWeight: FontWeight.w600, fontSize: 12),
),
Text(
isFree ? t.quotaFree : expLine,
overflow: TextOverflow.ellipsis,
style: PangolinText.caption.copyWith(color: c.fg3, fontSize: 10.5),
),
],
),
),
]),
);
}
}