Files
jiu/client/lib/widgets/network_retry_button.dart
T
wangjia 6238b86dcb feat(client): 登录/注册页照原型重建,ds 真相源组件族统一全部屏
- 登录/注册(login.html/register.html 1:1):两栏卡片+品牌渐变面板+主题小衣服
  pill(onSurface 变体)+记住我(记录并预填最近账号)+原型式 toast 校验;
  登录 fidelity 1.4–2.1% 三主题全绿;注册暂不入闸(少 门店编号/兑换券 字段,
  已记 CONTRACT,screens.mjs 留存根)
- ds 原子补齐:DsToast(.toast 单例)/DsCheck(.check/.agree)/DsButton lg 档/
  DsSelect 替换全部旧 DropdownButton/DsField label 在上/DsInput 后缀与密码形态
- 全屏统一:对话框按钮全 DsButton、盒式输入主题钉死(visualDensity.standard、
  h38、InputDecorationTheme 渗漏修复)、图标全 lucide、JetBrains Mono 三端同源、
  BrandMark 真相源 logo、只读模式写操作全量守卫(WriteGuard+DsToast)
- 出入库列表:版式对齐原型(卡片对齐+搜索框居中)、KPI 近30天滚动、结清后
  失效财务应收应付表;商品编辑抽屉介绍库改搜索下拉、图片双击全屏预览
- 删除旧 UI 死代码:DataTableCard/FormDialog/PageScaffold/SearchChip/
  SelectProductDialog/tabStateProvider
- golden/fidelity:stock-in/out 补注册(9%)、login 入册(8%)、goldens 全量重打;
  修复 pubspec flutter_web_plugins 非法声明(CI pub get 阻断)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-03 09:58:14 +08:00

66 lines
2.3 KiB
Dart

import 'package:lucide_icons_flutter/lucide_icons.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../core/theme/context_tokens.dart';
import '../providers/connectivity_provider.dart';
import 'ds/ds_toast.dart';
/// 离线提示里的「重试」按钮:
/// - 检测中显示转圈 +「重试中…」(过程可感知)
/// - 重试结束用 SnackBar 反馈成功/失败(结果可感知)
///
/// [foreground] 适配不同底色(红色横幅用白字,琥珀框用深色)。
class NetworkRetryButton extends ConsumerWidget {
final Color foreground;
const NetworkRetryButton(
{super.key, this.foreground = Colors.white}); // ds-ignore: 横幅承载色上默认白字
@override
Widget build(BuildContext context, WidgetRef ref) {
final checking = ref.watch(connectivityCheckingProvider);
return TextButton(
onPressed: checking
? null
: () async {
final ok = await ref.read(connectivityProvider.notifier).retry();
if (!context.mounted) return;
showDsToast(
context,
ok ? '已重新连接服务器' : '仍无法连接服务器,请稍后重试',
bg: ok ? context.tokens.success : context.tokens.danger,
duration: const Duration(seconds: 2),
);
},
style: TextButton.styleFrom(
foregroundColor: foreground,
minimumSize: const Size(0, 32),
padding: const EdgeInsets.symmetric(horizontal: 10),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (checking)
SizedBox(
width: 14,
height: 14,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(foreground),
),
)
else
Icon(LucideIcons.refreshCw, size: 16, color: foreground),
const SizedBox(width: 6),
Text(
checking ? '重试中…' : '重试',
style: TextStyle(
color: foreground, fontSize: 13, fontWeight: FontWeight.w600),
),
],
),
);
}
}