feedback_create_page.dart 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. import 'package:cpt_main/modules/feedback/create/feedback_create_state.dart';
  2. import 'package:cs_resources/generated/l10n.dart';
  3. import 'package:cs_resources/theme/app_colors_theme.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:auto_route/auto_route.dart';
  6. import 'package:flutter_hooks/flutter_hooks.dart';
  7. import 'package:hooks_riverpod/hooks_riverpod.dart';
  8. import 'package:plugin_platform/engine/image/image_nine_grid.dart';
  9. import 'package:router/ext/auto_router_extensions.dart';
  10. import 'package:widgets/ext/ex_widget.dart';
  11. import 'package:widgets/my_appbar.dart';
  12. import 'package:widgets/my_button.dart';
  13. import 'package:widgets/my_text_field.dart';
  14. import 'package:widgets/my_text_view.dart';
  15. import 'package:widgets/shatter/form_require_text.dart';
  16. import 'package:widgets/shatter/picker_container.dart';
  17. import 'package:widgets/widget_export.dart';
  18. import '../../../router/page/main_page_router.dart';
  19. import 'feedback_create_view_model.dart';
  20. @RoutePage()
  21. class FeedbackCreatePage extends HookConsumerWidget {
  22. const FeedbackCreatePage({Key? key}) : super(key: key);
  23. //启动当前页面
  24. static void startInstance({BuildContext? context}) {
  25. if (context != null) {
  26. context.router.push(const FeedbackCreatePageRoute());
  27. } else {
  28. appRouter.push(const FeedbackCreatePageRoute());
  29. }
  30. }
  31. @override
  32. Widget build(BuildContext context, WidgetRef ref) {
  33. final viewModel = ref.watch(feedbackCreateViewModelProvider.notifier);
  34. final state = ref.watch(feedbackCreateViewModelProvider);
  35. final noteCount = useState(0);
  36. return Scaffold(
  37. appBar: MyAppBar.appBar(context, S.current.create_new_feedback),
  38. backgroundColor: context.appColors.whiteBG,
  39. body: SingleChildScrollView(
  40. scrollDirection: Axis.vertical,
  41. physics: const BouncingScrollPhysics(),
  42. child: Container(
  43. margin: const EdgeInsets.symmetric(horizontal: 15),
  44. width: double.infinity,
  45. child: Column(
  46. mainAxisSize: MainAxisSize.max,
  47. crossAxisAlignment: CrossAxisAlignment.start,
  48. children: [
  49. //选择类型
  50. FormRequireText(
  51. text: S.current.full_name,
  52. textColor: context.appColors.textBlack,
  53. fontSize: 17,
  54. ).marginOnly(top: 14.5),
  55. // 选择器
  56. PickerContainer(
  57. content: state.selectedOption ?? "",
  58. hint: S.current.choose_category,
  59. margin: const EdgeInsets.only(top: 16),
  60. onClick: viewModel.pickCategory,
  61. ),
  62. //Title
  63. FormRequireText(
  64. text: S.current.title,
  65. textColor: context.appColors.textBlack,
  66. fontSize: 17,
  67. ).marginOnly(top: 14.5),
  68. // 表单
  69. _buildInputLayout(
  70. context,
  71. state,
  72. "title",
  73. marginTop: 16,
  74. textInputType: TextInputType.text,
  75. textInputAction: TextInputAction.next,
  76. errorText: state.titleErrorText,
  77. onSubmit: (formKey, value) {
  78. state.formData[formKey]!['focusNode'].unfocus();
  79. FocusScope.of(context).requestFocus(state.formData['desc']!['focusNode']);
  80. },
  81. ),
  82. // DESC
  83. MyTextView(
  84. S.current.describe_your_feedback,
  85. textColor: context.appColors.textBlack,
  86. fontSize: 17,
  87. marginTop: 14.5,
  88. isFontMedium: true,
  89. ),
  90. //大文本框
  91. IgnoreKeyboardDismiss(
  92. child: Container(
  93. height: 177,
  94. margin: const EdgeInsets.only(top: 16),
  95. padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15),
  96. decoration: BoxDecoration(
  97. color: context.appColors.authFiledBG,
  98. borderRadius: const BorderRadius.all(Radius.circular(5)),
  99. ),
  100. child: Stack(
  101. children: [
  102. TextField(
  103. cursorColor: context.appColors.authFiledText,
  104. cursorWidth: 1.5,
  105. autofocus: false,
  106. enabled: true,
  107. focusNode: state.formData["desc"]!['focusNode'],
  108. controller: state.formData["desc"]!['controller'],
  109. decoration: InputDecoration(
  110. isDense: true,
  111. isCollapsed: true,
  112. border: InputBorder.none,
  113. hintText: state.formData["desc"]!['hintText'],
  114. hintStyle: TextStyle(
  115. color: context.appColors.authFiledHint,
  116. fontSize: 16.0,
  117. fontWeight: FontWeight.w500,
  118. ),
  119. ),
  120. style: TextStyle(
  121. color: context.appColors.authFiledText,
  122. fontSize: 16.0,
  123. fontWeight: FontWeight.w500,
  124. ),
  125. textInputAction: TextInputAction.done,
  126. onSubmitted: (value) {
  127. FocusScope.of(context).unfocus();
  128. },
  129. maxLines: null,
  130. expands: true,
  131. onChanged: (text) {
  132. // 当文本改变时,更新字符数量
  133. noteCount.value = text.length;
  134. },
  135. ),
  136. Positioned(
  137. bottom: 0.0,
  138. right: 0.0,
  139. child: Text(
  140. S.current.characters(noteCount.value),
  141. style: TextStyle(
  142. color: context.appColors.textBlack,
  143. fontSize: 15.0,
  144. ),
  145. ),
  146. ),
  147. ],
  148. ),
  149. ),
  150. ),
  151. MyTextView(
  152. S.current.upload_pictures,
  153. textColor: context.appColors.textBlack,
  154. fontSize: 17,
  155. marginTop: 14.5,
  156. isFontMedium: true,
  157. ),
  158. MyTextView(
  159. S.current.up_to_max_images,
  160. fontSize: 13,
  161. marginTop: 5,
  162. marginBottom: 14,
  163. isFontRegular: true,
  164. textColor: context.appColors.textDarkGray999,
  165. ),
  166. ImageNineGrid(
  167. isSelectEnable: true,
  168. maxImages: 10,
  169. spacing: 10,
  170. aspectRatio: 108 / 80,
  171. initialImages: state.imgList,
  172. onImagesChanged: (list) {
  173. viewModel.setImgList(list);
  174. },
  175. ),
  176. MyButton(
  177. onPressed: viewModel.submitFeedback,
  178. text: S.current.submit,
  179. textColor: Colors.white,
  180. backgroundColor: context.appColors.btnBgDefault,
  181. fontWeight: FontWeight.w500,
  182. type: ClickType.throttle,
  183. fontSize: 16,
  184. minHeight: 50,
  185. radius: 5,
  186. ).marginOnly(top: 25, bottom: 25),
  187. ],
  188. ),
  189. ),
  190. ),
  191. );
  192. }
  193. /// 输入框
  194. Widget _buildInputLayout(
  195. BuildContext context,
  196. FeedbackCreateState state,
  197. String key, {
  198. double marginTop = 0,
  199. bool? showRightIcon = false, //是否展示右侧的布局
  200. Widget? rightWidget, //右侧的布局
  201. TextInputType textInputType = TextInputType.text,
  202. String? errorText,
  203. bool obscureText = false,
  204. bool enable = true,
  205. TextInputAction textInputAction = TextInputAction.done,
  206. Function? onSubmit,
  207. }) {
  208. return IgnoreKeyboardDismiss(
  209. child: MyTextField(
  210. key,
  211. fillBackgroundColor: context.appColors.authFiledBG,
  212. state.formData[key]!['value'],
  213. hintStyle: TextStyle(
  214. color: context.appColors.authFiledHint,
  215. fontSize: 16.0,
  216. fontWeight: FontWeight.w500,
  217. ),
  218. controller: state.formData[key]!['controller'],
  219. focusNode: state.formData[key]!['focusNode'],
  220. margin: EdgeInsets.only(top: marginTop),
  221. padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
  222. showDivider: false,
  223. height: 44,
  224. enabled: enable,
  225. style: TextStyle(
  226. color: context.appColors.authFiledText,
  227. fontSize: 16.0,
  228. fontWeight: FontWeight.w500,
  229. ),
  230. inputType: textInputType,
  231. textInputAction: textInputAction,
  232. onSubmit: onSubmit,
  233. cursorColor: context.appColors.authFiledText,
  234. obscureText: obscureText,
  235. errorText: errorText,
  236. showLeftIcon: true,
  237. showRightIcon: showRightIcon,
  238. rightWidget: rightWidget,
  239. ),
  240. );
  241. }
  242. }