flu-cli-core 1.0.5 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +9 -0
  2. package/dist/chunk-BGYZU6TU.js +466 -0
  3. package/dist/chunk-QGM4M3NI.js +37 -0
  4. package/dist/factory-LM2CTHPW.js +7 -0
  5. package/dist/factory-P6ABQFH3.js +7 -0
  6. package/dist/index.cjs +17766 -3244
  7. package/dist/index.d.cts +783 -99
  8. package/dist/index.d.ts +783 -99
  9. package/dist/index.js +17323 -2942
  10. package/dist/upgrade_snippets-BJ6CQY5Q.js +9 -0
  11. package/package.json +3 -3
  12. package/templates/README.md +12 -0
  13. package/templates/core_files/auth/auth_middleware.dart.template +33 -0
  14. package/templates/core_files/auth/auth_service.dart.template +22 -0
  15. package/templates/core_files/auth/auth_viewmodel_mixin.dart.template +9 -0
  16. package/templates/core_files/auth/index.dart.template +4 -0
  17. package/templates/core_files/base/base_service.dart.template +12 -0
  18. package/templates/core_files/base/index.dart.template +3 -0
  19. package/templates/core_files/config/agreement_document_page.dart.template +220 -0
  20. package/templates/core_files/config/app_agreement.dart.template +297 -0
  21. package/templates/core_files/config/app_config.dart.template +81 -22
  22. package/templates/core_files/config/app_env.dart.template +107 -0
  23. package/templates/core_files/config/app_initializer.dart.template +16 -23
  24. package/templates/core_files/config/index.dart.template +4 -1
  25. package/templates/core_files/config/privacy_dialog.dart.template +158 -0
  26. package/templates/core_files/index.dart.template +3 -0
  27. package/templates/core_files/mixins/page/keep_alive_mixin.dart.template +6 -0
  28. package/templates/core_files/mixins/page/scroll_controller_mixin.dart.template +7 -0
  29. package/templates/core_files/mixins/service/request_guard_mixin.dart.template +18 -0
  30. package/templates/core_files/mixins/viewmodel/debounce_mixin.dart.template +18 -0
  31. package/templates/core_files/network/app_http.dart.template +19 -4
  32. package/templates/core_files/network/index.dart.template +4 -0
  33. package/templates/core_files/network/interceptors/global_params_interceptor.dart.template +77 -0
  34. package/templates/core_files/network/interceptors/index.dart.template +3 -0
  35. package/templates/core_files/network/network_monitor.dart.template +18 -0
  36. package/templates/core_files/network/response_adapter.dart.template +8 -19
  37. package/templates/core_files/router/app_routes.dart.template +3 -6
  38. package/templates/core_files/storage/storage_keys.dart.template +6 -0
  39. package/templates/core_files/theme/app_color_config.dart.template +32 -0
  40. package/templates/core_files/theme/app_text_size_config.dart.template +22 -0
  41. package/templates/core_files/theme/app_text_style_config.dart.template +139 -0
  42. package/templates/core_files/theme/app_theme.dart.template +72 -12
  43. package/templates/core_files/theme/index.dart.template +3 -0
  44. package/templates/core_files/utils/loading_util.dart.template +1 -1
  45. package/templates/examples/eg_list_page.dart.template +1 -2
  46. package/templates/examples/eg_service.dart.template +27 -4
  47. package/templates/examples/home_feed_service.dart.template +37 -0
  48. package/templates/helper_examples/image_picker_example_page.dart.template +289 -0
  49. package/templates/helper_examples/index.dart.template +4 -0
  50. package/templates/helper_examples/payment_shell_example_page.dart.template +67 -0
  51. package/templates/helper_examples/permission_example_page.dart.template +365 -0
  52. package/templates/helper_examples/webview_example_page.dart.template +44 -0
  53. package/templates/helpers/image_picker/README.md.template +30 -0
  54. package/templates/helpers/image_picker/index.dart.template +73 -0
  55. package/templates/helpers/payment/README.md.template +29 -0
  56. package/templates/helpers/payment/index.dart.template +66 -0
  57. package/templates/helpers/permission/README.md.template +30 -0
  58. package/templates/helpers/permission/index.dart.template +67 -0
  59. package/templates/helpers/webview/README.md.template +29 -0
  60. package/templates/helpers/webview/index.dart.template +88 -0
  61. package/templates/starter_project/.env.dev.template +14 -0
  62. package/templates/starter_project/.env.prod.example.template +14 -0
  63. package/templates/starter_project/.env.staging.template +14 -0
  64. package/templates/starter_project/.vscode/launch.json.template +54 -0
  65. package/templates/starter_project/.vscode/settings.json.template +14 -0
  66. package/templates/starter_project/DEVELOPER_GUIDE.md.template +169 -0
  67. package/templates/starter_project/README.md.template +117 -0
  68. package/templates/starter_project/analysis_options.yaml.template +28 -0
  69. package/templates/starter_project/lib/app.dart.template +22 -0
  70. package/templates/starter_project/lib/main.dart.template +34 -0
  71. package/templates/starter_project/lib/pages/splash_page.dart.template +154 -0
  72. package/templates/template_clean/lib/features/home/data/datasources/index.dart +1 -0
  73. package/templates/template_clean/lib/features/home/data/models/index.dart +1 -0
  74. package/templates/template_clean/lib/features/home/domain/index.dart +1 -0
  75. package/templates/template_clean/lib/features/home/presentation/pages/home_page.dart +290 -0
  76. package/templates/template_clean/lib/features/home/presentation/pages/index.dart +2 -0
  77. package/templates/template_clean/lib/features/home/presentation/pages/splash_page.dart +154 -0
  78. package/templates/template_clean/lib/features/home/presentation/viewmodels/home_viewmodel.dart +17 -0
  79. package/templates/template_clean/lib/features/index.dart +2 -0
  80. package/templates/template_clean/lib/features/user/data/datasources/home_feed_service.dart +37 -0
  81. package/templates/template_clean/lib/features/user/data/datasources/index.dart +4 -0
  82. package/templates/template_clean/lib/features/user/data/models/index.dart +3 -0
  83. package/templates/template_clean/lib/features/user/data/models/user.dart +15 -0
  84. package/templates/template_clean/lib/features/user/domain/index.dart +1 -0
  85. package/templates/template_clean/lib/features/user/presentation/pages/index.dart +1 -0
  86. package/templates/template_clean/lib/features/user/presentation/pages/user_list_page.dart +27 -0
  87. package/templates/template_clean/lib/features/user/presentation/viewmodels/user_list_viewmodel.dart +88 -0
  88. package/templates/template_clean/lib/features/user/presentation/widgets/user_item_card.dart +24 -0
  89. package/templates/template_clean/lib/shared/extensions/index.dart +1 -0
  90. package/templates/template_clean/lib/shared/widgets/index.dart +1 -0
  91. package/templates/template_lite/lib/models/index.dart +1 -0
  92. package/templates/template_lite/lib/pages/home_page.dart +290 -0
  93. package/templates/template_lite/lib/pages/index.dart +3 -0
  94. package/templates/template_lite/lib/pages/splash_page.dart +154 -0
  95. package/templates/template_lite/lib/pages/user_list_page.dart +29 -0
  96. package/templates/template_lite/lib/services/home_feed_service.dart +37 -0
  97. package/templates/template_lite/lib/services/index.dart +5 -0
  98. package/templates/template_lite/lib/utils/index.dart +1 -0
  99. package/templates/template_lite/lib/viewmodels/home_viewmodel.dart +34 -0
  100. package/templates/template_lite/lib/viewmodels/index.dart +2 -0
  101. package/templates/template_lite/lib/viewmodels/user_list_viewmodel.dart +103 -0
  102. package/templates/template_lite/lib/widgets/index.dart +1 -0
  103. package/templates/template_lite/lib/widgets/user_item_widget.dart +57 -0
  104. package/templates/template_modular/lib/features/home/index.dart +2 -0
  105. package/templates/template_modular/lib/features/home/models/index.dart +1 -0
  106. package/templates/template_modular/lib/features/home/pages/home_page.dart +290 -0
  107. package/templates/template_modular/lib/features/home/pages/index.dart +2 -0
  108. package/templates/template_modular/lib/features/home/pages/splash_page.dart +154 -0
  109. package/templates/template_modular/lib/features/home/services/index.dart +1 -0
  110. package/templates/template_modular/lib/features/home/viewmodels/home_viewmodel.dart +17 -0
  111. package/templates/template_modular/lib/features/index.dart +2 -0
  112. package/templates/template_modular/lib/features/user/index.dart +6 -0
  113. package/templates/template_modular/lib/features/user/pages/user_list_page.dart +26 -0
  114. package/templates/template_modular/lib/features/user/services/home_feed_service.dart +37 -0
  115. package/templates/template_modular/lib/features/user/viewmodels/user_list_viewmodel.dart +103 -0
  116. package/templates/template_modular/lib/features/user/widgets/user_item_widget.dart +24 -0
  117. package/templates/template_modular/lib/shared/utils/index.dart +1 -0
  118. package/templates/template_modular/lib/shared/widgets/index.dart +1 -0
@@ -0,0 +1,77 @@
1
+ import 'package:dio/dio.dart';
2
+ import 'package:flutter/foundation.dart';
3
+
4
+ /// 全局参数自动注入拦截器。
5
+ class GlobalParamsInterceptor extends Interceptor {
6
+ GlobalParamsInterceptor({
7
+ required this.getParams,
8
+ this.injectToData = true,
9
+ });
10
+
11
+ final Map<String, dynamic> Function() getParams;
12
+ final bool injectToData;
13
+
14
+ static bool _isGetLike(String? method) {
15
+ final m = (method ?? 'GET').toUpperCase();
16
+ return m == 'GET' || m == 'HEAD';
17
+ }
18
+
19
+ void _mergeIntoQuery(RequestOptions options, Map<String, dynamic> params) {
20
+ final newQueryParams = Map<String, dynamic>.from(options.queryParameters);
21
+ newQueryParams.addAll(params);
22
+ options.queryParameters = newQueryParams;
23
+ }
24
+
25
+ void _mergeIntoBody(RequestOptions options, Map<String, dynamic> params) {
26
+ if (options.data == null) {
27
+ options.data = Map<String, dynamic>.from(params);
28
+ return;
29
+ }
30
+ if (options.data is Map) {
31
+ final newData = Map<String, dynamic>.from(options.data as Map);
32
+ newData.addAll(params);
33
+ options.data = newData;
34
+ return;
35
+ }
36
+ if (options.data is FormData) {
37
+ final formData = options.data as FormData;
38
+ for (final entry in params.entries) {
39
+ formData.fields.add(MapEntry(entry.key, entry.value?.toString() ?? ''));
40
+ }
41
+ return;
42
+ }
43
+ assert(() {
44
+ debugPrint(
45
+ 'GlobalParamsInterceptor: 未注入全局参数,body 类型 '
46
+ '${options.data.runtimeType} 不支持合并',
47
+ );
48
+ return true;
49
+ }());
50
+ }
51
+
52
+ @override
53
+ void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
54
+ try {
55
+ final params = getParams();
56
+ if (params.isEmpty) {
57
+ return handler.next(options);
58
+ }
59
+
60
+ if (_isGetLike(options.method)) {
61
+ _mergeIntoQuery(options, params);
62
+ return handler.next(options);
63
+ }
64
+
65
+ if (injectToData) {
66
+ _mergeIntoBody(options, params);
67
+ } else {
68
+ _mergeIntoQuery(options, params);
69
+ }
70
+
71
+ handler.next(options);
72
+ } catch (error) {
73
+ debugPrint('GlobalParamsInterceptor Error: $error');
74
+ handler.next(options);
75
+ }
76
+ }
77
+ }
@@ -1,6 +1,9 @@
1
1
  export 'app_response_interceptor.dart';
2
+ {{#if_auth}}
2
3
  export 'auth_interceptor.dart';
4
+ {{/if_auth}}
3
5
  export 'error_interceptor.dart';
6
+ export 'global_params_interceptor.dart';
4
7
  export 'log_interceptor.dart';
5
8
  export 'network_error_interceptor.dart';
6
9
  export 'retry_interceptor.dart';
@@ -0,0 +1,18 @@
1
+ import 'package:connectivity_plus/connectivity_plus.dart';
2
+
3
+ /// 提供最小网络状态监听封装,供项目初始化或全局状态层接入。
4
+ class NetworkMonitor {
5
+ NetworkMonitor({
6
+ Connectivity? connectivity,
7
+ }) : _connectivity = connectivity ?? Connectivity();
8
+
9
+ final Connectivity _connectivity;
10
+
11
+ Stream<List<ConnectivityResult>> watch() {
12
+ return _connectivity.onConnectivityChanged;
13
+ }
14
+
15
+ Future<List<ConnectivityResult>> current() {
16
+ return _connectivity.checkConnectivity();
17
+ }
18
+ }
@@ -13,6 +13,14 @@ abstract class AppResponseAdapter {
13
13
  class DefaultResponseAdapter extends AppResponseAdapter {
14
14
  @override
15
15
  Map<String, dynamic> adapt(dynamic json) {
16
+ if (json is List) {
17
+ return {
18
+ 'code': AppErrorCode.success,
19
+ 'msg': '成功',
20
+ 'data': json,
21
+ };
22
+ }
23
+
16
24
  if (json is Map) {
17
25
  return {
18
26
  'code': json['code'] ?? AppErrorCode.networkError,
@@ -48,22 +56,3 @@ Map<String, dynamic> _buildError(String msg) {
48
56
  'data': null,
49
57
  };
50
58
  }
51
-
52
- /// 图虫 API 适配器
53
- /// 对应格式: { "result": "SUCCESS", "message": "...", "feedList": [...] }
54
- class TuChongAdapter extends AppResponseAdapter {
55
- @override
56
- Map<String, dynamic> adapt(dynamic json) {
57
- if (json is Map) {
58
- final result = json['result'];
59
- final isSuccess = result == 'SUCCESS';
60
-
61
- return {
62
- 'code': isSuccess ? 200 : -1,
63
- 'msg': json['message'] ?? '',
64
- 'data': json['feedList'] ?? json['data'],
65
- };
66
- }
67
- return _buildError('数据格式错误');
68
- }
69
- }
@@ -12,8 +12,7 @@ class AppRoutes {
12
12
  // 路由常量
13
13
  static const String home = '/';
14
14
  static const String splash = '/splash';
15
- static const String egList = '/eg-list';
16
- static const String userList = '/user-list';
15
+ // 网络示例路由 - CLI 动态注入
17
16
 
18
17
  // __ROUTE_CONFIG_START__
19
18
  /// Material 路由映射
@@ -21,10 +20,8 @@ class AppRoutes {
21
20
  static Map<String, WidgetBuilder> get routes {
22
21
  return {
23
22
  home: (context) => const HomePage(),
24
- userList: (context) => const UserListPage(),
25
- {{#if_network}}
26
- egList: (context) => const EgListPage(),
27
- {{/if_network}}
23
+ splash: (context) => const SplashPage(),
24
+ // 网络示例路由映射 - 由 CLI 动态注入
28
25
  // --- 在此下方添加您的自定义路由 ---
29
26
  };
30
27
  }
@@ -10,6 +10,12 @@ abstract class StorageKeys {
10
10
  /// 当前应用版本(用于版本迁移)
11
11
  static const appVersion = 'app_version';
12
12
 
13
+ /// 是否已同意隐私协议
14
+ static const privacyAgreed = 'app_privacy_agreed';
15
+
16
+ /// 已接受的协议版本
17
+ static const agreementAcceptedVersion = 'app_agreement_accepted_version';
18
+
13
19
  // ==================== 用户相关 ====================
14
20
 
15
21
  /// 用户 Token
@@ -0,0 +1,32 @@
1
+ import 'package:flutter/material.dart';
2
+
3
+ /// 统一维护项目级颜色令牌,供 Theme 和文本样式配置复用。
4
+ class AppColorConfig {
5
+ static AppColorConfig get I => const AppColorConfig();
6
+
7
+ const AppColorConfig({
8
+ this.primary = const Color(0xFF3B82F6),
9
+ this.secondary = const Color(0xFF22C55E),
10
+ this.background = const Color(0xFFF8FAFC),
11
+ this.surface = Colors.white,
12
+ this.title = const Color(0xFF111827),
13
+ this.titleSecondary = const Color(0xFF4B5563),
14
+ this.caption = const Color(0xFF6B7280),
15
+ this.divider = const Color(0xFFE5E7EB),
16
+ this.error = const Color(0xFFEF4444),
17
+ this.success = const Color(0xFF22C55E),
18
+ this.warning = const Color(0xFFF59E0B),
19
+ });
20
+
21
+ final Color primary;
22
+ final Color secondary;
23
+ final Color background;
24
+ final Color surface;
25
+ final Color title;
26
+ final Color titleSecondary;
27
+ final Color caption;
28
+ final Color divider;
29
+ final Color error;
30
+ final Color success;
31
+ final Color warning;
32
+ }
@@ -0,0 +1,22 @@
1
+ /// 统一维护语义化字号,避免模板默认暴露 s12/s14 这类数字别名。
2
+ class AppTextSizeConfig {
3
+ const AppTextSizeConfig({
4
+ this.caption = 12,
5
+ this.bodySmall = 13,
6
+ this.body = 14,
7
+ this.bodyLarge = 16,
8
+ this.titleSmall = 18,
9
+ this.title = 20,
10
+ this.titleLarge = 24,
11
+ this.headline = 28,
12
+ });
13
+
14
+ final double caption;
15
+ final double bodySmall;
16
+ final double body;
17
+ final double bodyLarge;
18
+ final double titleSmall;
19
+ final double title;
20
+ final double titleLarge;
21
+ final double headline;
22
+ }
@@ -0,0 +1,139 @@
1
+ import 'package:flutter/material.dart';
2
+
3
+ import 'app_color_config.dart';
4
+ import 'app_text_size_config.dart';
5
+
6
+ /// 基于颜色和字号配置生成语义化文本样式,允许调用方按场景覆盖细节。
7
+ class AppTextStyleConfig {
8
+ const AppTextStyleConfig({
9
+ this.colors = const AppColorConfig(),
10
+ this.sizes = const AppTextSizeConfig(),
11
+ this.fontFamily,
12
+ });
13
+
14
+ static AppTextStyleConfig get I => const AppTextStyleConfig();
15
+
16
+ final AppColorConfig colors;
17
+ final AppTextSizeConfig sizes;
18
+ final String? fontFamily;
19
+
20
+ TextStyle caption({
21
+ Color? color,
22
+ FontWeight? fontWeight,
23
+ double? height,
24
+ }) {
25
+ return _style(
26
+ fontSize: sizes.caption,
27
+ color: color ?? colors.caption,
28
+ fontWeight: fontWeight,
29
+ height: height,
30
+ );
31
+ }
32
+
33
+ TextStyle bodySmall({
34
+ Color? color,
35
+ FontWeight? fontWeight,
36
+ double? height,
37
+ }) {
38
+ return _style(
39
+ fontSize: sizes.bodySmall,
40
+ color: color ?? colors.titleSecondary,
41
+ fontWeight: fontWeight,
42
+ height: height,
43
+ );
44
+ }
45
+
46
+ TextStyle body({
47
+ Color? color,
48
+ FontWeight? fontWeight,
49
+ double? height,
50
+ }) {
51
+ return _style(
52
+ fontSize: sizes.body,
53
+ color: color ?? colors.title,
54
+ fontWeight: fontWeight,
55
+ height: height,
56
+ );
57
+ }
58
+
59
+ TextStyle bodyLarge({
60
+ Color? color,
61
+ FontWeight? fontWeight,
62
+ double? height,
63
+ }) {
64
+ return _style(
65
+ fontSize: sizes.bodyLarge,
66
+ color: color ?? colors.title,
67
+ fontWeight: fontWeight,
68
+ height: height,
69
+ );
70
+ }
71
+
72
+ TextStyle titleSmall({
73
+ Color? color,
74
+ FontWeight? fontWeight,
75
+ double? height,
76
+ }) {
77
+ return _style(
78
+ fontSize: sizes.titleSmall,
79
+ color: color ?? colors.title,
80
+ fontWeight: fontWeight ?? FontWeight.w600,
81
+ height: height,
82
+ );
83
+ }
84
+
85
+ TextStyle title({
86
+ Color? color,
87
+ FontWeight? fontWeight,
88
+ double? height,
89
+ }) {
90
+ return _style(
91
+ fontSize: sizes.title,
92
+ color: color ?? colors.title,
93
+ fontWeight: fontWeight ?? FontWeight.w600,
94
+ height: height,
95
+ );
96
+ }
97
+
98
+ TextStyle titleLarge({
99
+ Color? color,
100
+ FontWeight? fontWeight,
101
+ double? height,
102
+ }) {
103
+ return _style(
104
+ fontSize: sizes.titleLarge,
105
+ color: color ?? colors.title,
106
+ fontWeight: fontWeight ?? FontWeight.w700,
107
+ height: height,
108
+ );
109
+ }
110
+
111
+ TextStyle headline({
112
+ Color? color,
113
+ FontWeight? fontWeight,
114
+ double? height,
115
+ }) {
116
+ return _style(
117
+ fontSize: sizes.headline,
118
+ color: color ?? colors.title,
119
+ fontWeight: fontWeight ?? FontWeight.w700,
120
+ height: height,
121
+ );
122
+ }
123
+
124
+ TextStyle _style({
125
+ required double fontSize,
126
+ required Color color,
127
+ FontWeight? fontWeight,
128
+ double? height,
129
+ }) {
130
+ // 所有语义样式最终都落到同一个底层构造,避免模板里出现重复 TextStyle 拼装。
131
+ return TextStyle(
132
+ fontSize: fontSize,
133
+ color: color,
134
+ fontWeight: fontWeight,
135
+ height: height,
136
+ fontFamily: fontFamily,
137
+ );
138
+ }
139
+ }
@@ -1,36 +1,96 @@
1
1
  import 'package:flutter/material.dart';
2
2
 
3
+ import 'app_color_config.dart';
4
+ import 'app_text_style_config.dart';
5
+
3
6
  class AppTheme {
7
+ static const AppColorConfig _lightColors = AppColorConfig();
8
+ static const AppTextStyleConfig _lightTextStyles = AppTextStyleConfig(
9
+ colors: _lightColors,
10
+ );
11
+
4
12
  /// 亮色主题(函数级注释)
5
13
  static ThemeData light() {
6
14
  return ThemeData(
7
15
  brightness: Brightness.light,
8
- primaryColor: const Color(0xFF3B82F6),
9
- colorScheme: const ColorScheme.light(
10
- primary: Color(0xFF3B82F6),
11
- secondary: Color(0xFF22C55E),
16
+ primaryColor: _lightColors.primary,
17
+ colorScheme: ColorScheme.light(
18
+ primary: _lightColors.primary,
19
+ secondary: _lightColors.secondary,
20
+ error: _lightColors.error,
21
+ surface: _lightColors.surface,
12
22
  ),
13
- appBarTheme: const AppBarTheme(
23
+ appBarTheme: AppBarTheme(
14
24
  elevation: 0,
15
25
  centerTitle: true,
16
- backgroundColor: Colors.white,
17
- foregroundColor: Colors.black87,
26
+ backgroundColor: _lightColors.surface,
27
+ foregroundColor: _lightColors.title,
28
+ titleTextStyle: _lightTextStyles.title(
29
+ color: _lightColors.title,
30
+ ),
31
+ ),
32
+ scaffoldBackgroundColor: _lightColors.background,
33
+ dividerColor: _lightColors.divider,
34
+ textTheme: TextTheme(
35
+ bodySmall: _lightTextStyles.bodySmall(),
36
+ bodyMedium: _lightTextStyles.body(),
37
+ bodyLarge: _lightTextStyles.bodyLarge(),
38
+ titleSmall: _lightTextStyles.titleSmall(),
39
+ titleMedium: _lightTextStyles.title(),
40
+ titleLarge: _lightTextStyles.titleLarge(),
41
+ headlineSmall: _lightTextStyles.headline(),
42
+ labelSmall: _lightTextStyles.caption(),
18
43
  ),
19
- scaffoldBackgroundColor: const Color(0xFFF8FAFC),
20
44
  );
21
45
  }
22
46
 
23
47
  /// 暗色主题(函数级注释)
24
48
  static ThemeData dark() {
49
+ const darkColors = AppColorConfig(
50
+ primary: Color(0xFF60A5FA),
51
+ secondary: Color(0xFF34D399),
52
+ background: Color(0xFF0F172A),
53
+ surface: Color(0xFF111827),
54
+ title: Color(0xFFF9FAFB),
55
+ titleSecondary: Color(0xFFD1D5DB),
56
+ caption: Color(0xFF9CA3AF),
57
+ divider: Color(0xFF1F2937),
58
+ error: Color(0xFFF87171),
59
+ success: Color(0xFF34D399),
60
+ warning: Color(0xFFFBBF24),
61
+ );
62
+ const darkTextStyles = AppTextStyleConfig(
63
+ colors: darkColors,
64
+ );
65
+
25
66
  return ThemeData(
26
67
  brightness: Brightness.dark,
27
- colorScheme: const ColorScheme.dark(
28
- primary: Color(0xFF60A5FA),
29
- secondary: Color(0xFF34D399),
68
+ colorScheme: ColorScheme.dark(
69
+ primary: darkColors.primary,
70
+ secondary: darkColors.secondary,
71
+ error: darkColors.error,
72
+ surface: darkColors.surface,
30
73
  ),
31
- appBarTheme: const AppBarTheme(
74
+ appBarTheme: AppBarTheme(
32
75
  elevation: 0,
33
76
  centerTitle: true,
77
+ backgroundColor: darkColors.surface,
78
+ foregroundColor: darkColors.title,
79
+ titleTextStyle: darkTextStyles.title(
80
+ color: darkColors.title,
81
+ ),
82
+ ),
83
+ scaffoldBackgroundColor: darkColors.background,
84
+ dividerColor: darkColors.divider,
85
+ textTheme: TextTheme(
86
+ bodySmall: darkTextStyles.bodySmall(),
87
+ bodyMedium: darkTextStyles.body(),
88
+ bodyLarge: darkTextStyles.bodyLarge(),
89
+ titleSmall: darkTextStyles.titleSmall(),
90
+ titleMedium: darkTextStyles.title(),
91
+ titleLarge: darkTextStyles.titleLarge(),
92
+ headlineSmall: darkTextStyles.headline(),
93
+ labelSmall: darkTextStyles.caption(),
34
94
  ),
35
95
  );
36
96
  }
@@ -1,3 +1,6 @@
1
1
  // 导出主题类 (按字母顺序排列)
2
+ export 'app_color_config.dart';
3
+ export 'app_text_size_config.dart';
4
+ export 'app_text_style_config.dart';
2
5
  export 'app_theme.dart';
3
6
  export 'status_views_theme.dart';
@@ -34,7 +34,7 @@ class LoadingUtil {
34
34
  mainAxisSize: MainAxisSize.min,
35
35
  children: [
36
36
  const CircularProgressIndicator(),
37
- if (message != null) ...[
37
+ if (message.isNotEmpty) ...[
38
38
  const SizedBox(height: 16),
39
39
  Text(
40
40
  message,
@@ -1,6 +1,5 @@
1
1
  import 'package:flutter/material.dart';
2
2
  import '{{CORE_IMPORT}}';
3
-
4
3
  {{#if_clean}}
5
4
  import '{{DATA_IMPORT}}';
6
5
  {{else}}
@@ -166,7 +165,7 @@ class ExampleTuItmeImagelessV extends StatelessWidget {
166
165
  body = Container(
167
166
  padding: const EdgeInsets.all(5),
168
167
  decoration: BoxDecoration(
169
- color: Colors.lightBlue.withOpacity(0.1),
168
+ color: Colors.lightBlue.withAlpha(26),
170
169
  borderRadius: BorderRadius.circular(
171
170
  10,
172
171
  ),
@@ -35,10 +35,9 @@ class EgService {
35
35
  };
36
36
  }
37
37
 
38
- final response = await _http.get(
39
- '/feed-app',
40
- queryParameters: queryParameters,
41
- );
38
+ AppHttp.init(adapter: TuChongExampleAdapter());
39
+
40
+ final response = await _http.get('/feed-app', queryParameters: queryParameters);
42
41
 
43
42
  if (response.isSuccess && response.data is List) {
44
43
  return (response.data as List)
@@ -76,3 +75,27 @@ class EgService {
76
75
  return [];
77
76
  }
78
77
  }
78
+
79
+ /// 图集示例专用响应适配器。
80
+ ///
81
+ /// 这个适配器只随 networkGallery 示例生成,不属于默认网络 Core。
82
+ class TuChongExampleAdapter extends AppResponseAdapter {
83
+ @override
84
+ Map<String, dynamic> adapt(dynamic json) {
85
+ if (json is Map) {
86
+ final result = json['result'];
87
+ final isSuccess = result == 'SUCCESS';
88
+
89
+ return {
90
+ 'code': isSuccess ? 200 : -1,
91
+ 'msg': json['message'] ?? '',
92
+ 'data': json['feedList'] ?? json['data'],
93
+ };
94
+ }
95
+ return {
96
+ 'code': AppErrorCode.parseError,
97
+ 'msg': '数据格式错误',
98
+ 'data': null,
99
+ };
100
+ }
101
+ }
@@ -0,0 +1,37 @@
1
+ {{#if_network_example}}
2
+ import '{{CORE_IMPORT}}';
3
+
4
+ class HomeFeedService {
5
+ HomeFeedService({
6
+ AppHttp? http,
7
+ }) : _http = http ?? AppHttp();
8
+
9
+ final AppHttp _http;
10
+
11
+ Future<List<Map<String, dynamic>>> fetchPosts({
12
+ required int page,
13
+ required int pageSize,
14
+ }) async {
15
+ final response = await _http.get<List<Map<String, dynamic>>>(
16
+ '/posts',
17
+ queryParameters: {
18
+ '_page': page,
19
+ '_limit': pageSize,
20
+ },
21
+ showError: false,
22
+ fromJson: (json) {
23
+ final list = json as List;
24
+ return list
25
+ .map((item) => Map<String, dynamic>.from(item as Map))
26
+ .toList();
27
+ },
28
+ );
29
+
30
+ if (response.isSuccess && response.data != null) {
31
+ return response.data!;
32
+ }
33
+
34
+ throw Exception(response.msg);
35
+ }
36
+ }
37
+ {{/if_network_example}}