feat(client): pay v2 支付渠道 switch + 订单列表/详情端到端
购买/支付(Phase B): - 新 SegSwitch 段控 widget(镜像 .segswitch 原子) - 购买页重构:顶部支付渠道 switch(默认 USDT→加密货币 / 人民币→支付宝),套餐价随渠道分币种显示,删底部弹窗选方式;点购买直达支付页 - 支付页加订单信息卡(套餐/渠道/金额按币种) - models:PayChannel + PayCatalogItem.priceUsdtMicro/priceLabel(ch)/perMonthLabel(ch) 订单(P0,全新): - payment_api.listOrders() + orders_provider(列表 + 详情 family) - OrdersScreen 列表→详情(状态 pill / 可复制订单号 / 继续支付·重新购买) - 导航:NavView.orders + desktop_shell 分支 + account 入口 配套: - l10n +19 getter(支付渠道 4 + 订单 15)×6 语言,l10n 闸绿 - 图标单源迁移 lucide_icons_flutter + pangolin_icons.dart(codegen) - 联系渠道订正(Telegram/邮件 support@yanmeiai.com/官网) + 前端去广告&时长 - 测试:购买 switch 分币种 + 订单列表/空态/详情 + 假 API listOrders;golden 重录 - flutter analyze 0 error,flutter test 226 全绿 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
This commit is contained in:
@@ -24,19 +24,11 @@ class ConnectButton extends StatefulWidget {
|
||||
required this.secureLabel,
|
||||
this.elapsed = Duration.zero,
|
||||
this.size = 208,
|
||||
this.enabled = true,
|
||||
this.onDisabledTap,
|
||||
});
|
||||
|
||||
final VpnPhase phase;
|
||||
final VoidCallback onTap;
|
||||
|
||||
/// 是否可点。免费额度耗尽时置 false → 灰化不可连,点击走 onDisabledTap。
|
||||
final bool enabled;
|
||||
|
||||
/// 灰化态被点击的回调(如弹看广告加时/升级)。enabled=false 时生效。
|
||||
final VoidCallback? onDisabledTap;
|
||||
|
||||
/// off 态圆内文字(如「点击连接」/「CONNECT」)。
|
||||
final String offLabel;
|
||||
|
||||
@@ -63,26 +55,18 @@ class _ConnectButtonState extends State<ConnectButton> with SingleTickerProvider
|
||||
Widget build(BuildContext context) {
|
||||
final c = context.pangolin;
|
||||
final s = widget.phase;
|
||||
// 免费额度耗尽:off 态灰化不可连(锁图标 + 柔和阴影),点击走 onDisabledTap。
|
||||
final disabled = !widget.enabled && s == VpnPhase.off;
|
||||
|
||||
final Color fill = disabled
|
||||
? c.bgSubtle
|
||||
: switch (s) {
|
||||
VpnPhase.off => c.bgSubtle,
|
||||
VpnPhase.connecting => c.accent,
|
||||
VpnPhase.on => c.success,
|
||||
};
|
||||
final Color fg = disabled
|
||||
? c.fg3
|
||||
: (s == VpnPhase.off ? c.accent : PangolinColors.white);
|
||||
final IconData icon = disabled
|
||||
? PangolinIcons.lock
|
||||
: switch (s) {
|
||||
VpnPhase.off => PangolinIcons.power,
|
||||
VpnPhase.connecting => PangolinIcons.loader,
|
||||
VpnPhase.on => PangolinIcons.shieldCheck,
|
||||
};
|
||||
final Color fill = switch (s) {
|
||||
VpnPhase.off => c.bgSubtle,
|
||||
VpnPhase.connecting => c.accent,
|
||||
VpnPhase.on => c.success,
|
||||
};
|
||||
final Color fg = s == VpnPhase.off ? c.accent : PangolinColors.white;
|
||||
final IconData icon = switch (s) {
|
||||
VpnPhase.off => PangolinIcons.power,
|
||||
VpnPhase.connecting => PangolinIcons.loaderCircle,
|
||||
VpnPhase.on => PangolinIcons.shieldCheck,
|
||||
};
|
||||
|
||||
// off 用柔和阴影;connecting/on 增加同色光晕环(box-shadow,不动背景计算)。
|
||||
final List<BoxShadow> glow = s == VpnPhase.off
|
||||
@@ -100,7 +84,7 @@ class _ConnectButtonState extends State<ConnectButton> with SingleTickerProvider
|
||||
button: true,
|
||||
label: widget.offLabel,
|
||||
child: GestureDetector(
|
||||
onTap: disabled ? widget.onDisabledTap : widget.onTap,
|
||||
onTap: widget.onTap,
|
||||
child: AnimatedContainer(
|
||||
duration: PangolinMotion.slow,
|
||||
curve: PangolinMotion.easeOut,
|
||||
|
||||
Reference in New Issue
Block a user