diff --git a/client/lib/main.dart b/client/lib/main.dart index 3262114..16fdc16 100644 --- a/client/lib/main.dart +++ b/client/lib/main.dart @@ -229,8 +229,12 @@ class _RootFlowState extends ConsumerState { logLine('AutoConnect', 'triggering connect → ${node.code}'); ref.read(connectionProvider.notifier).toggle(); // 自动连接 toast:「正在自动连接到 X」(主显示区内居中,见 pangolin_toast)。 + // 瞬态信息,1.5s 即可(默认 3s 用户反馈偏长;与「已复制」1.4s 同量级)。 final t = ref.read(appTextProvider); - if (mounted) showPangolinToast(context, t.autoConnectingTo(node.localizedName(t.lang))); + if (mounted) { + showPangolinToast(context, t.autoConnectingTo(node.localizedName(t.lang)), + duration: const Duration(milliseconds: 1500)); + } } else { logLine('AutoConnect', 'NOT connecting (autoConnect=${settings.autoConnect} phase=$phase)'); } diff --git a/client/lib/screens/orders_page.dart b/client/lib/screens/orders_page.dart index 351fbd9..f6fa9ce 100644 --- a/client/lib/screens/orders_page.dart +++ b/client/lib/screens/orders_page.dart @@ -275,6 +275,17 @@ class _OrderDetailView extends ConsumerWidget { } } + // 「取消订单」(created 单详情)——远程 cancel 后刷新列表/详情;失败(如已支付, + // pay 回 409)不报错,同样走刷新,以最新状态为准(已付单会显示已开通)。 + Future _cancelOrder(BuildContext context, WidgetRef ref) async { + try { + await ref.read(paymentApiProvider).cancel(order.orderNo); + } catch (_) {} + if (!context.mounted) return; + ref.invalidate(ordersProvider); + ref.invalidate(orderDetailProvider(order.orderNo)); + } + Future _copy(BuildContext context, String text) async { await Clipboard.setData(ClipboardData(text: text)); if (context.mounted) { @@ -346,6 +357,12 @@ class _OrderDetailView extends ConsumerWidget { switch (o.status) { case 'created': list.add(PangolinButton(label: t.orderContinuePay, expand: true, onPressed: () => _resumePay(context, ref))); + // 原型 pending 态为双按钮:继续支付(主)+ 取消订单(ghost)——orders.html/ui-desktop 均已登记。 + list.add(PangolinButton( + label: t.cancelOrder, + variant: PangolinButtonVariant.ghost, + expand: true, + onPressed: () => _cancelOrder(context, ref))); // 过期单 pay 会话已失效,点击是重新下单而非续付 → 用「重新购买」避免歧义。 case 'expired': case 'canceled': diff --git a/client/test/widget/orders_page_test.dart b/client/test/widget/orders_page_test.dart index f9a036a..5a9f152 100644 --- a/client/test/widget/orders_page_test.dart +++ b/client/test/widget/orders_page_test.dart @@ -78,7 +78,8 @@ void main() { // 点 created 那单(月付)进详情 await tester.tap(find.text(t.proMonthly)); await tester.pumpAndSettle(); - // 详情字段行 + created 态动作「继续支付」 + // 详情字段行 + created 态动作:继续支付(主)+ 取消订单(ghost,原型 pending 双按钮) + expect(find.text(t.cancelOrder), findsOneWidget); expect(find.text(t.orderNoLabel), findsOneWidget); expect(find.text(t.orderContinuePay), findsWidgets); });