feedback_create_page.dart 9.1 KB

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