protocol_screen.dart 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_riverpod/flutter_riverpod.dart';
  3. import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
  4. import 'package:go_router/go_router.dart';
  5. import '../../../core/l10n/app_localizations.dart';
  6. import '../../../providers/help_center_provider.dart';
  7. /// 协议详情页面
  8. /// 路由: /protocol,通过 GoRouterState.extra 传入 ProtocolArgs。
  9. class ProtocolScreen extends ConsumerWidget {
  10. const ProtocolScreen({
  11. super.key,
  12. required this.title,
  13. this.categoryCode = 'PROTOCOL',
  14. });
  15. /// 协议标题,用于在列表中匹配对应条目(如 "服务条款");
  16. /// 若为空则显示该分类下的第一条内容。
  17. final String title;
  18. /// CMS 分类码:'PROTOCOL'(注册协议)或 'FOLLOW_PROTOCOL'(交易员协议)
  19. final String categoryCode;
  20. @override
  21. Widget build(BuildContext context, WidgetRef ref) {
  22. final cs = Theme.of(context).colorScheme;
  23. final asyncData = ref.watch(protocolByTitleProvider((categoryCode, title)));
  24. // AppBar 标题:有明确 title 时用 title,否则加载后用文章标题
  25. final appBarTitle = title.isNotEmpty
  26. ? title
  27. : asyncData.valueOrNull?.title ?? AppLocalizations.of(context)!.protocolDetail;
  28. return Scaffold(
  29. appBar: AppBar(
  30. leading: IconButton(
  31. icon: const Icon(Icons.chevron_left, size: 28),
  32. onPressed: () => context.pop(),
  33. ),
  34. title: Text(
  35. appBarTitle,
  36. style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600),
  37. ),
  38. centerTitle: true,
  39. ),
  40. body: asyncData.when(
  41. loading: () => const Center(child: CircularProgressIndicator()),
  42. error: (_, __) => Center(
  43. child: Text(AppLocalizations.of(context)!.loadFailed, style: TextStyle(color: cs.onSurface.withAlpha(153))),
  44. ),
  45. data: (item) {
  46. if (item == null || item.content.isEmpty) {
  47. return Center(
  48. child: Text(AppLocalizations.of(context)!.noContent, style: TextStyle(color: cs.onSurface.withAlpha(153))),
  49. );
  50. }
  51. return SingleChildScrollView(
  52. padding: const EdgeInsets.all(16),
  53. child: HtmlWidget(
  54. item.content,
  55. textStyle: TextStyle(
  56. color: cs.onSurface,
  57. fontSize: 14,
  58. height: 1.8,
  59. ),
  60. ),
  61. );
  62. },
  63. ),
  64. );
  65. }
  66. }
  67. /// 路由 extra 参数
  68. class ProtocolArgs {
  69. const ProtocolArgs({required this.title, this.categoryCode = 'PROTOCOL'});
  70. final String title;
  71. final String categoryCode;
  72. }