feedback_create_page.dart 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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.backgroundWhite,
  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.choose_category,
  52. textColor: context.appColors.textBlack,
  53. fontSize: 17,
  54. ).marginOnly(top: 14.5),
  55. // 选择器
  56. PickerContainer(
  57. content: state.selectedOption?.name ?? "",
  58. hint: S.current.choose_an_option,
  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. onSubmit: (formKey, value) {
  77. state.formData[formKey]!['focusNode'].unfocus();
  78. FocusScope.of(context).requestFocus(state.formData['desc']!['focusNode']);
  79. },
  80. ),
  81. // DESC
  82. FormRequireText(
  83. text: S.current.describe_your_feedback,
  84. textColor: context.appColors.textBlack,
  85. fontSize: 17,
  86. ).marginOnly(top: 14.5),
  87. //大文本框
  88. IgnoreKeyboardDismiss(
  89. child: Container(
  90. height: 177,
  91. margin: const EdgeInsets.only(top: 16),
  92. padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15),
  93. decoration: BoxDecoration(
  94. color: context.appColors.authFiledBG,
  95. borderRadius: const BorderRadius.all(Radius.circular(5)),
  96. ),
  97. child: Stack(
  98. children: [
  99. TextField(
  100. cursorColor: context.appColors.authFiledText,
  101. cursorWidth: 1.5,
  102. autofocus: false,
  103. enabled: true,
  104. focusNode: state.formData["desc"]!['focusNode'],
  105. controller: state.formData["desc"]!['controller'],
  106. decoration: InputDecoration(
  107. isDense: true,
  108. isCollapsed: true,
  109. border: InputBorder.none,
  110. hintText: state.formData["desc"]!['hintText'],
  111. hintStyle: TextStyle(
  112. color: context.appColors.authFiledHint,
  113. fontSize: 16.0,
  114. fontWeight: FontWeight.w500,
  115. ),
  116. ),
  117. style: TextStyle(
  118. color: context.appColors.authFiledText,
  119. fontSize: 16.0,
  120. fontWeight: FontWeight.w500,
  121. ),
  122. textInputAction: TextInputAction.done,
  123. onSubmitted: (value) {
  124. FocusScope.of(context).unfocus();
  125. },
  126. maxLines: null,
  127. expands: true,
  128. onChanged: (text) {
  129. // 当文本改变时,更新字符数量
  130. noteCount.value = text.length;
  131. },
  132. ),
  133. Positioned(
  134. bottom: 0.0,
  135. right: 0.0,
  136. child: Text(
  137. S.current.characters(noteCount.value),
  138. style: TextStyle(
  139. color: context.appColors.textBlack,
  140. fontSize: 15.0,
  141. ),
  142. ),
  143. ),
  144. ],
  145. ),
  146. ),
  147. ),
  148. MyTextView(
  149. S.current.upload_pictures,
  150. textColor: context.appColors.textBlack,
  151. fontSize: 17,
  152. marginTop: 14.5,
  153. isFontMedium: true,
  154. ),
  155. MyTextView(
  156. S.current.up_to_max_images,
  157. fontSize: 13,
  158. marginTop: 5,
  159. marginBottom: 14,
  160. isFontRegular: true,
  161. textColor: context.appColors.textDarkGray999,
  162. ),
  163. ImageNineGrid(
  164. isSelectEnable: true,
  165. maxImages: 10,
  166. spacing: 10,
  167. aspectRatio: 108 / 80,
  168. initialImages: state.imgList,
  169. onImagesChanged: (list) {
  170. viewModel.setImgList(list);
  171. },
  172. ),
  173. MyButton(
  174. onPressed: viewModel.submitFeedback,
  175. text: S.current.submit,
  176. textColor: Colors.white,
  177. backgroundColor: context.appColors.btnBgDefault,
  178. fontWeight: FontWeight.w500,
  179. type: ClickType.throttle,
  180. fontSize: 16,
  181. minHeight: 50,
  182. radius: 5,
  183. ).marginOnly(top: 25, bottom: 25),
  184. ],
  185. ),
  186. ),
  187. ),
  188. );
  189. }
  190. /// 输入框
  191. Widget _buildInputLayout(
  192. BuildContext context,
  193. FeedbackCreateState state,
  194. String key, {
  195. double marginTop = 0,
  196. bool? showRightIcon = false, //是否展示右侧的布局
  197. Widget? rightWidget, //右侧的布局
  198. TextInputType textInputType = TextInputType.text,
  199. String? errorText,
  200. bool obscureText = false,
  201. bool enable = true,
  202. TextInputAction textInputAction = TextInputAction.done,
  203. Function? onSubmit,
  204. }) {
  205. return IgnoreKeyboardDismiss(
  206. child: MyTextField(
  207. key,
  208. fillBackgroundColor: context.appColors.authFiledBG,
  209. state.formData[key]!['value'],
  210. hintStyle: TextStyle(
  211. color: context.appColors.authFiledHint,
  212. fontSize: 16.0,
  213. fontWeight: FontWeight.w500,
  214. ),
  215. controller: state.formData[key]!['controller'],
  216. focusNode: state.formData[key]!['focusNode'],
  217. margin: EdgeInsets.only(top: marginTop),
  218. padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
  219. showDivider: false,
  220. height: 44,
  221. enabled: enable,
  222. style: TextStyle(
  223. color: context.appColors.authFiledText,
  224. fontSize: 16.0,
  225. fontWeight: FontWeight.w500,
  226. ),
  227. inputType: textInputType,
  228. textInputAction: textInputAction,
  229. onSubmit: onSubmit,
  230. cursorColor: context.appColors.authFiledText,
  231. obscureText: obscureText,
  232. errorText: errorText,
  233. showLeftIcon: true,
  234. showRightIcon: showRightIcon,
  235. rightWidget: rightWidget,
  236. ),
  237. );
  238. }
  239. }