Files
ttstd_family_care/lib/features/account/presentation/wechat_binding_page.dart
2026-08-21 17:12:17 +08:00

185 lines
6.1 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.
import 'package:cupertino_ui/cupertino_ui.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../core/widgets/feature_ui.dart';
import '../../../core/widgets/settings_ui.dart';
import '../../../l10n/app_localizations.dart';
import '../data/account_providers.dart';
import 'account_controller.dart';
/// 微信绑定页(账号与安全 → 微信绑定)。
///
/// 展示当前绑定状态:已绑定时提供「解除绑定」,未绑定时提供「绑定微信」。
///
/// 注意:绑定动作需要微信开放平台 SDK 返回的授权 `code`。当前项目尚未接入
/// 微信 SDK[_bind] 中的 `authCode` 获取处以 TODO 标注,接入后替换即可。
class WechatBindingPage extends ConsumerWidget {
const WechatBindingPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final l10n = AppLocalizations.of(context);
final bindingAsync = ref.watch(wechatBindingProvider);
final action = ref.watch(accountControllerProvider);
ref.listen<AccountActionState>(accountControllerProvider, (prev, next) {
final alert = next.alert;
if (alert == null) return;
ref.read(accountControllerProvider.notifier).consumeAlert();
AppDialogs.alert(context, message: alert, confirmText: l10n.commonConfirm);
});
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text(l10n.wechatTitle),
leading: CupertinoButton(
padding: EdgeInsets.zero,
child: const Icon(CupertinoIcons.back),
onPressed: () => context.pop(),
),
),
child: SafeArea(
child: bindingAsync.when(
loading: () => const Center(child: CupertinoActivityIndicator()),
error: (e, _) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
l10n.commonLoadFailed,
style: const TextStyle(fontSize: 13, color: AppColors.sub),
),
const SizedBox(height: 10),
GestureDetector(
onTap: () => ref.invalidate(wechatBindingProvider),
child: Text(
l10n.commonRetry,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w700,
color: AppColors.green,
),
),
),
],
),
),
data: (binding) => ListView(
padding: const EdgeInsets.only(bottom: 24),
children: [
SectionTitle(l10n.securityWechat),
CardBox(
padding: EdgeInsets.zero,
child: SettingsRow(
emoji: '💬',
color: AppColors.green,
title: binding.bound
? (binding.nickname?.isNotEmpty == true
? binding.nickname!
: l10n.wechatBound)
: l10n.wechatUnbound,
subtitle: binding.bound
? binding.bindTime
: l10n.securityWechatSub,
trailing: _StatusBadge(bound: binding.bound, l10n: l10n),
),
),
const SizedBox(height: 8),
if (binding.bound)
PrimaryButton(
text: l10n.wechatUnbind,
color: AppColors.red,
loading: action.submitting,
onPressed: () => _confirmUnbind(context, ref, l10n),
)
else
PrimaryButton(
text: l10n.wechatBind,
loading: action.submitting,
onPressed: () => _bind(context, ref, l10n),
),
],
),
),
),
);
}
/// 绑定微信:需先通过微信 SDK 获取授权 code。
Future<void> _bind(
BuildContext context,
WidgetRef ref,
AppLocalizations l10n,
) async {
// TODO(wechat): 接入微信开放平台 SDK如 fluwx
// 调用 sendWeChatAuth 获取授权 code 后传入 bindWechat。
const String? authCode = null;
if (authCode == null) {
await AppDialogs.alert(
context,
message: l10n.wechatSdkUnavailable,
confirmText: l10n.commonConfirm,
);
return;
}
final ok = await ref.read(accountControllerProvider.notifier).bindWechat(authCode);
if (!ok || !context.mounted) return;
await AppDialogs.alert(
context,
message: l10n.wechatBindSuccess,
confirmText: l10n.commonConfirm,
);
}
/// 解绑微信(二次确认)。
Future<void> _confirmUnbind(
BuildContext context,
WidgetRef ref,
AppLocalizations l10n,
) async {
final confirmed = await AppDialogs.confirm(
context,
title: l10n.wechatUnbind,
message: l10n.wechatUnbindConfirm,
confirmText: l10n.wechatUnbind,
cancelText: l10n.commonCancel,
);
if (!confirmed) return;
final ok = await ref.read(accountControllerProvider.notifier).unbindWechat();
if (!ok || !context.mounted) return;
await AppDialogs.alert(
context,
message: l10n.wechatUnbindSuccess,
confirmText: l10n.commonConfirm,
);
}
}
/// 绑定状态徽标。
class _StatusBadge extends StatelessWidget {
const _StatusBadge({required this.bound, required this.l10n});
final bool bound;
final AppLocalizations l10n;
@override
Widget build(BuildContext context) => Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: bound ? const Color(0xFFECFDF3) : AppColors.track,
borderRadius: BorderRadius.circular(16),
),
child: Text(
bound ? l10n.wechatBound : l10n.wechatUnbound,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w700,
color: bound ? AppColors.green : AppColors.sub,
),
),
);
}