Przeglądaj źródła

在线表单的详情与复显

liukai 3 miesięcy temu
rodzic
commit
5a8826c34d
53 zmienionych plików z 2012 dodań i 712 usunięć
  1. 1 1
      app/lib/main.dart
  2. 1 1
      packages/cpt_auth/lib/modules/auth_login/auth_login_page.dart
  3. 20 12
      packages/cpt_form/lib/modules/apply/attachment_page.dart
  4. 138 93
      packages/cpt_form/lib/modules/apply/form_payment_page.dart
  5. 33 8
      packages/cpt_form/lib/modules/apply/form_terms_page.dart
  6. 68 24
      packages/cpt_form/lib/modules/apply/guest_vehicle_page.dart
  7. 24 14
      packages/cpt_form/lib/modules/apply/large_text_box_page.dart
  8. 44 13
      packages/cpt_form/lib/modules/apply/moving_company_page.dart
  9. 55 30
      packages/cpt_form/lib/modules/apply/moving_date_page.dart
  10. 23 12
      packages/cpt_form/lib/modules/apply/note_management_page.dart
  11. 44 14
      packages/cpt_form/lib/modules/apply/renovation_company_page.dart
  12. 61 33
      packages/cpt_form/lib/modules/apply/renovation_date_page.dart
  13. 75 34
      packages/cpt_form/lib/modules/apply/signature_page.dart
  14. 21 3
      packages/cpt_form/lib/modules/apply/type_of_application_page.dart
  15. 87 55
      packages/cpt_form/lib/modules/apply/vehicle_info_page.dart
  16. 31 8
      packages/cpt_form/lib/modules/apply/vm/apply_state.dart
  17. 114 11
      packages/cpt_form/lib/modules/apply/vm/apply_view_model.dart
  18. 1 1
      packages/cpt_form/lib/modules/apply/vm/apply_view_model.g.dart
  19. 38 22
      packages/cpt_form/lib/modules/detail/detail_approved_fragment.dart
  20. 20 4
      packages/cpt_form/lib/modules/detail/detail_not_approved_fragment.dart
  21. 23 7
      packages/cpt_form/lib/modules/detail/detail_processing_fragment.dart
  22. 13 7
      packages/cpt_form/lib/modules/detail/form_detail_page.dart
  23. 16 0
      packages/cpt_form/lib/modules/detail/form_detail_state.dart
  24. 22 9
      packages/cpt_form/lib/modules/detail/form_detail_view_model.dart
  25. 1 1
      packages/cpt_form/lib/modules/detail/form_detail_view_model.g.dart
  26. 6 1
      packages/cpt_form/lib/modules/form/apply/form_apply_screen.dart
  27. 1 1
      packages/cpt_form/lib/modules/form/apply/form_apply_view_model.g.dart
  28. 7 4
      packages/cpt_form/lib/modules/form/approve/form_approve_screen.dart
  29. 1 1
      packages/cpt_form/lib/modules/form/approve/form_approve_view_model.g.dart
  30. 191 189
      packages/cpt_form/lib/modules/form/form_types.dart
  31. 7 1
      packages/cpt_form/lib/modules/form/not_approve/form_not_approve_screen.dart
  32. 1 1
      packages/cpt_form/lib/modules/form/not_approve/form_not_approve_view_model.g.dart
  33. 7 1
      packages/cpt_form/lib/modules/form/submit/form_submit_screen.dart
  34. 1 1
      packages/cpt_form/lib/modules/form/submit/form_submit_view_model.g.dart
  35. 3 2
      packages/cpt_form/lib/router/page/form_page_router.dart
  36. 42 14
      packages/cpt_form/lib/router/page/form_page_router.gr.dart
  37. 1 1
      packages/cpt_main/lib/modules/feedback/create_success/feedback_create_success_page.dart
  38. 5 1
      packages/cpt_main/lib/router/component/main_component_service_impl.dart
  39. 9 0
      packages/cs_domain/lib/constants/api_constants.dart
  40. 164 0
      packages/cs_domain/lib/entity/form_content_entity.dart
  41. 31 0
      packages/cs_domain/lib/entity/form_detail_entity.dart
  42. 2 1
      packages/cs_domain/lib/entity/form_list_entity.dart
  43. 23 0
      packages/cs_domain/lib/entity/form_option_entity.dart
  44. 2 21
      packages/cs_domain/lib/entity/form_submitted_entity.dart
  45. 15 4
      packages/cs_domain/lib/generated/json/base/json_convert_content.dart
  46. 204 0
      packages/cs_domain/lib/generated/json/form_content_entity.g.dart
  47. 70 0
      packages/cs_domain/lib/generated/json/form_detail_entity.g.dart
  48. 9 2
      packages/cs_domain/lib/generated/json/form_list_entity.g.dart
  49. 35 0
      packages/cs_domain/lib/generated/json/form_option_entity.g.dart
  50. 4 40
      packages/cs_domain/lib/generated/json/form_submitted_entity.g.dart
  51. 189 0
      packages/cs_domain/lib/repository/form_repository.dart
  52. 1 1
      packages/cs_router/lib/componentRouter/main_service.dart
  53. 7 8
      packages/cs_widgets/lib/my_button.dart

+ 1 - 1
app/lib/main.dart

@@ -42,7 +42,7 @@ void main() async {
   await AppInitializer.initializeRunalone();
 
   //组件路由的注入
-  final serviceManager = ComponentServiceManager()
+  ComponentServiceManager()
     ..addServiceProvider(mainServiceProvider)
     ..addServiceProvider(authServiceProvider)
     ..addServiceProvider(appServiceProvider)

+ 1 - 1
packages/cpt_auth/lib/modules/auth_login/auth_login_page.dart

@@ -121,7 +121,7 @@ class AuthLoginPage extends HookConsumerWidget {
               MyButton(
                 onPressed: viewModel.doLogin,
                 text: S.current.login,
-                isEnabled: state.isLoginBtnEnable,
+                enable: state.isLoginBtnEnable,
                 textColor: Colors.white,
                 disabledTextColor: Colors.white,
                 backgroundColor: context.appColors.btnBgDefault,

+ 20 - 12
packages/cpt_form/lib/modules/apply/attachment_page.dart

@@ -1,4 +1,3 @@
-
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
@@ -6,6 +5,7 @@ import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:plugin_platform/engine/image/image_nine_grid.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
@@ -30,7 +30,6 @@ class AttachmentPage extends HookConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-
     final viewModel = ref.watch(applyViewModelProvider.notifier);
     final state = ref.watch(applyViewModelProvider);
 
@@ -44,7 +43,7 @@ class AttachmentPage extends HookConsumerWidget {
 
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -70,7 +69,7 @@ class AttachmentPage extends HookConsumerWidget {
 
                         //Note to Management 的文本
                         MyTextView(
-                          state.applyDetail?['detail_data']['attachment_txt'],
+                          state.detailPage?['detail_data']['attachment_txt'],
                           fontSize: 15,
                           marginBottom: 14,
                           isFontRegular: true,
@@ -83,13 +82,11 @@ class AttachmentPage extends HookConsumerWidget {
                           maxImages: 10,
                           spacing: 10,
                           aspectRatio: 108 / 80,
-                          initialImages: const [
-                            "https://img1.baidu.com/it/u=2931243091,718249849&fm=253&fmt=auto&app=120&f=JPEG?w=569&h=427",
-                            "https://inews.gtimg.com/om_bt/OVx3YS2XJc1zbndGTkjPKW9J0W7kN8M0SIidT-3K4mb2YAA/641",
-                            "https://inews.gtimg.com/om_bt/OAVMydtx9BsJxf5i_thi4Oll9sR1px-Esmtv6UHSxoisEAA/641"
-                          ],
+                          initialImages: state.formContentDetail.attachments ?? [],
                           onImagesChanged: (list) {
-
+                            viewModel.updateFormContentDetail((content) {
+                              content.attachments = list;
+                            });
                           },
                         ),
                       ],
@@ -99,7 +96,19 @@ class AttachmentPage extends HookConsumerWidget {
 
                 //底部按钮
                 MyButton(
-                  onPressed: viewModel.gotoNextPage,
+                  onPressed: () {
+
+                    if (state.enableEdit){
+                      final attachments = state.formContentDetail.attachments;
+
+                      if (attachments == null || attachments.isEmpty) {
+                        ToastEngine.show("Select attachments");
+                        return;
+                      }
+                    }
+
+                    viewModel.gotoNextPage();
+                  },
                   text: S.current.next,
                   textColor: Colors.white,
                   backgroundColor: context.appColors.btnBgDefault,
@@ -116,5 +125,4 @@ class AttachmentPage extends HookConsumerWidget {
           return true;
         });
   }
-
 }

+ 138 - 93
packages/cpt_form/lib/modules/apply/form_payment_page.dart

@@ -1,3 +1,6 @@
+import 'dart:typed_data';
+import 'dart:ui';
+
 import 'package:cpt_form/modules/form/apply/form_apply_screen.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/generated/l10n.dart';
@@ -6,8 +9,11 @@ import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_basic/provider/user_config/user_config_service.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/componentRouter/component_service_manager.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/date_time_utils.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
@@ -36,16 +42,17 @@ class FormPaymentPage extends HookConsumerWidget {
     final state = ref.watch(applyViewModelProvider);
 
     //签名版配置
-    HandSignatureControl handSignatureControl = HandSignatureControl(
-      threshold: 3.0,
-      smoothRatio: 190 / 345,
-      velocityRange: 2.0,
-    );
+    final HandSignatureControl handSignatureControl = useMemoized(() {
+      return HandSignatureControl(
+        threshold: 3.0,
+        smoothRatio: 190 / 345,
+        velocityRange: 2.0,
+      );
+    });
 
     useEffect(() {
       //赋值State的值
       Future.microtask(() {});
-
       return () {
         // 释放控制器资源
       };
@@ -53,7 +60,7 @@ class FormPaymentPage extends HookConsumerWidget {
 
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -68,96 +75,114 @@ class FormPaymentPage extends HookConsumerWidget {
                       crossAxisAlignment: CrossAxisAlignment.start,
                       children: [
                         //支付
-                        Row(
-                          children: [
-                            const MyAssetImage(Assets.paymentInfoDetails, width: 27, height: 27),
-                            MyTextView(
-                              S.current.payment,
-                              textColor: context.appColors.textBlack,
-                              fontSize: 17,
-                              marginLeft: 14,
-                              isFontMedium: true,
-                            ).expanded(),
-                          ],
-                        ).marginOnly(top: 15, left: 15, right: 15),
+                        Visibility(
+                          visible: state.formItem != null && state.formItem!.price > 0,
+                          child: Row(
+                            children: [
+                              const MyAssetImage(Assets.paymentInfoDetails, width: 27, height: 27),
+                              MyTextView(
+                                S.current.payment,
+                                textColor: context.appColors.textBlack,
+                                fontSize: 17,
+                                marginLeft: 14,
+                                isFontMedium: true,
+                              ).expanded(),
+                            ],
+                          ).marginOnly(top: 15, left: 15, right: 15),
+                        ),
 
-                        //金额
-                        Row(
-                          mainAxisSize: MainAxisSize.max,
-                          children: [
-                            MyTextView(
-                              S.current.fee,
-                              textColor: context.appColors.textBlack,
-                              fontSize: 18,
-                              isFontRegular: true,
-                            ),
-                            const Spacer(),
-                            MyTextView(
-                              "SGD",
-                              textColor: context.appColors.textBlack,
-                              fontSize: 18,
-                              isFontRegular: true,
-                            ),
-                            MyTextView(
-                              "\$21.80",
-                              textColor: context.appColors.textPrimary,
-                              fontSize: 22,
-                              marginLeft: 8,
-                              isFontMedium: true,
-                            ),
-                          ],
-                        ).marginOnly(top: 20, left: 15, right: 15, bottom: 20),
+                        //支付金额
+                        Visibility(
+                          visible: state.formItem != null && state.formItem!.price > 0,
+                          child: Row(
+                            mainAxisSize: MainAxisSize.max,
+                            children: [
+                              MyTextView(
+                                S.current.fee,
+                                textColor: context.appColors.textBlack,
+                                fontSize: 18,
+                                isFontRegular: true,
+                              ),
+                              const Spacer(),
+                              MyTextView(
+                                "SGD",
+                                textColor: context.appColors.textBlack,
+                                fontSize: 18,
+                                isFontRegular: true,
+                              ),
+                              MyTextView(
+                                "\$${state.formItem?.price ?? 0}",
+                                textColor: context.appColors.textPrimary,
+                                fontSize: 22,
+                                marginLeft: 8,
+                                isFontMedium: true,
+                              ),
+                            ],
+                          ).marginOnly(top: 20, left: 15, right: 15, bottom: 20),
+                        ),
 
                         //分割线
-                        Divider(
-                          color: context.appColors.dividerDefault,
-                          height: 0.5,
+                        Visibility(
+                          visible: state.formItem != null && state.formItem!.price > 0,
+                          child: Divider(
+                            color: context.appColors.dividerDefault,
+                            height: 0.5,
+                          ),
                         ),
 
                         //押金
-                        Row(
-                          children: [
-                            const MyAssetImage(Assets.paymentInfoDetails, width: 27, height: 27),
-                            MyTextView(
-                              S.current.deposit,
-                              textColor: context.appColors.textBlack,
-                              fontSize: 17,
-                              marginLeft: 14,
-                              isFontMedium: true,
-                            ).expanded(),
-                          ],
-                        ).marginOnly(top: 15, left: 15, right: 15),
+                        Visibility(
+                          visible: state.formItem != null && state.formItem!.deposit > 0,
+                          child: Row(
+                            children: [
+                              const MyAssetImage(Assets.paymentInfoDetails, width: 27, height: 27),
+                              MyTextView(
+                                S.current.deposit,
+                                textColor: context.appColors.textBlack,
+                                fontSize: 17,
+                                marginLeft: 14,
+                                isFontMedium: true,
+                              ).expanded(),
+                            ],
+                          ).marginOnly(top: 15, left: 15, right: 15),
+                        ),
 
                         //押金金额
-                        Row(
-                          children: [
-                            MyTextView(
-                              S.current.deposit_hold,
-                              textColor: context.appColors.textBlack,
-                              fontSize: 18,
-                              isFontRegular: true,
-                            ),
-                            const Spacer(),
-                            MyTextView(
-                              "SGD",
-                              textColor: context.appColors.textBlack,
-                              fontSize: 18,
-                              isFontRegular: true,
-                            ),
-                            MyTextView(
-                              "\$1000.00",
-                              textColor: context.appColors.textPrimary,
-                              fontSize: 22,
-                              marginLeft: 8,
-                              isFontMedium: true,
-                            ),
-                          ],
-                        ).marginOnly(top: 20, left: 15, right: 15, bottom: 20),
+                        Visibility(
+                          visible: state.formItem != null && state.formItem!.deposit > 0,
+                          child: Row(
+                            children: [
+                              MyTextView(
+                                S.current.deposit_hold,
+                                textColor: context.appColors.textBlack,
+                                fontSize: 18,
+                                isFontRegular: true,
+                              ),
+                              const Spacer(),
+                              MyTextView(
+                                "SGD",
+                                textColor: context.appColors.textBlack,
+                                fontSize: 18,
+                                isFontRegular: true,
+                              ),
+                              MyTextView(
+                                "\$${state.formItem?.deposit ?? 0}",
+                                textColor: context.appColors.textPrimary,
+                                fontSize: 22,
+                                marginLeft: 8,
+                                isFontMedium: true,
+                              ),
+                            ],
+                          ).marginOnly(top: 20, left: 15, right: 15, bottom: 20),
+                        ),
 
                         //分割线
-                        Divider(
-                          color: context.appColors.dividerDefault,
-                          height: 0.5,
+                        Visibility(
+                          visible: state.formItem != null && state.formItem!.deposit > 0,
+                          child: Divider(
+                            color: context.appColors.dividerDefault,
+                            height: 0.5,
+                          ),
                         ),
 
                         //银行卡
@@ -190,7 +215,7 @@ class FormPaymentPage extends HookConsumerWidget {
 
                         //签名的说明文本
                         MyTextView(
-                          state.applyDetail?['detail_data']['signature_txt'],
+                          state.detailPage?['detail_data']['signature_txt'],
                           fontSize: 15,
                           marginTop: 18,
                           marginLeft: 15,
@@ -202,7 +227,8 @@ class FormPaymentPage extends HookConsumerWidget {
 
                         //签名框
                         Center(
-                          child: GestureDetector(  //处理手势冲突,手指在签名版上的时候不滑动父布局
+                          child: GestureDetector(
+                              //处理手势冲突,手指在签名版上的时候不滑动父布局
                               behavior: HitTestBehavior.opaque,
                               onVerticalDragUpdate: (_) {},
                               child: Stack(
@@ -258,11 +284,11 @@ class FormPaymentPage extends HookConsumerWidget {
                                 text: S.current.signed_and_agreed_by,
                               ),
                               TextSpan(
-                                text: " Wu Bing Bing ",
+                                text: " ${UserConfigService.getState().userName ?? "-"} \n",
                                 style: TextStyle(color: context.appColors.textPrimary),
                               ),
                               TextSpan(
-                                text: " 21 Nov 2024, 03:08 PM",
+                                text: DateTimeUtils.formatNowDateStr(format: 'dd MMM yyyy HH:mm'),
                               ),
                             ],
                           ),
@@ -274,8 +300,27 @@ class FormPaymentPage extends HookConsumerWidget {
 
                 //底部按钮
                 MyButton(
-                  onPressed: () {
-                    viewModel.gotoNextPage();
+                  onPressed: () async{
+                    final isFilled = handSignatureControl.isFilled;
+                    if (!isFilled) {
+                      ToastEngine.show("Please sign first");
+                      return;
+                    }
+
+                    var byteData = await handSignatureControl.toImage(
+                      format: ImageByteFormat.png,
+                      border: 0,
+                      width: 345,
+                      height: 190,
+                      background: Colors.white,
+                    ) as ByteData;
+
+                    //存入本表单数据
+                    viewModel.updateFormContentDetail((content) {
+                      content.signatureByteData = byteData;
+                    });
+
+                    viewModel.submitForm();
                   },
                   text: S.current.next,
                   textColor: Colors.white,

+ 33 - 8
packages/cpt_form/lib/modules/apply/form_terms_page.dart

@@ -1,5 +1,7 @@
 import 'package:cpt_form/modules/apply/vm/apply_view_model.dart';
 import 'package:cs_resources/generated/l10n.dart';
+import 'package:domain/entity/form_content_entity.dart';
+import 'package:domain/entity/form_list_entity.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
@@ -12,15 +14,38 @@ import '../../router/page/form_page_router.dart';
 @RoutePage()
 class FormTermsPage extends HookConsumerWidget {
   final String type;
+  final String? estateFormId;
+  final FormListEntity? formItem;
+  final bool enableEdit;
+  final FormContentEntity? formContent;
 
-  const FormTermsPage({Key? key, @PathParam() required this.type}) : super(key: key);
+  const FormTermsPage({Key? key, required this.type, this.estateFormId, this.formItem, required this.enableEdit, this.formContent}) : super(key: key);
 
   //启动当前页面
-  static void startInstance({BuildContext? context, required String formType}) {
+  static void startInstance({
+    BuildContext? context,
+    required String formType,
+    String? estateFormId,
+    FormListEntity? formItem,
+    required bool enableEdit,
+    FormContentEntity? formContent,
+  }) {
     if (context != null) {
-      context.router.push(FormTermsPageRoute(type: formType));
+      context.router.push(FormTermsPageRoute(
+        type: formType,
+        formItem: formItem,
+        enableEdit: enableEdit,
+        formContent: formContent,
+        estateFormId: estateFormId,
+      ));
     } else {
-      appRouter.push(FormTermsPageRoute(type: formType));
+      appRouter.push(FormTermsPageRoute(
+        type: formType,
+        formItem: formItem,
+        enableEdit: enableEdit,
+        formContent: formContent,
+        estateFormId: estateFormId,
+      ));
     }
   }
 
@@ -31,17 +56,17 @@ class FormTermsPage extends HookConsumerWidget {
 
     useEffect(() {
       // 组件挂载时执行 - 执行接口请求
-      Future.microtask(() => viewModel.setFormType(type));
+      Future.microtask(() => viewModel.setFormType(type, estateFormId, formItem, enableEdit, formContent));
       return () {
         // 组件卸载时执行
       };
     }, []);
 
-    return state.applyDetail != null
+    return state.detailPage != null
         ? WebViewPage(
             showAppbar: true,
-            initialUrl: state.applyDetail?['term_url'],
-            arguments: {'title': state.applyDetail?['title']},
+            initialUrl: state.detailPage?['term_url'],
+            arguments: {'title': state.detailPage?['title']},
             bottomBtnTxt: S.current.next,
             bottomBtnAction: viewModel.gotoNextPage,
           )

+ 68 - 24
packages/cpt_form/lib/modules/apply/guest_vehicle_page.dart

@@ -6,6 +6,8 @@ import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
@@ -47,24 +49,19 @@ class GuestVehiclePage extends HookConsumerWidget {
 
     useEffect(() {
       //赋值State的值
-      Future.microtask(() {});
+      Future.microtask(() {
+        vehicleNumController.text = state.formContentDetail.vehicleNumber ?? "";
+        vehicleInfoController.text = state.formContentDetail.vehicleMakeModelColour ?? "";
+        guestNameController.text = state.formContentDetail.guestName ?? "";
+        guestPhoneController.text = state.formContentDetail.guestMobileNumber ?? "";
+      });
 
-      return () {
-        // 释放控制器资源
-        vehicleNumController.dispose();
-        vehicleInfoController.dispose();
-        guestNameController.dispose();
-        guestPhoneController.dispose();
-        vehicleNumFocusNode.dispose();
-        vehicleInfoFocusNode.dispose();
-        guestNameFocusNode.dispose();
-        guestPhoneFocusNode.dispose();
-      };
+      return () {};
     }, []);
 
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -79,21 +76,22 @@ class GuestVehiclePage extends HookConsumerWidget {
                       crossAxisAlignment: CrossAxisAlignment.start,
                       children: [
                         //下拉选 - 访问时间
-                        MyTextView(
-                          S.current.date_of_entry,
-                          fontSize: 17,
-                          marginTop: 30,
-                          marginLeft: 15,
-                          marginBottom: 16,
-                          isFontMedium: true,
+                        FormRequireText(
+                          text: S.current.date_of_entry,
                           textColor: context.appColors.textBlack,
-                        ),
+                          fontSize: 17,
+                          fontWeight: FontWeight.w500,
+                        ).marginOnly(top: 30, bottom: 16, left: 15, right: 15),
 
                         PickerContainer(
                           hint: S.current.choose_date,
+                          enable: state.enableEdit,
+                          content: state.formContentDetail.dateOfEntry,
                           onClick: () {
                             viewModel.pickDate(null, (date) {
-                              ToastEngine.show("选择的日期:$date");
+                              viewModel.updateFormContentDetail((content) {
+                                content.dateOfEntry = DateTimeUtils.formatDate(date, format: 'yyyy-MM-dd');
+                              });
                             });
                           },
                         ).marginOnly(left: 15, right: 15),
@@ -110,6 +108,7 @@ class GuestVehiclePage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "vehicle_num",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.text,
                           textInputAction: TextInputAction.next,
                           controller: vehicleNumController,
@@ -132,6 +131,7 @@ class GuestVehiclePage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "vehicle_info",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.text,
                           textInputAction: TextInputAction.next,
                           controller: vehicleInfoController,
@@ -154,6 +154,7 @@ class GuestVehiclePage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "guest_name",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.text,
                           textInputAction: TextInputAction.next,
                           controller: guestNameController,
@@ -176,6 +177,7 @@ class GuestVehiclePage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "guest_phone",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.phone,
                           textInputAction: TextInputAction.done,
                           controller: guestPhoneController,
@@ -184,7 +186,6 @@ class GuestVehiclePage extends HookConsumerWidget {
                             guestPhoneFocusNode.unfocus();
                           },
                         ),
-
                       ],
                     ),
                   ),
@@ -198,6 +199,49 @@ class GuestVehiclePage extends HookConsumerWidget {
                     guestNameFocusNode.unfocus();
                     guestPhoneFocusNode.unfocus();
 
+                    if (state.enableEdit) {
+                      String? vehicleNumber = vehicleNumController.text;
+                      String? vehicleMakeModelColour = vehicleInfoController.text;
+                      String? guestName = guestNameController.text;
+                      String? guestMobileNumber = guestPhoneController.text;
+
+                      //校验数据
+                      final dateOfEntry = state.formContentDetail.dateOfEntry;
+
+                      if (Utils.isEmpty(dateOfEntry)) {
+                        ToastEngine.show("Select date of entry");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(vehicleNumber)) {
+                        ToastEngine.show("Enter vehicle number");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(vehicleMakeModelColour)) {
+                        ToastEngine.show("Enter vehicle make/model/ colour");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(guestName)) {
+                        ToastEngine.show("Enter guest name");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(guestMobileNumber)) {
+                        ToastEngine.show("Enter guest mobile number");
+                        return;
+                      }
+
+                      //存入本表单数据
+                      viewModel.updateFormContentDetail((content) {
+                        content.vehicleNumber = vehicleNumber;
+                        content.vehicleMakeModelColour = vehicleMakeModelColour;
+                        content.guestName = guestName;
+                        content.guestMobileNumber = guestMobileNumber;
+                      });
+                    }
+
                     viewModel.gotoNextPage();
                   },
                   text: S.current.next,
@@ -226,7 +270,7 @@ class GuestVehiclePage extends HookConsumerWidget {
     TextInputType textInputType = TextInputType.text,
     String? errorText,
     bool obscureText = false,
-    required TextEditingController controller,
+    required TextEditingController? controller,
     required FocusNode focusNode,
     bool enable = true,
     TextInputAction textInputAction = TextInputAction.done,

+ 24 - 14
packages/cpt_form/lib/modules/apply/large_text_box_page.dart

@@ -1,11 +1,12 @@
-
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
@@ -13,6 +14,7 @@ import 'package:widgets/my_text_view.dart';
 import 'package:widgets/widget_export.dart';
 import '../../router/page/form_page_router.dart';
 import 'vm/apply_view_model.dart';
+
 @RoutePage()
 class LargeTextBoxPage extends HookConsumerWidget {
   const LargeTextBoxPage({Key? key}) : super(key: key);
@@ -37,19 +39,16 @@ class LargeTextBoxPage extends HookConsumerWidget {
 
     useEffect(() {
       //赋值State的值
-      Future.microtask(() {});
+      Future.microtask(() {
+        textEditingController.text = state.formContentDetail.listOfRenovationWorks ?? "";
+      });
 
-      return () {
-        // 释放控制器资源
-        textEditingController.dispose();
-        focusNode.dispose();
-      };
+      return () {};
     }, []);
 
-
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -65,7 +64,7 @@ class LargeTextBoxPage extends HookConsumerWidget {
                       crossAxisAlignment: CrossAxisAlignment.start,
                       children: [
                         MyTextView(
-                          state.applyDetail?['detail_data']['large_txt'],
+                          state.detailPage?['detail_data']['large_txt'],
                           fontSize: 17,
                           marginTop: 30,
                           marginBottom: 17,
@@ -86,7 +85,7 @@ class LargeTextBoxPage extends HookConsumerWidget {
                               cursorColor: context.appColors.authFiledText,
                               cursorWidth: 1.5,
                               autofocus: false,
-                              enabled: true,
+                              enabled: state.enableEdit,
                               focusNode: focusNode,
                               controller: textEditingController,
                               decoration: InputDecoration(
@@ -113,7 +112,6 @@ class LargeTextBoxPage extends HookConsumerWidget {
                               expands: true,
                               onChanged: (text) {
                                 // 当文本改变时
-
                               },
                             ),
                           ),
@@ -125,9 +123,21 @@ class LargeTextBoxPage extends HookConsumerWidget {
 
                 //底部按钮
                 MyButton(
-                  onPressed: (){
+                  onPressed: () {
                     focusNode.unfocus();
 
+                    if (state.enableEdit) {
+                      String? listOfRenovationWorks = textEditingController.text;
+                      if (Utils.isEmpty(listOfRenovationWorks)) {
+                        ToastEngine.show("Enter List Of Renovation Works");
+                        return;
+                      }
+
+                      viewModel.updateFormContentDetail((content) {
+                        content.listOfRenovationWorks = listOfRenovationWorks;
+                      });
+                    }
+
                     viewModel.gotoNextPage();
                   },
                   text: S.current.next,
@@ -146,4 +156,4 @@ class LargeTextBoxPage extends HookConsumerWidget {
           return true;
         });
   }
-}
+}

+ 44 - 13
packages/cpt_form/lib/modules/apply/moving_company_page.dart

@@ -4,7 +4,9 @@ import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
@@ -45,26 +47,22 @@ class MovingCompanyPage extends HookConsumerWidget {
     final addressFocusNode = useFocusNode();
 
     useEffect(() {
-
       //赋值State的值
-      Future.microtask(() {});
+      Future.microtask(() {
+        companyController.text = state.formContentDetail.movingCompany ?? "";
+        contactController.text = state.formContentDetail.personInCharge ?? "";
+        phoneController.text = state.formContentDetail.mobileNumber ?? "";
+        addressController.text = state.formContentDetail.companyAddress ?? "";
+      });
 
       return () {
         // 释放控制器资源
-        companyController.dispose();
-        contactController.dispose();
-        phoneController.dispose();
-        addressController.dispose();
-        companyFocusNode.dispose();
-        contactFocusNode.dispose();
-        phoneFocusNode.dispose();
-        addressFocusNode.dispose();
       };
     }, []);
 
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -90,6 +88,7 @@ class MovingCompanyPage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "company",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.text,
                           textInputAction: TextInputAction.next,
                           controller: companyController,
@@ -112,6 +111,7 @@ class MovingCompanyPage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "contact",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.text,
                           textInputAction: TextInputAction.next,
                           controller: contactController,
@@ -134,6 +134,7 @@ class MovingCompanyPage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "phone",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.phone,
                           textInputAction: TextInputAction.next,
                           controller: phoneController,
@@ -170,7 +171,7 @@ class MovingCompanyPage extends HookConsumerWidget {
                               cursorColor: context.appColors.authFiledText,
                               cursorWidth: 1.5,
                               autofocus: false,
-                              enabled: true,
+                              enabled: state.enableEdit,
                               focusNode: addressFocusNode,
                               controller: addressController,
                               decoration: InputDecoration(
@@ -207,12 +208,42 @@ class MovingCompanyPage extends HookConsumerWidget {
 
                 //底部按钮
                 MyButton(
-                  onPressed: (){
+                  onPressed: () {
                     companyFocusNode.unfocus();
                     contactFocusNode.unfocus();
                     phoneFocusNode.unfocus();
                     addressFocusNode.unfocus();
 
+                    if (state.enableEdit) {
+                      String? movingCompany = companyController.text;
+                      String? personInCharge = contactController.text;
+                      String? mobileNumber = phoneController.text;
+                      String? companyAddress = addressController.text;
+
+                      if (Utils.isEmpty(movingCompany)) {
+                        ToastEngine.show("Enter Moving Company");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(personInCharge)) {
+                        ToastEngine.show("Enter Person In Charge");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(mobileNumber)) {
+                        ToastEngine.show("Enter Mobile Number");
+                        return;
+                      }
+
+                      //存入本表单数据
+                      viewModel.updateFormContentDetail((content) {
+                        content.movingCompany = movingCompany;
+                        content.personInCharge = personInCharge;
+                        content.mobileNumber = mobileNumber;
+                        content.companyAddress = companyAddress;
+                      });
+                    }
+
                     viewModel.gotoNextPage();
                   },
                   text: S.current.next,

+ 55 - 30
packages/cpt_form/lib/modules/apply/moving_date_page.dart

@@ -1,4 +1,3 @@
-
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
@@ -7,13 +6,17 @@ import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
 import 'package:widgets/my_text_view.dart';
+import 'package:widgets/shatter/form_require_text.dart';
 import 'package:widgets/shatter/picker_container.dart';
 import '../../router/page/form_page_router.dart';
 import 'vm/apply_view_model.dart';
+
 @RoutePage()
 class MovingDatePage extends HookConsumerWidget {
   const MovingDatePage({Key? key}) : super(key: key);
@@ -43,7 +46,7 @@ class MovingDatePage extends HookConsumerWidget {
 
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -57,43 +60,44 @@ class MovingDatePage extends HookConsumerWidget {
                       mainAxisSize: MainAxisSize.max,
                       crossAxisAlignment: CrossAxisAlignment.start,
                       children: [
-
                         //下拉选 - 开始时间
-                        MyTextView(
-                          S.current.start_date_caps,
-                          fontSize: 17,
-                          marginTop: 30,
-                          marginLeft: 15,
-                          marginBottom: 16,
-                          isFontMedium: true,
+                        FormRequireText(
+                          text: S.current.start_date_caps,
                           textColor: context.appColors.textBlack,
-                        ),
+                          fontSize: 17,
+                          fontWeight: FontWeight.w500,
+                        ).marginOnly(top: 30, bottom: 16, left: 15, right: 15),
 
                         PickerContainer(
                           hint: S.current.choose_date,
-                          onClick: (){
-                            viewModel.pickDate(null,(date){
-                              ToastEngine.show("选择的日期:$date");
+                          enable: state.enableEdit,
+                          content: state.formContentDetail.startDate,
+                          onClick: () {
+                            viewModel.pickDate(null, (date) {
+                              viewModel.updateFormContentDetail((content) {
+                                content.startDate = DateTimeUtils.formatDate(date, format: 'yyyy-MM-dd');
+                              });
                             });
                           },
                         ).marginOnly(left: 15, right: 15),
 
                         //下拉选 - 结束时间
-                        MyTextView(
-                          S.current.end_date_caps,
-                          fontSize: 17,
-                          marginTop: 14,
-                          marginLeft: 15,
-                          marginBottom: 16,
-                          isFontMedium: true,
+                        FormRequireText(
+                          text: S.current.end_date_caps,
                           textColor: context.appColors.textBlack,
-                        ),
+                          fontSize: 17,
+                          fontWeight: FontWeight.w500,
+                        ).marginOnly(top: 14, bottom: 16, left: 15, right: 15),
 
                         PickerContainer(
                           hint: S.current.choose_date,
-                          onClick: (){
-                            viewModel.pickDate(null,(date){
-                              ToastEngine.show("选择的日期:$date");
+                          enable: state.enableEdit,
+                          content: state.formContentDetail.endDate,
+                          onClick: () {
+                            viewModel.pickDate(null, (date) {
+                              viewModel.updateFormContentDetail((content) {
+                                content.endDate = DateTimeUtils.formatDate(date, format: 'yyyy-MM-dd');
+                              });
                             });
                           },
                         ).marginOnly(left: 15, right: 15),
@@ -111,13 +115,16 @@ class MovingDatePage extends HookConsumerWidget {
 
                         PickerContainer(
                           hint: S.current.choose_date,
-                          onClick: (){
-                            viewModel.pickDate(null,(date){
-                              ToastEngine.show("选择的日期:$date");
+                          enable: state.enableEdit,
+                          content: state.formContentDetail.timeOrArrival,
+                          onClick: () {
+                            viewModel.pickTime(null, (date) {
+                              viewModel.updateFormContentDetail((content) {
+                                content.timeOrArrival = DateTimeUtils.formatDate(date, format: 'HH:mm');
+                              });
                             });
                           },
                         ).marginOnly(left: 15, right: 15),
-
                       ],
                     ),
                   ),
@@ -125,7 +132,25 @@ class MovingDatePage extends HookConsumerWidget {
 
                 //底部按钮
                 MyButton(
-                  onPressed: viewModel.gotoNextPage,
+                  onPressed: () {
+                    if (state.enableEdit) {
+                      //校验数据
+                      final startDate = state.formContentDetail.startDate;
+                      final endDate = state.formContentDetail.endDate;
+
+                      if (Utils.isEmpty(startDate)) {
+                        ToastEngine.show("Select Start Date");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(endDate)) {
+                        ToastEngine.show("Select End Date");
+                        return;
+                      }
+                    }
+
+                    viewModel.gotoNextPage();
+                  },
                   text: S.current.next,
                   textColor: Colors.white,
                   backgroundColor: context.appColors.btnBgDefault,

+ 23 - 12
packages/cpt_form/lib/modules/apply/note_management_page.dart

@@ -4,7 +4,9 @@ import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
@@ -37,19 +39,16 @@ class NoteManagementPage extends HookConsumerWidget {
 
     useEffect(() {
       //赋值State的值
-      Future.microtask(() {});
+      Future.microtask(() {
+        textEditingController.text = state.formContentDetail.notesToManagement ?? "";
+      });
 
-      return () {
-        // 释放控制器资源
-        textEditingController.dispose();
-        focusNode.dispose();
-      };
+      return () {};
     }, []);
 
-
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -75,7 +74,7 @@ class NoteManagementPage extends HookConsumerWidget {
 
                         //Note to Management 的文本
                         MyTextView(
-                          state.applyDetail?['detail_data']['note_management_txt'],
+                          state.detailPage?['detail_data']['note_management_txt'],
                           fontSize: 15,
                           marginBottom: 18,
                           isFontRegular: true,
@@ -95,7 +94,7 @@ class NoteManagementPage extends HookConsumerWidget {
                               cursorColor: context.appColors.authFiledText,
                               cursorWidth: 1.5,
                               autofocus: false,
-                              enabled: true,
+                              enabled: state.enableEdit,
                               focusNode: focusNode,
                               controller: textEditingController,
                               decoration: InputDecoration(
@@ -122,7 +121,6 @@ class NoteManagementPage extends HookConsumerWidget {
                               expands: true,
                               onChanged: (text) {
                                 // 当文本改变时
-
                               },
                             ),
                           ),
@@ -134,9 +132,22 @@ class NoteManagementPage extends HookConsumerWidget {
 
                 //底部按钮
                 MyButton(
-                  onPressed: (){
+                  onPressed: () {
                     focusNode.unfocus();
 
+                    if (state.enableEdit) {
+                      String? notesToManagement = textEditingController.text;
+
+                      if (Utils.isEmpty(notesToManagement)) {
+                        ToastEngine.show("Enter Notes To Management");
+                        return;
+                      }
+
+                      viewModel.updateFormContentDetail((content) {
+                        content.notesToManagement = notesToManagement;
+                      });
+                    }
+
                     viewModel.gotoNextPage();
                   },
                   text: S.current.next,

+ 44 - 14
packages/cpt_form/lib/modules/apply/renovation_company_page.dart

@@ -4,7 +4,9 @@ import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
@@ -46,24 +48,19 @@ class RenovationCompanyPage extends HookConsumerWidget {
 
     useEffect(() {
       //赋值State的值
-      Future.microtask(() {});
+      Future.microtask(() {
+        companyController.text = state.formContentDetail.renovationCompany ?? "";
+        contactController.text = state.formContentDetail.personInCharge ?? "";
+        phoneController.text = state.formContentDetail.mobileNumber ?? "";
+        addressController.text = state.formContentDetail.companyAddress ?? "";
+      });
 
-      return () {
-        // 释放控制器资源
-        companyController.dispose();
-        contactController.dispose();
-        phoneController.dispose();
-        addressController.dispose();
-        companyFocusNode.dispose();
-        contactFocusNode.dispose();
-        phoneFocusNode.dispose();
-        addressFocusNode.dispose();
-      };
+      return () {};
     }, []);
 
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -89,6 +86,7 @@ class RenovationCompanyPage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "company",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.text,
                           textInputAction: TextInputAction.next,
                           controller: companyController,
@@ -111,6 +109,7 @@ class RenovationCompanyPage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "contact",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.text,
                           textInputAction: TextInputAction.next,
                           controller: contactController,
@@ -133,6 +132,7 @@ class RenovationCompanyPage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "phone",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.phone,
                           textInputAction: TextInputAction.next,
                           controller: phoneController,
@@ -169,7 +169,7 @@ class RenovationCompanyPage extends HookConsumerWidget {
                               cursorColor: context.appColors.authFiledText,
                               cursorWidth: 1.5,
                               autofocus: false,
-                              enabled: true,
+                              enabled: state.enableEdit,
                               focusNode: addressFocusNode,
                               controller: addressController,
                               decoration: InputDecoration(
@@ -212,6 +212,36 @@ class RenovationCompanyPage extends HookConsumerWidget {
                     phoneFocusNode.unfocus();
                     addressFocusNode.unfocus();
 
+                    if (state.enableEdit) {
+                      String? renovationCompany = companyController.text;
+                      String? personInCharge = contactController.text;
+                      String? mobileNumber = phoneController.text;
+                      String? companyAddress = addressController.text;
+
+                      if (Utils.isEmpty(renovationCompany)) {
+                        ToastEngine.show("Enter Renovation Company");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(personInCharge)) {
+                        ToastEngine.show("Enter Person In Charge");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(mobileNumber)) {
+                        ToastEngine.show("Enter Mobile Number");
+                        return;
+                      }
+
+                      //存入本表单数据
+                      viewModel.updateFormContentDetail((content) {
+                        content.renovationCompany = renovationCompany;
+                        content.personInCharge = personInCharge;
+                        content.mobileNumber = mobileNumber;
+                        content.companyAddress = companyAddress;
+                      });
+                    }
+
                     viewModel.gotoNextPage();
                   },
                   text: S.current.next,

+ 61 - 33
packages/cpt_form/lib/modules/apply/renovation_date_page.dart

@@ -1,4 +1,3 @@
-
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
@@ -7,10 +6,13 @@ import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
 import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
 import 'package:widgets/my_text_view.dart';
+import 'package:widgets/shatter/form_require_text.dart';
 import 'package:widgets/shatter/picker_container.dart';
 import '../../router/page/form_page_router.dart';
 import 'vm/apply_view_model.dart';
@@ -44,7 +46,7 @@ class RenovationDatePage extends HookConsumerWidget {
 
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -58,43 +60,44 @@ class RenovationDatePage extends HookConsumerWidget {
                       mainAxisSize: MainAxisSize.max,
                       crossAxisAlignment: CrossAxisAlignment.start,
                       children: [
-
                         //下拉选 - 开始时间
-                        MyTextView(
-                          S.current.renovation_start_date,
-                          fontSize: 17,
-                          marginTop: 30,
-                          marginLeft: 15,
-                          marginBottom: 16,
-                          isFontMedium: true,
+                        FormRequireText(
+                          text: S.current.renovation_start_date,
                           textColor: context.appColors.textBlack,
-                        ),
+                          fontSize: 17,
+                          fontWeight: FontWeight.w500,
+                        ).marginOnly(top: 30, bottom: 16, left: 15, right: 15),
 
                         PickerContainer(
                           hint: S.current.choose_date,
-                          onClick: (){
-                            viewModel.pickDate(null,(date){
-                              ToastEngine.show("选择的日期:$date");
+                          enable: state.enableEdit,
+                          content: state.formContentDetail.renovationStartDate,
+                          onClick: () {
+                            viewModel.pickDate(null, (date) {
+                              viewModel.updateFormContentDetail((content) {
+                                content.renovationStartDate = DateTimeUtils.formatDate(date, format: 'yyyy-MM-dd');
+                              });
                             });
                           },
                         ).marginOnly(left: 15, right: 15),
 
                         //下拉选 - 结束时间
-                        MyTextView(
-                          S.current.renovation_end_date,
-                          fontSize: 17,
-                          marginTop: 14,
-                          marginLeft: 15,
-                          marginBottom: 16,
-                          isFontMedium: true,
+                        FormRequireText(
+                          text: S.current.renovation_end_date,
                           textColor: context.appColors.textBlack,
-                        ),
+                          fontSize: 17,
+                          fontWeight: FontWeight.w500,
+                        ).marginOnly(top: 14, bottom: 16, left: 15, right: 15),
 
                         PickerContainer(
                           hint: S.current.choose_date,
-                          onClick: (){
-                            viewModel.pickDate(null,(date){
-                              ToastEngine.show("选择的日期:$date");
+                          enable: state.enableEdit,
+                          content: state.formContentDetail.renovationEndDate,
+                          onClick: () {
+                            viewModel.pickDate(null, (date) {
+                              viewModel.updateFormContentDetail((content) {
+                                content.renovationEndDate = DateTimeUtils.formatDate(date, format: 'yyyy-MM-dd');
+                              });
                             });
                           },
                         ).marginOnly(left: 15, right: 15),
@@ -112,9 +115,13 @@ class RenovationDatePage extends HookConsumerWidget {
 
                         PickerContainer(
                           hint: S.current.choose_date,
-                          onClick: (){
-                            viewModel.pickDate(null,(date){
-                              ToastEngine.show("选择的日期:$date");
+                          enable: state.enableEdit,
+                          content: state.formContentDetail.hackingStartDate,
+                          onClick: () {
+                            viewModel.pickDate(null, (date) {
+                              viewModel.updateFormContentDetail((content) {
+                                content.hackingStartDate = DateTimeUtils.formatDate(date, format: 'yyyy-MM-dd');
+                              });
                             });
                           },
                         ).marginOnly(left: 15, right: 15),
@@ -132,13 +139,16 @@ class RenovationDatePage extends HookConsumerWidget {
 
                         PickerContainer(
                           hint: S.current.choose_date,
-                          onClick: (){
-                            viewModel.pickDate(null,(date){
-                              ToastEngine.show("选择的日期:$date");
+                          enable: state.enableEdit,
+                          content: state.formContentDetail.hackingEndDate,
+                          onClick: () {
+                            viewModel.pickDate(null, (date) {
+                              viewModel.updateFormContentDetail((content) {
+                                content.hackingEndDate = DateTimeUtils.formatDate(date, format: 'yyyy-MM-dd');
+                              });
                             });
                           },
                         ).marginOnly(left: 15, right: 15),
-
                       ],
                     ),
                   ),
@@ -146,7 +156,25 @@ class RenovationDatePage extends HookConsumerWidget {
 
                 //底部按钮
                 MyButton(
-                  onPressed: viewModel.gotoNextPage,
+                  onPressed: () {
+                    if (state.enableEdit) {
+                      //校验数据
+                      final startDate = state.formContentDetail.renovationEndDate;
+                      final endDate = state.formContentDetail.renovationEndDate;
+
+                      if (Utils.isEmpty(startDate)) {
+                        ToastEngine.show("Select Renovation Start Date");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(endDate)) {
+                        ToastEngine.show("Select Renovation End Date");
+                        return;
+                      }
+                    }
+
+                    viewModel.gotoNextPage();
+                  },
                   text: S.current.next,
                   textColor: Colors.white,
                   backgroundColor: context.appColors.btnBgDefault,

+ 75 - 34
packages/cpt_form/lib/modules/apply/signature_page.dart

@@ -1,3 +1,5 @@
+import 'dart:typed_data';
+import 'dart:ui';
 
 import 'package:cpt_form/modules/apply/vm/apply_view_model.dart';
 import 'package:cs_resources/generated/l10n.dart';
@@ -6,10 +8,15 @@ import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_basic/provider/user_config/user_config_service.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/date_time_utils.dart';
+import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
+import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 import 'package:widgets/widget_export.dart';
 import '../../router/page/form_page_router.dart';
@@ -33,11 +40,13 @@ class SignaturePage extends HookConsumerWidget {
     final state = ref.watch(applyViewModelProvider);
 
     //签名版配置
-    HandSignatureControl handSignatureControl = HandSignatureControl(
-      threshold: 3.0,
-      smoothRatio: 190 / 345,
-      velocityRange: 2.0,
-    );
+    final HandSignatureControl handSignatureControl = useMemoized(() {
+      return HandSignatureControl(
+        threshold: 3.0,
+        smoothRatio: 190 / 345,
+        velocityRange: 2.0,
+      );
+    });
 
     useEffect(() {
       //赋值State的值
@@ -51,7 +60,7 @@ class SignaturePage extends HookConsumerWidget {
 
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -76,7 +85,7 @@ class SignaturePage extends HookConsumerWidget {
 
                         //签名的说明文本
                         MyTextView(
-                          state.applyDetail?['detail_data']['signature_txt'],
+                          state.detailPage?['detail_data']['signature_txt'],
                           fontSize: 15,
                           marginTop: 26,
                           marginBottom: 21,
@@ -93,33 +102,42 @@ class SignaturePage extends HookConsumerWidget {
                                 width: 345,
                                 height: 190,
                                 color: context.appColors.imgGrayBg,
-                                child: HandSignature(
-                                  control: handSignatureControl,
-                                  color: context.appColors.textBlack,
-                                  width: 1.0,
-                                  maxWidth: 3.5,
-                                  type: SignatureDrawType.shape,
-                                ),
+                                child: state.enableEdit
+                                    ? HandSignature(
+                                        control: handSignatureControl,
+                                        color: context.appColors.textBlack,
+                                        width: 1.0,
+                                        maxWidth: 3.5,
+                                        type: SignatureDrawType.shape,
+                                      )
+                                    : MyLoadImage(
+                                        state.formContentDetail.signature,
+                                        width: 345,
+                                        height: 190,
+                                      ),
                               ),
                             ),
 
                             //清除签名
                             Align(
                               alignment: Alignment.bottomRight,
-                              child: MyTextView(
-                                S.current.clean,
-                                fontSize: 12,
-                                textColor: Colors.white,
-                                cornerRadius: 10.37,
-                                backgroundColor: context.appColors.btnBgDefault,
-                                paddingTop: 4,
-                                paddingBottom: 4,
-                                paddingLeft: 11,
-                                paddingRight: 11,
-                                margin: 10,
-                                onClick: () {
-                                  handSignatureControl.clear();
-                                },
+                              child: Visibility(
+                                visible: state.enableEdit,
+                                child: MyTextView(
+                                  S.current.clean,
+                                  fontSize: 12,
+                                  textColor: Colors.white,
+                                  cornerRadius: 10.37,
+                                  backgroundColor: context.appColors.btnBgDefault,
+                                  paddingTop: 4,
+                                  paddingBottom: 4,
+                                  paddingLeft: 11,
+                                  paddingRight: 11,
+                                  margin: 10,
+                                  onClick: () {
+                                    handSignatureControl.clear();
+                                  },
+                                ),
                               ),
                             ),
                           ],
@@ -128,24 +146,24 @@ class SignaturePage extends HookConsumerWidget {
                           height: 190,
                         ),
 
+                        //同意协议富文本
                         RichText(
                           text: TextSpan(
-                            style: TextStyle(fontSize: 15, fontWeight:  FontWeight.w400, color: context.appColors.textBlack),
+                            style: TextStyle(fontSize: 15, fontWeight: FontWeight.w400, color: context.appColors.textBlack),
                             children: <TextSpan>[
                               TextSpan(
                                 text: S.current.signed_and_agreed_by,
                               ),
                               TextSpan(
-                                text: " Wu Bing Bing ",
+                                text: " ${UserConfigService.getState().userName ?? "-"} \n",
                                 style: TextStyle(color: context.appColors.textPrimary),
                               ),
                               TextSpan(
-                                text: " 21 Nov 2024, 03:08 PM",
+                                text: DateTimeUtils.formatNowDateStr(format: 'dd MMM yyyy HH:mm'),
                               ),
                             ],
                           ),
-                        ).marginOnly(top: 21,bottom: 21),
-
+                        ).marginOnly(top: 21, bottom: 21),
                       ],
                     ),
                   ),
@@ -153,11 +171,34 @@ class SignaturePage extends HookConsumerWidget {
 
                 //底部按钮
                 MyButton(
-                  onPressed: viewModel.gotoNextPage,
+                  onPressed: () async {
+                    final isFilled = handSignatureControl.isFilled;
+                    if (!isFilled) {
+                      ToastEngine.show("Please sign first");
+                      return;
+                    }
+
+                    var byteData = await handSignatureControl.toImage(
+                      format: ImageByteFormat.png,
+                      border: 0,
+                      width: 345,
+                      height: 190,
+                      background: Colors.white,
+                    ) as ByteData;
+
+                    //存入本表单数据
+                    viewModel.updateFormContentDetail((content) {
+                      content.signatureByteData = byteData;
+                    });
+
+                    viewModel.submitForm();
+                  },
                   text: S.current.submit,
                   textColor: Colors.white,
                   backgroundColor: context.appColors.btnBgDefault,
                   fontWeight: FontWeight.w500,
+                  enable: state.enableEdit,
+                  disabledBackgroundColor: context.appColors.disEnableGray,
                   type: ClickType.throttle,
                   fontSize: 16,
                   minHeight: 50,

+ 21 - 3
packages/cpt_form/lib/modules/apply/type_of_application_page.dart

@@ -3,8 +3,10 @@ import 'package:cs_resources/theme/app_colors_theme.dart';
 import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
 import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
@@ -33,7 +35,7 @@ class TypeOfApplicationPage extends HookConsumerWidget {
 
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -50,14 +52,30 @@ class TypeOfApplicationPage extends HookConsumerWidget {
 
                 PickerContainer(
                   hint: S.current.choose_an_option,
-                  onClick: viewModel.pickOption,
+                  enable: state.enableEdit,
+                  content: state.formContentDetail.typeOfApplication,
+                  onClick: () {
+                    viewModel.pickOption(true);
+                  },
                 ).marginOnly(left: 15, right: 15),
 
                 const Spacer(),
 
                 //底部按钮
                 MyButton(
-                  onPressed: viewModel.gotoNextPage,
+                  onPressed: (){
+                    if (state.enableEdit){
+                      //校验数据
+                      final typeOfApplication = state.formContentDetail.typeOfApplication;
+
+                      if (Utils.isEmpty(typeOfApplication)) {
+                        ToastEngine.show("Select Type Of Application");
+                        return;
+                      }
+                    }
+
+                    viewModel.gotoNextPage();
+                  },
                   text: S.current.next,
                   textColor: Colors.white,
                   backgroundColor: context.appColors.btnBgDefault,

+ 87 - 55
packages/cpt_form/lib/modules/apply/vehicle_info_page.dart

@@ -1,4 +1,3 @@
-
 import 'package:cpt_form/modules/apply/vm/apply_view_model.dart';
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
@@ -6,7 +5,9 @@ import 'package:flutter/material.dart';
 import 'package:auto_route/auto_route.dart';
 import 'package:flutter_hooks/flutter_hooks.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
 import 'package:router/ext/auto_router_extensions.dart';
+import 'package:shared/utils/util.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
@@ -43,27 +44,20 @@ class VehicleInfoPage extends HookConsumerWidget {
     final FocusNode iuNumFocusNode = useFocusNode();
     final FocusNode vehicleInfoFocusNode = useFocusNode();
 
-
     useEffect(() {
-
       //赋值State的值
-      Future.microtask(() {});
+      Future.microtask(() {
+        vehicleNumController.text = state.formContentDetail.vehicleNumber ?? "";
+        iuNumController.text = state.formContentDetail.iuNumber ?? "";
+        vehicleInfoController.text = state.formContentDetail.vehicleMakeModelColour ?? "";
+      });
 
-      return () {
-        // 释放控制器资源
-        vehicleNumController.dispose();
-        iuNumController.dispose();
-        vehicleInfoController.dispose();
-        vehicleNumFocusNode.dispose();
-        iuNumFocusNode.dispose();
-        vehicleInfoFocusNode.dispose();
-      };
+      return () {};
     }, []);
 
-
     return WillPopScope(
         child: Scaffold(
-            appBar: MyAppBar.appBar(context, state.applyDetail?['title']),
+            appBar: MyAppBar.appBar(context, state.detailPage?['title']),
             backgroundColor: context.appColors.backgroundWhite,
             body: Column(
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -77,52 +71,53 @@ class VehicleInfoPage extends HookConsumerWidget {
                       mainAxisSize: MainAxisSize.max,
                       crossAxisAlignment: CrossAxisAlignment.start,
                       children: [
-
                         //下拉选 - Type类型
-                        MyTextView(
-                          S.current.type_of_application,
-                          fontSize: 17,
-                          marginTop: 30,
-                          marginLeft: 15,
-                          marginBottom: 16,
-                          isFontMedium: true,
+                        FormRequireText(
+                          text: S.current.type_of_application,
                           textColor: context.appColors.textBlack,
-                        ),
+                          fontSize: 17,
+                          fontWeight: FontWeight.w500,
+                        ).marginOnly(top: 30, bottom: 16, left: 15, right: 15),
 
                         PickerContainer(
                           hint: S.current.choose_an_option,
-                          onClick: viewModel.pickOption,
+                          enable: state.enableEdit,
+                          content: state.formContentDetail.typeOfApplication,
+                          onClick: () {
+                            viewModel.pickOption(true);
+                          },
                         ).marginOnly(left: 15, right: 15),
 
                         //下拉选 - 所有权状态
-                        MyTextView(
-                          S.current.ownership_status,
-                          fontSize: 17,
-                          marginTop: 14,
-                          marginLeft: 15,
-                          marginBottom: 16,
-                          isFontMedium: true,
+                        FormRequireText(
+                          text: S.current.ownership_status,
                           textColor: context.appColors.textBlack,
-                        ),
+                          fontSize: 17,
+                          fontWeight: FontWeight.w500,
+                        ).marginOnly(top: 14, bottom: 16, left: 15, right: 15),
 
                         PickerContainer(
                           hint: S.current.choose_an_option,
-                          onClick: viewModel.pickOption,
+                          enable: state.enableEdit,
+                          content: state.formContentDetail.ownershipStatus,
+                          onClick: () {
+                            viewModel.pickOption(false);
+                          },
                         ).marginOnly(left: 15, right: 15),
 
-
                         //输入框 - 车牌号
                         FormRequireText(
                           text: S.current.vehicle_number,
                           textColor: context.appColors.textBlack,
                           fontSize: 17,
                           fontWeight: FontWeight.w500,
-                        ).marginOnly(top: 14,bottom: 16,left: 15,right: 15),
+                        ).marginOnly(top: 14, bottom: 16, left: 15, right: 15),
 
                         // 表单
                         _buildInputLayout(
                           context,
                           "vehicle_num",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.text,
                           textInputAction: TextInputAction.next,
                           controller: vehicleNumController,
@@ -149,6 +144,7 @@ class VehicleInfoPage extends HookConsumerWidget {
                         _buildInputLayout(
                           context,
                           "iu_num",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.text,
                           textInputAction: TextInputAction.next,
                           controller: iuNumController,
@@ -165,12 +161,13 @@ class VehicleInfoPage extends HookConsumerWidget {
                           textColor: context.appColors.textBlack,
                           fontSize: 17,
                           fontWeight: FontWeight.w500,
-                        ).marginOnly(top: 14,bottom: 16,left: 15,right: 15),
+                        ).marginOnly(top: 14, bottom: 16, left: 15, right: 15),
 
                         // 表单
                         _buildInputLayout(
                           context,
                           "vehicle_info",
+                          enable: state.enableEdit,
                           textInputType: TextInputType.text,
                           textInputAction: TextInputAction.done,
                           controller: vehicleInfoController,
@@ -179,7 +176,6 @@ class VehicleInfoPage extends HookConsumerWidget {
                             vehicleInfoFocusNode.unfocus();
                           },
                         ),
-
                       ],
                     ),
                   ),
@@ -187,11 +183,48 @@ class VehicleInfoPage extends HookConsumerWidget {
 
                 //底部按钮
                 MyButton(
-                  onPressed: (){
+                  onPressed: () {
                     vehicleNumFocusNode.unfocus();
                     iuNumFocusNode.unfocus();
                     vehicleInfoFocusNode.unfocus();
 
+                    if (state.enableEdit) {
+                      String? vehicleNumber = vehicleNumController.text;
+                      String? iuNumber = iuNumController.text;
+                      String? vehicleMakeModelColour = vehicleInfoController.text;
+
+                      //校验数据
+                      final typeOfApplication = state.formContentDetail.typeOfApplication;
+                      final ownershipStatus = state.formContentDetail.ownershipStatus;
+
+                      if (Utils.isEmpty(typeOfApplication)) {
+                        ToastEngine.show("Select Type Of Application");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(ownershipStatus)) {
+                        ToastEngine.show("Select Ownership Status");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(vehicleNumber)) {
+                        ToastEngine.show("Enter vehicle number");
+                        return;
+                      }
+
+                      if (Utils.isEmpty(vehicleMakeModelColour)) {
+                        ToastEngine.show("Enter vehicle make/model/ colour");
+                        return;
+                      }
+
+                      //存入本表单数据
+                      viewModel.updateFormContentDetail((content) {
+                        content.vehicleNumber = vehicleNumber;
+                        content.vehicleMakeModelColour = vehicleMakeModelColour;
+                        content.iuNumber = iuNumber;
+                      });
+                    }
+
                     viewModel.gotoNextPage();
                   },
                   text: S.current.next,
@@ -212,20 +245,20 @@ class VehicleInfoPage extends HookConsumerWidget {
   }
 
   Widget _buildInputLayout(
-      BuildContext context,
-      String key, {
-        double marginTop = 0,
-        bool? showRightIcon = false, //是否展示右侧的布局
-        Widget? rightWidget, //右侧的布局
-        TextInputType textInputType = TextInputType.text,
-        String? errorText,
-        bool obscureText = false,
-        required TextEditingController controller,
-        required FocusNode focusNode,
-        bool enable = true,
-        TextInputAction textInputAction = TextInputAction.done,
-        Function? onSubmit,
-      }) {
+    BuildContext context,
+    String key, {
+    double marginTop = 0,
+    bool? showRightIcon = false, //是否展示右侧的布局
+    Widget? rightWidget, //右侧的布局
+    TextInputType textInputType = TextInputType.text,
+    String? errorText,
+    bool obscureText = false,
+    required TextEditingController controller,
+    required FocusNode focusNode,
+    bool enable = true,
+    TextInputAction textInputAction = TextInputAction.done,
+    Function? onSubmit,
+  }) {
     return IgnoreKeyboardDismiss(
       child: MyTextField(
         key,
@@ -238,7 +271,7 @@ class VehicleInfoPage extends HookConsumerWidget {
         ),
         controller: controller,
         focusNode: focusNode,
-        margin: EdgeInsets.only(top: marginTop,left: 15,right: 15),
+        margin: EdgeInsets.only(top: marginTop, left: 15, right: 15),
         padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
         showDivider: false,
         height: 44,
@@ -260,5 +293,4 @@ class VehicleInfoPage extends HookConsumerWidget {
       ),
     );
   }
-
 }

+ 31 - 8
packages/cpt_form/lib/modules/apply/vm/apply_state.dart

@@ -1,37 +1,60 @@
 import 'package:cs_resources/generated/l10n.dart';
+import 'package:domain/entity/form_content_entity.dart';
+import 'package:domain/entity/form_list_entity.dart';
+import 'package:domain/entity/form_option_entity.dart';
 import 'package:flutter/material.dart';
 
 class ApplyState {
-
-  //详情页面的索引,为了记录详情页面组的当前跳转索引,不参与状态所以不用参与Copy方法
   int detailPageIndex;
 
   //表单类型(列表的Form类型)
   String? formType;
 
+  String? estateFormId;
+
+  //该房产小区对应的此 Form 信息,从Apply 的列表item中拿过来
+  FormListEntity? formItem;
+
   //是否可编辑
   bool enableEdit;
 
-  //详情数据
-  Map<String, dynamic>? applyDetail;
+  //页面组的信息
+  Map<String, dynamic>? detailPage;
+
+  //复显的详情数据(来自网络数据)
+  FormContentEntity formContentDetail;
+
+  FormOptionEntity? formOption;
 
   ApplyState({
     this.formType,
-    this.applyDetail,
+    this.estateFormId,
+    this.formItem,
+    this.detailPage,
+    this.formOption,
+    required this.formContentDetail,
     this.enableEdit = true,
     this.detailPageIndex = 0,
   });
 
   ApplyState copyWith({
     String? formType,
+    String? estateFormId,
+    FormListEntity? formItem,
     bool? enableEdit,
-    Map<String, dynamic>? applyDetail,
+    Map<String, dynamic>? detailPage,
+    FormContentEntity? formContentDetail,
+    FormOptionEntity? formOption,
   }) {
     return ApplyState(
       formType: formType ?? this.formType,
+      estateFormId: estateFormId ?? this.estateFormId,
+      formItem: formItem ?? this.formItem,
       enableEdit: enableEdit ?? this.enableEdit,
-      applyDetail: applyDetail ?? this.applyDetail,
+      detailPage: detailPage ?? this.detailPage,
+      formContentDetail: formContentDetail ?? this.formContentDetail,
+      formOption: formOption ?? this.formOption,
+      detailPageIndex: this.detailPageIndex,
     );
   }
-
 }

+ 114 - 11
packages/cpt_form/lib/modules/apply/vm/apply_view_model.dart

@@ -1,7 +1,13 @@
 import 'dart:ui';
 
 import 'package:cs_resources/generated/l10n.dart';
+import 'package:domain/entity/form_content_entity.dart';
+import 'package:domain/entity/form_list_entity.dart';
+import 'package:domain/repository/form_repository.dart';
 import 'package:flutter/cupertino.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:plugin_platform/engine/notify/notify_engine.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:shared/utils/log_utils.dart';
 import 'package:widgets/picker/date_picker_util.dart';
@@ -13,23 +19,44 @@ import 'package:widgets/picker/option_pick_util.dart';
 part 'apply_view_model.g.dart';
 
 @riverpod
-class ApplyViewModel extends _$ApplyViewModel {
+class ApplyViewModel extends _$ApplyViewModel with DioCancelableMixin {
+  late final FormRepository _formRepository;
+
   @override
   ApplyState build() {
-    return ApplyState();
+    _formRepository = ref.read(formRepositoryProvider);
+    final state = ApplyState(formContentDetail: FormContentEntity());
+    registerCancellation();
+    return state;
   }
 
   //设置具体的表单类型
-  void setFormType(String formType) {
-    final detail = FormTypes.detailPageMap[formType];
-    Log.d("applyViewModelProvider - detail:$detail");
-    state = state.copyWith(formType: formType, applyDetail: detail);
+  void setFormType(String formType, String? estateFormId, FormListEntity? formItem, bool enableEdit, FormContentEntity? formContent) {
+    final detail = FormTypes.buildDetailPageMap(enableEdit)[formType];
+    if (enableEdit) {
+      state = state.copyWith(
+        formType: formType,
+        detailPage: detail,
+        formItem: formItem,
+        enableEdit: enableEdit,
+        estateFormId: estateFormId ?? formItem?.id,
+      );
+    } else {
+      state = state.copyWith(
+        formType: formType,
+        detailPage: detail,
+        formItem: formItem,
+        enableEdit: enableEdit,
+        formContentDetail: formContent,
+        estateFormId: estateFormId ?? formItem?.id,
+      );
+    }
   }
 
   //进入下一步页面
   void gotoNextPage() {
     Log.d("applyViewModelProvider - detailPageIndex:${state.detailPageIndex}");
-    bool success = FormTypes.startDetailPageByType(state.applyDetail?['detail_pages'], state.detailPageIndex);
+    bool success = FormTypes.startDetailPageByType(state.detailPage?['detail_pages'], state.detailPageIndex);
     Log.d("applyViewModelProvider - gotoNextPage - success:$success");
     if (!success) {
       FormPage.startInstance();
@@ -44,15 +71,53 @@ class ApplyViewModel extends _$ApplyViewModel {
   }
 
   //选择一个选项
-  void pickOption() {
+  void pickOption(bool isApplicationType) async {
+    Log.d("当前的optionList:${state.formOption}");
+    if (state.formOption == null) {
+      //请求接口
+      final result = await _formRepository.fetchFormOption(typeId: state.formType, cancelToken: cancelToken);
+
+      if (result.isSuccess) {
+        state = state.copyWith(formOption: result.data);
+        _showPicker(isApplicationType);
+      } else {
+        ToastEngine.show(result.errorMsg ?? "UnKnow Error");
+      }
+    } else {
+      _showPicker(isApplicationType);
+    }
+  }
+
+  //展示分类的PickerView
+  void _showPicker(bool isApplicationType) {
+    List<String>? list;
+    if (isApplicationType) {
+      list = state.formOption?.typeOfApplication;
+    } else {
+      list = state.formOption?.ownershipStatus;
+    }
+
+    if (list == null || list.isEmpty) return;
+
     OptionPickerUtil.showCupertinoOptionPicker(
-      items: ["选项1", "选项2", "选项3"],
+      items: list,
       initialSelectIndex: 0,
-      onPickerChanged: (_, index) {},
+      onPickerChanged: (_, index) {
+        final value = list![index];
+        if (isApplicationType) {
+          updateFormContentDetail((content) {
+            content.typeOfApplication = value;
+          });
+        } else {
+          updateFormContentDetail((content) {
+            content.ownershipStatus = value;
+          });
+        }
+      },
     );
   }
 
-  //选择一个日期,并回调出去
+  //选择一个日期,并回调出去赋值
   void pickDate(DateTime? selectedDate, void Function(DateTime) dateCallback) {
     DatePickerUtil.showCupertinoDatePicker(
       selectedDateTime: selectedDate ?? DateTime.now(),
@@ -64,4 +129,42 @@ class ApplyViewModel extends _$ApplyViewModel {
     );
   }
 
+  //选择一个时间 时分秒
+  void pickTime(DateTime? selectedDate, void Function(DateTime) dateCallback) {
+    DatePickerUtil.showCupertinoDatePicker(
+      selectedDateTime: selectedDate ?? DateTime.now(),
+      mode: CupertinoDatePickerMode.time,
+      onDateTimeChanged: (date) {
+        dateCallback.call(date);
+      },
+      title: S.current.choose_date,
+    );
+  }
+
+  /// 更新页面内容状态数据
+  void updateFormContentDetail(void Function(FormContentEntity) update) {
+    //先创建一个新对象
+    final updatedDetail = state.formContentDetail.copyWith();
+    //更新新对象的值
+    update(updatedDetail);
+    //更新State
+    state = state.copyWith(formContentDetail: updatedDetail);
+  }
+
+  /// 提交Form表单
+  void submitForm() async {
+    final result = await _formRepository.submitForm(
+      estateFormId: state.estateFormId,
+      typeId: state.formType,
+      content: state.formContentDetail,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      NotifyEngine.showSuccess(S.current.successful);
+      gotoNextPage();
+    } else {
+      ToastEngine.show(result.errorMsg ?? "UnKnow Error");
+    }
+  }
 }

+ 1 - 1
packages/cpt_form/lib/modules/apply/vm/apply_view_model.g.dart

@@ -6,7 +6,7 @@ part of 'apply_view_model.dart';
 // RiverpodGenerator
 // **************************************************************************
 
-String _$applyViewModelHash() => r'ea1cdebf421fe02f772e0f1896e1bf37df0b5a5c';
+String _$applyViewModelHash() => r'd79f7a3eb669265cc9d4c43850736b215051ef49';
 
 /// See also [ApplyViewModel].
 @ProviderFor(ApplyViewModel)

+ 38 - 22
packages/cpt_form/lib/modules/detail/detail_approved_fragment.dart

@@ -4,13 +4,19 @@ import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/src/widgets/framework.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/componentRouter/component_service_manager.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_button.dart';
 import 'package:widgets/my_text_view.dart';
 
+import '../apply/form_terms_page.dart';
+import 'form_detail_view_model.dart';
+
 class DetailApprovedFragment extends HookConsumerWidget {
   @override
   Widget build(BuildContext context, WidgetRef ref) {
+    final state = ref.watch(formDetailViewModelProvider);
+
     return SizedBox(
       width: double.infinity,
       height: double.infinity,
@@ -51,7 +57,7 @@ class DetailApprovedFragment extends HookConsumerWidget {
                           text: S.current.send_on_sometime(' '),
                         ),
                         TextSpan(
-                          text: "21 Nov 2024, 03:08 PM",
+                          text: state.forDetail?.sentOn ?? "-",
                           style: TextStyle(fontSize: 15, fontWeight: FontWeight.w500, color: context.appColors.textBlack),
                         ),
                       ],
@@ -67,7 +73,7 @@ class DetailApprovedFragment extends HookConsumerWidget {
                           text: S.current.approved_on_sometime(' '),
                         ),
                         TextSpan(
-                          text: "21 Nov 2024, 03:08 PM",
+                          text: state.forDetail?.approvedOn ?? "-",
                           style: TextStyle(fontSize: 15, fontWeight: FontWeight.w500, color: context.appColors.textBlack),
                         ),
                       ],
@@ -83,24 +89,24 @@ class DetailApprovedFragment extends HookConsumerWidget {
                   ),
 
                   //通行卡的数据
-                  MyTextView(
-                    S.current.serial_number,
-                    marginLeft: 50,
-                    marginRight: 50,
-                    textAlign: TextAlign.center,
-                    textColor: context.appColors.textBlack,
-                    fontSize: 17,
-                    isFontRegular: true,
-                  ),
-
-                  MyTextView(
-                    "PL24087",
-                    marginTop: 16,
-                    marginBottom: 16,
-                    textColor: context.appColors.textPrimary,
-                    fontSize: 24,
-                    isFontMedium: true,
-                  ),
+                  // MyTextView(
+                  //   S.current.serial_number,
+                  //   marginLeft: 50,
+                  //   marginRight: 50,
+                  //   textAlign: TextAlign.center,
+                  //   textColor: context.appColors.textBlack,
+                  //   fontSize: 17,
+                  //   isFontRegular: true,
+                  // ),
+                  //
+                  // MyTextView(
+                  //   "PL24087",
+                  //   marginTop: 16,
+                  //   marginBottom: 16,
+                  //   textColor: context.appColors.textPrimary,
+                  //   fontSize: 24,
+                  //   isFontMedium: true,
+                  // ),
 
                   //提示 Feedback 文本
                   MyTextView(
@@ -120,7 +126,9 @@ class DetailApprovedFragment extends HookConsumerWidget {
           Row(
             children: [
               MyButton(
-                onPressed: () {},
+                onPressed: () {
+                  ComponentServiceManager().mainService.startFeedbackCreatePage(context: context);
+                },
                 text: S.current.send_feedback,
                 textColor: Colors.white,
                 fontSize: 15,
@@ -130,7 +138,15 @@ class DetailApprovedFragment extends HookConsumerWidget {
               ).expanded(),
               const SizedBox(width: 10),
               MyButton(
-                onPressed: () {},
+                onPressed: () {
+                  FormTermsPage.startInstance(
+                      formType: state.typeId ?? "",
+                      estateFormId: state.estateFormId,
+                      formItem: null,
+                      enableEdit: false,
+                      formContent: state.forDetail?.content,
+                  );
+                },
                 text: S.current.view_application,
                 textColor: Colors.white,
                 fontSize: 15,

+ 20 - 4
packages/cpt_form/lib/modules/detail/detail_not_approved_fragment.dart

@@ -4,13 +4,19 @@ import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/src/widgets/framework.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/componentRouter/component_service_manager.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_button.dart';
 import 'package:widgets/my_text_view.dart';
 
+import '../apply/form_terms_page.dart';
+import 'form_detail_view_model.dart';
+
 class DetailNotApprovedFragment extends HookConsumerWidget {
   @override
   Widget build(BuildContext context, WidgetRef ref) {
+    final state = ref.watch(formDetailViewModelProvider);
+
     return SizedBox(
       width: double.infinity,
       height: double.infinity,
@@ -51,7 +57,7 @@ class DetailNotApprovedFragment extends HookConsumerWidget {
                           text: S.current.send_on_sometime(' '),
                         ),
                         TextSpan(
-                          text: "21 Nov 2024, 03:08 PM",
+                          text: state.forDetail?.sentOn ?? "-",
                           style: TextStyle(fontSize: 15, fontWeight: FontWeight.w500, color: context.appColors.textBlack),
                         ),
                       ],
@@ -67,7 +73,7 @@ class DetailNotApprovedFragment extends HookConsumerWidget {
                           text: S.current.approved_on_sometime(' '),
                         ),
                         TextSpan(
-                          text: "21 Nov 2024, 03:08 PM",
+                          text: state.forDetail?.rejectedOn ?? "-",
                           style: TextStyle(fontSize: 15, fontWeight: FontWeight.w500, color: context.appColors.textBlack),
                         ),
                       ],
@@ -119,7 +125,9 @@ class DetailNotApprovedFragment extends HookConsumerWidget {
           Row(
             children: [
               MyButton(
-                onPressed: () {},
+                onPressed: () {
+                  ComponentServiceManager().mainService.startFeedbackCreatePage(context: context);
+                },
                 text: S.current.send_feedback,
                 textColor: Colors.white,
                 fontSize: 15,
@@ -129,7 +137,15 @@ class DetailNotApprovedFragment extends HookConsumerWidget {
               ).expanded(),
               const SizedBox(width: 10),
               MyButton(
-                onPressed: () {},
+                onPressed: () {
+                  FormTermsPage.startInstance(
+                      formType: state.typeId ?? "",
+                      estateFormId: state.estateFormId,
+                      formItem: null,
+                      enableEdit: false,
+                      formContent: state.forDetail?.content,
+                  );
+                },
                 text: S.current.view_application,
                 textColor: Colors.white,
                 fontSize: 15,

+ 23 - 7
packages/cpt_form/lib/modules/detail/detail_processing_fragment.dart

@@ -5,14 +5,21 @@ import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/src/widgets/framework.dart';
 import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/componentRouter/component_service_manager.dart';
 import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_button.dart';
 import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 
+import '../apply/form_terms_page.dart';
+import '../form/form_types.dart';
+import 'form_detail_view_model.dart';
+
 class DetailProcessingFragment extends HookConsumerWidget {
   @override
   Widget build(BuildContext context, WidgetRef ref) {
+    final state = ref.watch(formDetailViewModelProvider);
+
     return SizedBox(
       width: double.infinity,
       height: double.infinity,
@@ -53,12 +60,12 @@ class DetailProcessingFragment extends HookConsumerWidget {
                           text: S.current.send_on_sometime(' '),
                         ),
                         TextSpan(
-                          text: "21 Nov 2024, 03:08 PM",
+                          text: state.forDetail?.sentOn ?? "-",
                           style: TextStyle(fontSize: 15, fontWeight: FontWeight.w500, color: context.appColors.textBlack),
                         ),
                       ],
                     ),
-                  ).marginOnly(top: 12,bottom: 28),
+                  ).marginOnly(top: 12, bottom: 28),
 
                   //图片
                   const MyAssetImage(
@@ -88,7 +95,7 @@ class DetailProcessingFragment extends HookConsumerWidget {
                   Align(
                     alignment: Alignment.centerLeft, // 左对齐
                     child: MyTextView(
-                      "Access Card - Owner",
+                      FormTypes.iconMap[state.typeId]?['name'],
                       marginTop: 22,
                       marginBottom: 12,
                       marginLeft: 18,
@@ -101,7 +108,7 @@ class DetailProcessingFragment extends HookConsumerWidget {
                   Align(
                     alignment: Alignment.centerLeft, // 左对齐
                     child: MyTextView(
-                      "Damaged or faulty",
+                      state.forDetail?.content?.typeOfApplication ?? "-",
                       marginBottom: 22,
                       marginLeft: 18,
                       textColor: context.appColors.textBlack,
@@ -109,7 +116,6 @@ class DetailProcessingFragment extends HookConsumerWidget {
                       isFontMedium: true,
                     ),
                   ),
-
                 ],
               ),
             ),
@@ -117,7 +123,9 @@ class DetailProcessingFragment extends HookConsumerWidget {
           Row(
             children: [
               MyButton(
-                onPressed: () {},
+                onPressed: () {
+                  ComponentServiceManager().mainService.startFeedbackCreatePage(context: context);
+                },
                 text: S.current.send_feedback,
                 textColor: Colors.white,
                 fontSize: 15,
@@ -127,7 +135,15 @@ class DetailProcessingFragment extends HookConsumerWidget {
               ).expanded(),
               const SizedBox(width: 10),
               MyButton(
-                onPressed: () {},
+                onPressed: () {
+                  FormTermsPage.startInstance(
+                    formType: state.typeId ?? "",
+                    estateFormId: state.estateFormId,
+                    formItem: null,
+                    enableEdit: false,
+                    formContent: state.forDetail?.content,
+                  );
+                },
                 text: S.current.view_application,
                 textColor: Colors.white,
                 fontSize: 15,

+ 13 - 7
packages/cpt_form/lib/modules/detail/form_detail_page.dart

@@ -17,25 +17,28 @@ import 'form_detail_view_model.dart';
 
 @RoutePage()
 class FormDetailPage extends HookConsumerWidget {
-  final String applyId;
+  final String estateFormId;
+  final String taskId;
   final String type;
 
   const FormDetailPage({
     Key? key,
-    @PathParam() required this.applyId,
+    @PathParam() required this.estateFormId,
+    @PathParam() required this.taskId,
     @PathParam() required this.type,
   }) : super(key: key);
 
   //启动当前页面
   static void startInstance({
     BuildContext? context,
-    required String applyId,
+    required String estateFormId,
+    required String taskId,
     required String type,
   }) {
     if (context != null) {
-      context.router.push(FormDetailPageRoute(applyId: applyId, type: type));
+      context.router.push(FormDetailPageRoute(estateFormId: estateFormId, taskId: taskId, type: type));
     } else {
-      appRouter.push(FormDetailPageRoute(applyId: applyId, type: type));
+      appRouter.push(FormDetailPageRoute(estateFormId: estateFormId, taskId: taskId, type: type));
     }
   }
 
@@ -46,7 +49,10 @@ class FormDetailPage extends HookConsumerWidget {
 
     useEffect(() {
       // 组件挂载时执行 - 执行接口请求
-      Future.microtask(() => viewModel.fetchFormDetail());
+      Future.microtask((){
+        viewModel.setType(type);
+        viewModel.fetchFormDetail(estateFormId, taskId);
+      });
       return () {
         // 组件卸载时执行
       };
@@ -62,7 +68,7 @@ class FormDetailPage extends HookConsumerWidget {
             state: state.loadingState,
             errorMessage: state.errorMessage,
             errorRetry: () {
-              viewModel.retryRequest();
+              viewModel.retryRequest(estateFormId, taskId);
             },
             successWidget: state.status == 0
                 ? DetailProcessingFragment()

+ 16 - 0
packages/cpt_form/lib/modules/detail/form_detail_state.dart

@@ -1,3 +1,5 @@
+import 'package:domain/entity/form_content_entity.dart';
+import 'package:domain/entity/form_detail_entity.dart';
 import 'package:widgets/load_state_layout.dart';
 
 class FormDetailState{
@@ -8,23 +10,37 @@ class FormDetailState{
 
   int status;  // 0是Pending , 1是Approve , 2是Not Approve
 
+  FormDetailEntity? forDetail;
+
+  String? typeId;
+  String? estateFormId;
+
   // ===================================  Begin  ↓  ===================================
 
   FormDetailState({
     this.loadingState = LoadState.State_Loading,
     this.errorMessage,
     this.status = 0,
+    this.forDetail,
+    this.typeId,
+    this.estateFormId,
   });
 
   FormDetailState copyWith({
     LoadState? loadingState,
     String? errorMessage,
+    String? typeId,
+    String? estateFormId,
     int? status,
+    FormDetailEntity? forDetail,
   }) {
     return FormDetailState(
       errorMessage: errorMessage ?? this.errorMessage,
       loadingState: loadingState ?? this.loadingState,
       status: status ?? this.status,
+      forDetail: forDetail ?? this.forDetail,
+      typeId: typeId ?? this.typeId,
+      estateFormId: estateFormId ?? this.estateFormId,
     );
   }
 

+ 22 - 9
packages/cpt_form/lib/modules/detail/form_detail_view_model.dart

@@ -1,3 +1,5 @@
+import 'package:domain/repository/form_repository.dart';
+import 'package:plugin_platform/http/dio/dio_cancelable_mixin.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:widgets/load_state_layout.dart';
 
@@ -6,26 +8,37 @@ import 'form_detail_state.dart';
 part 'form_detail_view_model.g.dart';
 
 @riverpod
-class FormDetailViewModel extends _$FormDetailViewModel {
+class FormDetailViewModel extends _$FormDetailViewModel with DioCancelableMixin {
+  late final FormRepository _formRepository;
+
   @override
   FormDetailState build() {
-    return FormDetailState();
+    _formRepository = ref.read(formRepositoryProvider);
+    final state = FormDetailState();
+    registerCancellation();
+    return state;
+  }
+
+  void setType(String type) {
+    state = state.copyWith(typeId: type);
   }
 
-  void retryRequest() {
-    fetchFormDetail();
+  void retryRequest(String? estateFormId, String? taskId) {
+    fetchFormDetail(estateFormId, taskId);
   }
 
   //获取表单的详情数据
-  void fetchFormDetail() async {
+  void fetchFormDetail(String? estateFormId, String? taskId) async {
     //显示加载数据
     state = state.copyWith(loadingState: LoadState.State_Loading);
 
-    await Future.delayed(const Duration(milliseconds: 1500));
+    final result = await _formRepository.fetchFormDetail(estateFormId: estateFormId, taskId: taskId);
 
     //根据后端返回的数据赋值状态
-    state = state.copyWith(loadingState: LoadState.State_Success, status: 2);
-
-
+    if (result.isSuccess) {
+      state = state.copyWith(loadingState: LoadState.State_Success, status: result.data?.status, forDetail: result.data, estateFormId: estateFormId);
+    } else {
+      state = state.copyWith(loadingState: LoadState.State_Error, errorMessage: result.errorMsg);
+    }
   }
 }

+ 1 - 1
packages/cpt_form/lib/modules/detail/form_detail_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'form_detail_view_model.dart';
 // **************************************************************************
 
 String _$formDetailViewModelHash() =>
-    r'ff75168453999e002ef05e85ede97021615b2181';
+    r'cb3ec02850ae818982d6358f0935b09546515ba1';
 
 /// See also [FormDetailViewModel].
 @ProviderFor(FormDetailViewModel)

+ 6 - 1
packages/cpt_form/lib/modules/form/apply/form_apply_screen.dart

@@ -43,7 +43,12 @@ class FormApplyScreen extends HookConsumerWidget {
               (context, index) {
                 return FormApplyItem(index: index, item: state.datas[index]).onTap(() {
                   //进入申请的协议页面
-                  FormTermsPage.startInstance(formType: state.datas[index].typeId!);
+                  FormTermsPage.startInstance(
+                    formType: state.datas[index].typeId!,
+                    estateFormId: null,
+                    formItem: state.datas[index],
+                    enableEdit: true,
+                  );
                 });
               },
               childCount: state.datas.length,

+ 1 - 1
packages/cpt_form/lib/modules/form/apply/form_apply_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'form_apply_view_model.dart';
 // **************************************************************************
 
 String _$formApplyViewModelHash() =>
-    r'1fba2b4d77c876507a8138c25ccf205d2b819f72';
+    r'6ec50f08281d0d52345741459787d25046f77be2';
 
 /// See also [FormApplyViewModel].
 @ProviderFor(FormApplyViewModel)

+ 7 - 4
packages/cpt_form/lib/modules/form/approve/form_approve_screen.dart

@@ -45,18 +45,21 @@ class FormApproveScreen extends HookConsumerWidget {
             SliverList(
                 delegate: SliverChildBuilderDelegate(
               (context, index) {
-                return FormApproveItem(index: index, item: state.datas[index]).onTap((){
+                return FormApproveItem(index: index, item: state.datas[index]).onTap(() {
                   //去详情页面
-                  FormDetailPage.startInstance(context: context, applyId: "123", type: state.datas[index].estateOnlineForm?.type?.id ?? "");
+                  FormDetailPage.startInstance(
+                    context: context,
+                    estateFormId: state.datas[index].estateOnlineFormId ?? "",
+                    taskId: state.datas[index].id ?? "",
+                    type: state.datas[index].estateOnlineForm?.type?.id ?? "",
+                  );
                 });
               },
               childCount: state.datas.length,
             )),
-
           ],
         ),
       ).marginOnly(top: 5, bottom: 5),
     );
   }
-
 }

+ 1 - 1
packages/cpt_form/lib/modules/form/approve/form_approve_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'form_approve_view_model.dart';
 // **************************************************************************
 
 String _$formApproveViewModelHash() =>
-    r'040c903a0f3423ebccf00bf1fcaed1f0361a7ed6';
+    r'88b513f846a7e885ee951878529e54a0f63d5e67';
 
 /// See also [FormApproveViewModel].
 @ProviderFor(FormApproveViewModel)

+ 191 - 189
packages/cpt_form/lib/modules/form/form_types.dart

@@ -121,195 +121,197 @@ class FormTypes {
   // ===================================  Begin  ↓  ===================================
 
   //type类型对应的详情页面组与对应的数据
-  static Map<String, Map<String, dynamic>> detailPageMap = {
-    //Access Card-Owner
-    '1': {
-      'title': S.current.access_card_owner,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.typeOfApplication,
-        DetailPageType.note2Management,
-        DetailPageType.payment,
-      ],
-      'detail_data': {
-        'note_management_txt': S.current.access_card_desc,
-        'signature_txt': S.current.signature_access_card,
-      }
-    },
-    //Access Card-Tenant
-    '2': {
-      'title': S.current.access_card_tenant,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.typeOfApplication,
-        DetailPageType.attachment,
-        DetailPageType.note2Management,
-        DetailPageType.payment,
-      ],
-      'detail_data': {
-        'attachment_txt': S.current.access_card_tenant_letter,
-        'note_management_txt': S.current.access_card_desc,
-        'signature_txt': S.current.signature_access_card,
-      }
-    },
-    //Car Park Cancellation
-    '3': {
-      'title': S.current.car_park_cancellation,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.vehicleInfo,
-        DetailPageType.note2Management,
-        DetailPageType.signature,
-      ],
-      'detail_data': {
-        'note_management_txt': '${S.current.car_cancel_txt}\n\n${S.current.car_cancel_txt_1}\n${S.current.car_cancel_txt_2}',
-        'signature_txt': S.current.signature_vehicle,
-      }
-    },
-    //Moving In
-    '4': {
-      'title': S.current.moving_in,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.movingDate,
-        DetailPageType.movingCompany,
-        DetailPageType.note2Management,
-        DetailPageType.payment,
-      ],
-      'detail_data': {
-        'note_management_txt': S.current.moving_in_msg,
-        'signature_txt': S.current.signature_moving,
-      }
-    },
-    //Moving Out
-    '5': {
-      'title': S.current.moving_out,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.movingDate,
-        DetailPageType.movingCompany,
-        DetailPageType.note2Management,
-        DetailPageType.payment,
-      ],
-      'detail_data': {
-        'note_management_txt': S.current.moving_in_msg,
-        'signature_txt': S.current.signature_moving,
-      }
-    },
-    //Overnight Parking
-    '6': {
-      'title': S.current.overnight_parking,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.guestVehicleInfo,
-        DetailPageType.note2Management,
-        DetailPageType.signature,
-      ],
-      'detail_data': {
-        'note_management_txt': S.current.overnight_parking_msg,
-        'signature_txt': S.current.signature_vehicle,
-      }
-    },
-    //Registration of 2nd Vehicle
-    '7': {
-      'title': S.current.registration_of_2_vehicle,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.vehicleInfo,
-        DetailPageType.attachment,
-        DetailPageType.note2Management,
-        DetailPageType.signature,
-      ],
-      'detail_data': {
-        'attachment_txt': '${S.current.label_txt}\n\n${S.current.label_txt_1}\n\n${S.current.label_txt_2}\n\n${S.current.label_txt_3}',
-        'note_management_txt': S.current.moving_in_msg,
-        'signature_txt': S.current.signature_vehicle,
-      }
-    },
-    //Renovation
-    '8': {
-      'title': S.current.renovation,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.renovationDate,
-        DetailPageType.renovationCompany,
-        DetailPageType.largeTextBox,
-        DetailPageType.attachment,
-        DetailPageType.note2Management,
-        DetailPageType.payment,
-      ],
-      'detail_data': {
-        'large_txt': S.current.list_of_renovation_works,
-        'attachment_txt': S.current.renovation_attachments,
-        'note_management_txt': S.current.renovation_note,
-        'signature_txt': S.current.signature_renovation,
-      }
-    },
-    //Re-Registration of 1st Vehicle-Owner
-    '9': {
-      'title': S.current.re_registration_of_1_vehicle_owner,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.vehicleInfo,
-        DetailPageType.attachment,
-        DetailPageType.note2Management,
-        DetailPageType.signature,
-      ],
-      'detail_data': {
-        'attachment_txt': '${S.current.label_txt}\n\n${S.current.label_txt_1}\n\n${S.current.label_txt_2}\n\n${S.current.label_txt_3}',
-        'note_management_txt': S.current.moving_in_msg,
-        'signature_txt': S.current.signature_vehicle,
-      }
-    },
-    //Re-Registration of 1st Vehicle-Owner
-    '10': {
-      'title': S.current.re_registration_of_1_vehicle_tenant,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.vehicleInfo,
-        DetailPageType.attachment,
-        DetailPageType.note2Management,
-        DetailPageType.signature,
-      ],
-      'detail_data': {
-        'attachment_txt': '${S.current.label_txt}\n\n${S.current.label_txt_1}\n\n${S.current.label_txt_2}\n\n${S.current.label_txt_3}',
-        'note_management_txt': S.current.moving_in_msg,
-        'signature_txt': S.current.signature_vehicle,
-      }
-    },
-    //Re-Registration of Bicycles
-    '11': {
-      'title': S.current.re_registration_of_bicycle,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.typeOfApplication,
-        DetailPageType.attachment,
-        DetailPageType.note2Management,
-        DetailPageType.signature,
-      ],
-      'detail_data': {
-        'attachment_txt': S.current.bicycle_desc,
-        'note_management_txt': S.current.bicycle_note,
-        'signature_txt': S.current.signature_bicycle,
-      }
-    },
-    //Vehicle Label Replacement
-    '12': {
-      'title': S.current.vehicle_label_replacement,
-      'term_url': 'https://lehuoer.com/privacy.html',
-      'detail_pages': [
-        DetailPageType.typeOfApplication,
-        DetailPageType.attachment,
-        DetailPageType.note2Management,
-        DetailPageType.payment,
-      ],
-      'detail_data': {
-        'attachment_txt': '${S.current.label_txt}\n\n${S.current.label_txt_1}\n\n${S.current.label_txt_2}\n\n${S.current.label_txt_3}',
-        'note_management_txt': S.current.label_replace_note,
-        'signature_txt': S.current.signature_vehicle,
-      }
-    },
-  };
+  static Map<String, Map<String, dynamic>> buildDetailPageMap(bool enableEdit) {
+    return {
+      //Access Card-Owner
+      '1': {
+        'title': S.current.access_card_owner,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.typeOfApplication,
+          DetailPageType.note2Management,
+          enableEdit ? DetailPageType.payment : DetailPageType.signature,
+        ],
+        'detail_data': {
+          'note_management_txt': S.current.access_card_desc,
+          'signature_txt': S.current.signature_access_card,
+        }
+      },
+      //Access Card-Tenant
+      '2': {
+        'title': S.current.access_card_tenant,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.typeOfApplication,
+          DetailPageType.attachment,
+          DetailPageType.note2Management,
+          enableEdit ? DetailPageType.payment : DetailPageType.signature,
+        ],
+        'detail_data': {
+          'attachment_txt': S.current.access_card_tenant_letter,
+          'note_management_txt': S.current.access_card_desc,
+          'signature_txt': S.current.signature_access_card,
+        }
+      },
+      //Car Park Cancellation
+      '3': {
+        'title': S.current.car_park_cancellation,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.vehicleInfo,
+          DetailPageType.note2Management,
+          DetailPageType.signature,
+        ],
+        'detail_data': {
+          'note_management_txt': '${S.current.car_cancel_txt}\n\n${S.current.car_cancel_txt_1}\n${S.current.car_cancel_txt_2}',
+          'signature_txt': S.current.signature_vehicle,
+        }
+      },
+      //Moving In
+      '4': {
+        'title': S.current.moving_in,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.movingDate,
+          DetailPageType.movingCompany,
+          DetailPageType.note2Management,
+          enableEdit ? DetailPageType.payment : DetailPageType.signature,
+        ],
+        'detail_data': {
+          'note_management_txt': S.current.moving_in_msg,
+          'signature_txt': S.current.signature_moving,
+        }
+      },
+      //Moving Out
+      '5': {
+        'title': S.current.moving_out,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.movingDate,
+          DetailPageType.movingCompany,
+          DetailPageType.note2Management,
+          enableEdit ? DetailPageType.payment : DetailPageType.signature,
+        ],
+        'detail_data': {
+          'note_management_txt': S.current.moving_in_msg,
+          'signature_txt': S.current.signature_moving,
+        }
+      },
+      //Overnight Parking
+      '6': {
+        'title': S.current.overnight_parking,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.guestVehicleInfo,
+          DetailPageType.note2Management,
+          DetailPageType.signature,
+        ],
+        'detail_data': {
+          'note_management_txt': S.current.overnight_parking_msg,
+          'signature_txt': S.current.signature_vehicle,
+        }
+      },
+      //Registration of 2nd Vehicle
+      '7': {
+        'title': S.current.registration_of_2_vehicle,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.vehicleInfo,
+          DetailPageType.attachment,
+          DetailPageType.note2Management,
+          DetailPageType.signature,
+        ],
+        'detail_data': {
+          'attachment_txt': '${S.current.label_txt}\n\n${S.current.label_txt_1}\n\n${S.current.label_txt_2}\n\n${S.current.label_txt_3}',
+          'note_management_txt': S.current.moving_in_msg,
+          'signature_txt': S.current.signature_vehicle,
+        }
+      },
+      //Renovation
+      '8': {
+        'title': S.current.renovation,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.renovationDate,
+          DetailPageType.renovationCompany,
+          DetailPageType.largeTextBox,
+          DetailPageType.attachment,
+          DetailPageType.note2Management,
+          enableEdit ? DetailPageType.payment : DetailPageType.signature,
+        ],
+        'detail_data': {
+          'large_txt': S.current.list_of_renovation_works,
+          'attachment_txt': S.current.renovation_attachments,
+          'note_management_txt': S.current.renovation_note,
+          'signature_txt': S.current.signature_renovation,
+        }
+      },
+      //Re-Registration of 1st Vehicle-Owner
+      '9': {
+        'title': S.current.re_registration_of_1_vehicle_owner,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.vehicleInfo,
+          DetailPageType.attachment,
+          DetailPageType.note2Management,
+          DetailPageType.signature,
+        ],
+        'detail_data': {
+          'attachment_txt': '${S.current.label_txt}\n\n${S.current.label_txt_1}\n\n${S.current.label_txt_2}\n\n${S.current.label_txt_3}',
+          'note_management_txt': S.current.moving_in_msg,
+          'signature_txt': S.current.signature_vehicle,
+        }
+      },
+      //Re-Registration of 1st Vehicle-Owner
+      '10': {
+        'title': S.current.re_registration_of_1_vehicle_tenant,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.vehicleInfo,
+          DetailPageType.attachment,
+          DetailPageType.note2Management,
+          DetailPageType.signature,
+        ],
+        'detail_data': {
+          'attachment_txt': '${S.current.label_txt}\n\n${S.current.label_txt_1}\n\n${S.current.label_txt_2}\n\n${S.current.label_txt_3}',
+          'note_management_txt': S.current.moving_in_msg,
+          'signature_txt': S.current.signature_vehicle,
+        }
+      },
+      //Re-Registration of Bicycles
+      '11': {
+        'title': S.current.re_registration_of_bicycle,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.typeOfApplication,
+          DetailPageType.attachment,
+          DetailPageType.note2Management,
+          DetailPageType.signature,
+        ],
+        'detail_data': {
+          'attachment_txt': S.current.bicycle_desc,
+          'note_management_txt': S.current.bicycle_note,
+          'signature_txt': S.current.signature_bicycle,
+        }
+      },
+      //Vehicle Label Replacement
+      '12': {
+        'title': S.current.vehicle_label_replacement,
+        'term_url': 'https://lehuoer.com/privacy.html',
+        'detail_pages': [
+          DetailPageType.typeOfApplication,
+          DetailPageType.attachment,
+          DetailPageType.note2Management,
+          enableEdit ? DetailPageType.payment : DetailPageType.signature,
+        ],
+        'detail_data': {
+          'attachment_txt': '${S.current.label_txt}\n\n${S.current.label_txt_1}\n\n${S.current.label_txt_2}\n\n${S.current.label_txt_3}',
+          'note_management_txt': S.current.label_replace_note,
+          'signature_txt': S.current.signature_vehicle,
+        }
+      },
+    };
+  }
 
   // ===================================  Begin  ↓  ===================================
 

+ 7 - 1
packages/cpt_form/lib/modules/form/not_approve/form_not_approve_screen.dart

@@ -43,7 +43,13 @@ class FormNotApproveScreen extends HookConsumerWidget {
               (context, index) {
                 return FormNotApproveItem(index: index, item: state.datas[index]).onTap(() {
                   //去详情页面
-                  FormDetailPage.startInstance(context: context, applyId: "123", type: state.datas[index].estateOnlineForm?.type?.id ?? "");
+                  //去详情页面
+                  FormDetailPage.startInstance(
+                    context: context,
+                    estateFormId: state.datas[index].estateOnlineFormId ?? "",
+                    taskId: state.datas[index].id ?? "",
+                    type: state.datas[index].estateOnlineForm?.type?.id ?? "",
+                  );
                 });
               },
               childCount: state.datas.length,

+ 1 - 1
packages/cpt_form/lib/modules/form/not_approve/form_not_approve_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'form_not_approve_view_model.dart';
 // **************************************************************************
 
 String _$formNotApproveViewModelHash() =>
-    r'e763ac3aeaf6d5d97bf617a49cd180c672d8cf12';
+    r'3ec09df3be6c4bd9d78333952d83c831938d2111';
 
 /// See also [FormNotApproveViewModel].
 @ProviderFor(FormNotApproveViewModel)

+ 7 - 1
packages/cpt_form/lib/modules/form/submit/form_submit_screen.dart

@@ -44,7 +44,13 @@ class FormSubmitScreen extends HookConsumerWidget {
               (context, index) {
                 return FormSubmitItem(index: index, item: state.datas[index]).onTap(() {
                   //去详情页面
-                  FormDetailPage.startInstance(context: context, applyId: "123", type: state.datas[index].estateOnlineForm?.type?.id ?? "");
+                  //去详情页面
+                  FormDetailPage.startInstance(
+                    context: context,
+                    estateFormId: state.datas[index].estateOnlineFormId ?? "",
+                    taskId: state.datas[index].id ?? "",
+                    type: state.datas[index].estateOnlineForm?.type?.id ?? "",
+                  );
                 });
               },
               childCount: state.datas.length,

+ 1 - 1
packages/cpt_form/lib/modules/form/submit/form_submit_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'form_submit_view_model.dart';
 // **************************************************************************
 
 String _$formSubmitViewModelHash() =>
-    r'b5bfc8957a27fa130bb00ea057ca2b7d52957740';
+    r'87ef17cca1f53c2e845733c2d08b3d5e97bc7845';
 
 /// See also [FormSubmitViewModel].
 @ProviderFor(FormSubmitViewModel)

+ 3 - 2
packages/cpt_form/lib/router/page/form_page_router.dart

@@ -22,7 +22,8 @@ import '../../modules/apply/type_of_application_page.dart';
 import '../../modules/apply/vehicle_info_page.dart';
 import '../../modules/apply/form_terms_page.dart';
 import '../../modules/detail/form_detail_page.dart';
-
+import 'package:domain/entity/form_list_entity.dart';
+import 'package:domain/entity/form_content_entity.dart';
 part 'form_page_router.gr.dart';
 
 /*\
@@ -55,7 +56,7 @@ class FormPageRouter extends _$FormPageRouter {
         CustomRoute(page: SignaturePageRoute.page, path: RouterPath.formSignature, transitionsBuilder: applySlideTransition),
         CustomRoute(page: TypeOfApplicationPageRoute.page, path: RouterPath.formTypeOfApplication, transitionsBuilder: applySlideTransition),
         CustomRoute(page: VehicleInfoPageRoute.page, path: RouterPath.formVehicleInfo, transitionsBuilder: applySlideTransition),
-        CustomRoute(page: FormTermsPageRoute.page, path: "${RouterPath.formTerms}:type", transitionsBuilder: applySlideTransition),
+        CustomRoute(page: FormTermsPageRoute.page, path: RouterPath.formTerms, transitionsBuilder: applySlideTransition),
         CustomRoute(page: FormDetailPageRoute.page, path: "${RouterPath.formDetail}:applyId/:type", transitionsBuilder: applySlideTransition),
       ];
 }

+ 42 - 14
packages/cpt_form/lib/router/page/form_page_router.gr.dart

@@ -37,14 +37,16 @@ abstract class _$FormPageRouter extends RootStackRouter {
       final pathParams = routeData.inheritedPathParams;
       final args = routeData.argsAs<FormDetailPageRouteArgs>(
           orElse: () => FormDetailPageRouteArgs(
-                applyId: pathParams.getString('applyId'),
+                estateFormId: pathParams.getString('estateFormId'),
+                taskId: pathParams.getString('taskId'),
                 type: pathParams.getString('type'),
               ));
       return AutoRoutePage<dynamic>(
         routeData: routeData,
         child: FormDetailPage(
           key: args.key,
-          applyId: args.applyId,
+          estateFormId: args.estateFormId,
+          taskId: args.taskId,
           type: args.type,
         ),
       );
@@ -74,15 +76,16 @@ abstract class _$FormPageRouter extends RootStackRouter {
       );
     },
     FormTermsPageRoute.name: (routeData) {
-      final pathParams = routeData.inheritedPathParams;
-      final args = routeData.argsAs<FormTermsPageRouteArgs>(
-          orElse: () =>
-              FormTermsPageRouteArgs(type: pathParams.getString('type')));
+      final args = routeData.argsAs<FormTermsPageRouteArgs>();
       return AutoRoutePage<dynamic>(
         routeData: routeData,
         child: FormTermsPage(
           key: args.key,
           type: args.type,
+          estateFormId: args.estateFormId,
+          formItem: args.formItem,
+          enableEdit: args.enableEdit,
+          formContent: args.formContent,
         ),
       );
     },
@@ -196,18 +199,21 @@ class FormApprovePageRoute extends PageRouteInfo<void> {
 class FormDetailPageRoute extends PageRouteInfo<FormDetailPageRouteArgs> {
   FormDetailPageRoute({
     Key? key,
-    required String applyId,
+    required String estateFormId,
+    required String taskId,
     required String type,
     List<PageRouteInfo>? children,
   }) : super(
           FormDetailPageRoute.name,
           args: FormDetailPageRouteArgs(
             key: key,
-            applyId: applyId,
+            estateFormId: estateFormId,
+            taskId: taskId,
             type: type,
           ),
           rawPathParams: {
-            'applyId': applyId,
+            'estateFormId': estateFormId,
+            'taskId': taskId,
             'type': type,
           },
           initialChildren: children,
@@ -222,19 +228,22 @@ class FormDetailPageRoute extends PageRouteInfo<FormDetailPageRouteArgs> {
 class FormDetailPageRouteArgs {
   const FormDetailPageRouteArgs({
     this.key,
-    required this.applyId,
+    required this.estateFormId,
+    required this.taskId,
     required this.type,
   });
 
   final Key? key;
 
-  final String applyId;
+  final String estateFormId;
+
+  final String taskId;
 
   final String type;
 
   @override
   String toString() {
-    return 'FormDetailPageRouteArgs{key: $key, applyId: $applyId, type: $type}';
+    return 'FormDetailPageRouteArgs{key: $key, estateFormId: $estateFormId, taskId: $taskId, type: $type}';
   }
 }
 
@@ -300,14 +309,21 @@ class FormTermsPageRoute extends PageRouteInfo<FormTermsPageRouteArgs> {
   FormTermsPageRoute({
     Key? key,
     required String type,
+    String? estateFormId,
+    FormListEntity? formItem,
+    required bool enableEdit,
+    FormContentEntity? formContent,
     List<PageRouteInfo>? children,
   }) : super(
           FormTermsPageRoute.name,
           args: FormTermsPageRouteArgs(
             key: key,
             type: type,
+            estateFormId: estateFormId,
+            formItem: formItem,
+            enableEdit: enableEdit,
+            formContent: formContent,
           ),
-          rawPathParams: {'type': type},
           initialChildren: children,
         );
 
@@ -321,15 +337,27 @@ class FormTermsPageRouteArgs {
   const FormTermsPageRouteArgs({
     this.key,
     required this.type,
+    this.estateFormId,
+    this.formItem,
+    required this.enableEdit,
+    this.formContent,
   });
 
   final Key? key;
 
   final String type;
 
+  final String? estateFormId;
+
+  final FormListEntity? formItem;
+
+  final bool enableEdit;
+
+  final FormContentEntity? formContent;
+
   @override
   String toString() {
-    return 'FormTermsPageRouteArgs{key: $key, type: $type}';
+    return 'FormTermsPageRouteArgs{key: $key, type: $type, estateFormId: $estateFormId, formItem: $formItem, enableEdit: $enableEdit, formContent: $formContent}';
   }
 }
 

+ 1 - 1
packages/cpt_main/lib/modules/feedback/create_success/feedback_create_success_page.dart

@@ -55,7 +55,7 @@ class FeedbackCreateSuccessPage extends HookConsumerWidget {
 
           MyButton(
             onPressed: () {
-              MainPage.startInstance(context: context);
+              appRouter.maybePop();
             },
             text: S.current.back_home,
             textColor: Colors.white,

+ 5 - 1
packages/cpt_main/lib/router/component/main_component_service_impl.dart

@@ -5,6 +5,8 @@ import 'package:cpt_main/modules/main/main_page.dart';
 import 'package:flutter/material.dart';
 import 'package:router/componentRouter/main_service.dart';
 
+import '../../modules/feedback/create/feedback_create_page.dart';
+
 class MainComponentServiceImpl extends MainService {
   @override
   void startMainPage({BuildContext? context}) {
@@ -12,6 +14,8 @@ class MainComponentServiceImpl extends MainService {
   }
 
   @override
-  void startSettingPage({BuildContext? context}) {}
+  void startFeedbackCreatePage({BuildContext? context}) {
+    FeedbackCreatePage.startInstance(context: context);
+  }
 }
 

+ 9 - 0
packages/cs_domain/lib/constants/api_constants.dart

@@ -90,6 +90,15 @@ class ApiConstants {
   // 在线表单的已提交的申请
   static const apiFormSubmittedList = "/api/v1/user/online-form/submitted/index";
 
+  //在线表单的选项列表
+  static const apiFormOption = "/api/v1/user/online-form/form/options";
+
+  //在线表单的提交,注意后面要拼接type
+  static const apiFormSubmit = "/api/v1/user/online-form/apply/submit/";
+
+  //在线表单的提交详情
+  static const apiFormDetail = "/api/v1/user/online-form/apply/detail";
+
   // =========================== 其他 ↓=========================================
 
   //服务器时间

+ 164 - 0
packages/cs_domain/lib/entity/form_content_entity.dart

@@ -0,0 +1,164 @@
+import 'dart:typed_data';
+
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/form_content_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/form_content_entity.g.dart';
+
+/*
+ * 这是Form表单的入参和出参的对象,12种类型全部整合在一个对象中
+ */
+@JsonSerializable()
+class FormContentEntity {
+  @JSONField(name: "type_of_application")
+  String? typeOfApplication;
+  @JSONField(name: "notes_to_recipient")
+  String? notesToRecipient;
+  @JSONField(name: "notes_to_management")
+  String? notesToManagement;
+  List<String>? attachments;
+  String? signature;
+  dynamic signatureByteData = null; //签名的ByteData数据
+
+  //汽车相关
+  @JSONField(name: "ownership_status")
+  String? ownershipStatus;
+  @JSONField(name: "vehicle_number")
+  String? vehicleNumber;
+  @JSONField(name: "iu_number")
+  String? iuNumber;
+  @JSONField(name: "vehicle_make_model_colour")
+  String? vehicleMakeModelColour;
+
+  //搬家相关
+  @JSONField(name: "start_date")
+  String? startDate;
+  @JSONField(name: "end_date")
+  String? endDate;
+  @JSONField(name: "time_or_arrival")
+  String? timeOrArrival;
+  @JSONField(name: "moving_company")
+  String? movingCompany;
+  @JSONField(name: "person_in_charge")
+  String? personInCharge;
+  @JSONField(name: "mobile_number")
+  String? mobileNumber;
+  @JSONField(name: "company_address")
+  String? companyAddress;
+
+  //停车过夜
+  @JSONField(name: "date_of_entry")
+  String? dateOfEntry;
+  @JSONField(name: "guest_name")
+  String? guestName;
+  @JSONField(name: "guest_mobile_number")
+  String? guestMobileNumber;
+
+  //装修
+  @JSONField(name: "renovation_start_date")
+  String? renovationStartDate;
+  @JSONField(name: "renovation_end_date")
+  String? renovationEndDate;
+  @JSONField(name: "hacking_start_date")
+  String? hackingStartDate;
+  @JSONField(name: "hacking_end_date")
+  String? hackingEndDate;
+  @JSONField(name: "renovation_company")
+  String? renovationCompany;
+  @JSONField(name: "list_of_renovation_works")
+  String? listOfRenovationWorks;
+
+
+  factory FormContentEntity.fromJson(Map<String, dynamic> json) => $FormContentEntityFromJson(json);
+
+  Map<String, dynamic> toJson() => $FormContentEntityToJson(this);
+
+  @override
+  String toString() {
+    return jsonEncode(this);
+  }
+
+  FormContentEntity({
+    this.typeOfApplication,
+    this.notesToRecipient,
+    this.notesToManagement,
+    this.attachments,
+    this.signature,
+    this.ownershipStatus,
+    this.vehicleNumber,
+    this.iuNumber,
+    this.vehicleMakeModelColour,
+    this.startDate,
+    this.endDate,
+    this.timeOrArrival,
+    this.movingCompany,
+    this.personInCharge,
+    this.mobileNumber,
+    this.companyAddress,
+    this.dateOfEntry,
+    this.guestName,
+    this.guestMobileNumber,
+    this.renovationStartDate,
+    this.renovationEndDate,
+    this.hackingStartDate,
+    this.hackingEndDate,
+    this.renovationCompany,
+    this.listOfRenovationWorks,
+  });
+
+  FormContentEntity copyWith({
+    String? typeOfApplication,
+    String? notesToRecipient,
+    String? notesToManagement,
+    List<String>? attachments,
+    String? signature,
+    String? ownershipStatus,
+    String? vehicleNumber,
+    String? iuNumber,
+    String? vehicleMakeModelColour,
+    String? startDate,
+    String? endDate,
+    String? timeOrArrival,
+    String? movingCompany,
+    String? personInCharge,
+    String? mobileNumber,
+    String? companyAddress,
+    String? dateOfEntry,
+    String? guestName,
+    String? guestMobileNumber,
+    String? renovationStartDate,
+    String? renovationEndDate,
+    String? hackingStartDate,
+    String? hackingEndDate,
+    String? renovationCompany,
+    String? listOfRenovationWorks,
+  }) {
+    return FormContentEntity(
+      typeOfApplication: typeOfApplication ?? this.typeOfApplication,
+      notesToRecipient: notesToRecipient ?? this.notesToRecipient,
+      notesToManagement: notesToManagement ?? this.notesToManagement,
+      attachments: attachments ?? this.attachments,
+      signature: signature ?? this.signature,
+      ownershipStatus: ownershipStatus ?? this.ownershipStatus,
+      vehicleNumber: vehicleNumber ?? this.vehicleNumber,
+      iuNumber: iuNumber ?? this.iuNumber,
+      vehicleMakeModelColour: vehicleMakeModelColour ?? this.vehicleMakeModelColour,
+      startDate: startDate ?? this.startDate,
+      endDate: endDate ?? this.endDate,
+      timeOrArrival: timeOrArrival ?? this.timeOrArrival,
+      movingCompany: movingCompany ?? this.movingCompany,
+      personInCharge: personInCharge ?? this.personInCharge,
+      mobileNumber: mobileNumber ?? this.mobileNumber,
+      companyAddress: companyAddress ?? this.companyAddress,
+      dateOfEntry: dateOfEntry ?? this.dateOfEntry,
+      guestName: guestName ?? this.guestName,
+      guestMobileNumber: guestMobileNumber ?? this.guestMobileNumber,
+      renovationStartDate: renovationStartDate ?? this.renovationStartDate,
+      renovationEndDate: renovationEndDate ?? this.renovationEndDate,
+      hackingStartDate: hackingStartDate ?? this.hackingStartDate,
+      hackingEndDate: hackingEndDate ?? this.hackingEndDate,
+      renovationCompany: renovationCompany ?? this.renovationCompany,
+      listOfRenovationWorks: listOfRenovationWorks ?? this.listOfRenovationWorks,
+    );
+  }
+}

+ 31 - 0
packages/cs_domain/lib/entity/form_detail_entity.dart

@@ -0,0 +1,31 @@
+import 'package:domain/entity/form_content_entity.dart';
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/form_detail_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/form_detail_entity.g.dart';
+
+@JsonSerializable()
+class FormDetailEntity {
+	String? id;
+	@JSONField(name: "user_id")
+	String? userId;
+	FormContentEntity? content;  //详情内容
+	int status = 0;  //0-已提交未审核,1-已审核通过,2-审核失败
+	@JSONField(name: "sent_on")
+	String? sentOn;
+	@JSONField(name: "rejected_on")
+	String? rejectedOn;
+	@JSONField(name: "approved_on")
+	String? approvedOn;
+
+	FormDetailEntity();
+
+	factory FormDetailEntity.fromJson(Map<String, dynamic> json) => $FormDetailEntityFromJson(json);
+
+	Map<String, dynamic> toJson() => $FormDetailEntityToJson(this);
+
+	@override
+	String toString() {
+		return jsonEncode(this);
+	}
+}

+ 2 - 1
packages/cs_domain/lib/entity/form_list_entity.dart

@@ -10,7 +10,8 @@ class FormListEntity {
   String? typeId;
   String? icon;
   String? name;
-  String? price;
+  double price = 0;
+  double deposit = 0;
   String? description;
 
   FormListEntity();

+ 23 - 0
packages/cs_domain/lib/entity/form_option_entity.dart

@@ -0,0 +1,23 @@
+import 'package:domain/generated/json/base/json_field.dart';
+import 'package:domain/generated/json/form_option_entity.g.dart';
+import 'dart:convert';
+export 'package:domain/generated/json/form_option_entity.g.dart';
+
+@JsonSerializable()
+class FormOptionEntity {
+  @JSONField(name: "type_of_application")
+  List<String> typeOfApplication = [];
+  @JSONField(name: "ownership_status")
+  List<String> ownershipStatus = [];
+
+  FormOptionEntity();
+
+  factory FormOptionEntity.fromJson(Map<String, dynamic> json) => $FormOptionEntityFromJson(json);
+
+  Map<String, dynamic> toJson() => $FormOptionEntityToJson(this);
+
+  @override
+  String toString() {
+    return jsonEncode(this);
+  }
+}

+ 2 - 21
packages/cs_domain/lib/entity/form_submitted_entity.dart

@@ -1,3 +1,4 @@
+import 'package:domain/entity/form_content_entity.dart';
 import 'package:domain/entity/id_name_entity.dart';
 import 'package:domain/generated/json/base/json_field.dart';
 import 'package:domain/generated/json/form_submitted_entity.g.dart';
@@ -11,7 +12,7 @@ class FormSubmittedEntity {
 	String? userId;
 	@JSONField(name: "estate_online_form_id")
 	String? estateOnlineFormId;
-	FormSubmittedContent? content;
+	FormContentEntity? content;
 	@JSONField(name: "sent_on")
 	String? sentOn;
 	@JSONField(name: "rejected_on")
@@ -34,26 +35,6 @@ class FormSubmittedEntity {
 	}
 }
 
-@JsonSerializable()
-class FormSubmittedContent {
-	@JSONField(name: "notes_to_recipient")
-	String? notesToRecipient;
-	@JSONField(name: "notes_to_management")
-	String? notesToManagement;
-	@JSONField(name: "type_of_application")
-	String? typeOfApplication;
-
-	FormSubmittedContent();
-
-	factory FormSubmittedContent.fromJson(Map<String, dynamic> json) => $FormSubmittedContentFromJson(json);
-
-	Map<String, dynamic> toJson() => $FormSubmittedContentToJson(this);
-
-	@override
-	String toString() {
-		return jsonEncode(this);
-	}
-}
 
 @JsonSerializable()
 class FormSubmittedEstateOnlineForm {

+ 15 - 4
packages/cs_domain/lib/generated/json/base/json_convert_content.dart

@@ -8,7 +8,10 @@ import 'package:domain/entity/auth_login_entity.dart';
 import 'package:domain/entity/captcha_img_entity.dart';
 import 'package:domain/entity/feedback_detail_entity.dart';
 import 'package:domain/entity/feedback_list_entity.dart';
+import 'package:domain/entity/form_content_entity.dart';
+import 'package:domain/entity/form_detail_entity.dart';
 import 'package:domain/entity/form_list_entity.dart';
+import 'package:domain/entity/form_option_entity.dart';
 import 'package:domain/entity/form_submitted_entity.dart';
 import 'package:domain/entity/form_submitted_page_entity.dart';
 import 'package:domain/entity/id_name_entity.dart';
@@ -170,15 +173,21 @@ class JsonConvert {
     if (<FeedbackItemEntity>[] is M) {
       return data.map<FeedbackItemEntity>((Map<String, dynamic> e) => FeedbackItemEntity.fromJson(e)).toList() as M;
     }
+    if (<FormContentEntity>[] is M) {
+      return data.map<FormContentEntity>((Map<String, dynamic> e) => FormContentEntity.fromJson(e)).toList() as M;
+    }
+    if (<FormDetailEntity>[] is M) {
+      return data.map<FormDetailEntity>((Map<String, dynamic> e) => FormDetailEntity.fromJson(e)).toList() as M;
+    }
     if (<FormListEntity>[] is M) {
       return data.map<FormListEntity>((Map<String, dynamic> e) => FormListEntity.fromJson(e)).toList() as M;
     }
+    if (<FormOptionEntity>[] is M) {
+      return data.map<FormOptionEntity>((Map<String, dynamic> e) => FormOptionEntity.fromJson(e)).toList() as M;
+    }
     if (<FormSubmittedEntity>[] is M) {
       return data.map<FormSubmittedEntity>((Map<String, dynamic> e) => FormSubmittedEntity.fromJson(e)).toList() as M;
     }
-    if (<FormSubmittedContent>[] is M) {
-      return data.map<FormSubmittedContent>((Map<String, dynamic> e) => FormSubmittedContent.fromJson(e)).toList() as M;
-    }
     if (<FormSubmittedEstateOnlineForm>[] is M) {
       return data.map<FormSubmittedEstateOnlineForm>((Map<String, dynamic> e) => FormSubmittedEstateOnlineForm.fromJson(e)).toList() as M;
     }
@@ -280,9 +289,11 @@ class JsonConvertClassCollection {
     (FeedbackDetailReplies).toString(): FeedbackDetailReplies.fromJson,
     (FeedbackListEntity).toString(): FeedbackListEntity.fromJson,
     (FeedbackItemEntity).toString(): FeedbackItemEntity.fromJson,
+    (FormContentEntity).toString(): FormContentEntity.fromJson,
+    (FormDetailEntity).toString(): FormDetailEntity.fromJson,
     (FormListEntity).toString(): FormListEntity.fromJson,
+    (FormOptionEntity).toString(): FormOptionEntity.fromJson,
     (FormSubmittedEntity).toString(): FormSubmittedEntity.fromJson,
-    (FormSubmittedContent).toString(): FormSubmittedContent.fromJson,
     (FormSubmittedEstateOnlineForm).toString(): FormSubmittedEstateOnlineForm.fromJson,
     (FormSubmittedPageEntity).toString(): FormSubmittedPageEntity.fromJson,
     (IdNameEntity).toString(): IdNameEntity.fromJson,

+ 204 - 0
packages/cs_domain/lib/generated/json/form_content_entity.g.dart

@@ -0,0 +1,204 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/form_content_entity.dart';
+import 'dart:typed_data';
+
+
+FormContentEntity $FormContentEntityFromJson(Map<String, dynamic> json) {
+  final FormContentEntity formContentEntity = FormContentEntity();
+  final String? typeOfApplication = jsonConvert.convert<String>(json['type_of_application']);
+  if (typeOfApplication != null) {
+    formContentEntity.typeOfApplication = typeOfApplication;
+  }
+  final String? notesToRecipient = jsonConvert.convert<String>(json['notes_to_recipient']);
+  if (notesToRecipient != null) {
+    formContentEntity.notesToRecipient = notesToRecipient;
+  }
+  final String? notesToManagement = jsonConvert.convert<String>(json['notes_to_management']);
+  if (notesToManagement != null) {
+    formContentEntity.notesToManagement = notesToManagement;
+  }
+  final List<String>? attachments = (json['attachments'] as List<dynamic>?)?.map(
+          (e) => jsonConvert.convert<String>(e) as String).toList();
+  if (attachments != null) {
+    formContentEntity.attachments = attachments;
+  }
+  final String? signature = jsonConvert.convert<String>(json['signature']);
+  if (signature != null) {
+    formContentEntity.signature = signature;
+  }
+  final dynamic signatureByteData = json['signatureByteData'];
+  if (signatureByteData != null) {
+    formContentEntity.signatureByteData = signatureByteData;
+  }
+  final String? ownershipStatus = jsonConvert.convert<String>(json['ownership_status']);
+  if (ownershipStatus != null) {
+    formContentEntity.ownershipStatus = ownershipStatus;
+  }
+  final String? vehicleNumber = jsonConvert.convert<String>(json['vehicle_number']);
+  if (vehicleNumber != null) {
+    formContentEntity.vehicleNumber = vehicleNumber;
+  }
+  final String? iuNumber = jsonConvert.convert<String>(json['iu_number']);
+  if (iuNumber != null) {
+    formContentEntity.iuNumber = iuNumber;
+  }
+  final String? vehicleMakeModelColour = jsonConvert.convert<String>(json['vehicle_make_model_colour']);
+  if (vehicleMakeModelColour != null) {
+    formContentEntity.vehicleMakeModelColour = vehicleMakeModelColour;
+  }
+  final String? startDate = jsonConvert.convert<String>(json['start_date']);
+  if (startDate != null) {
+    formContentEntity.startDate = startDate;
+  }
+  final String? endDate = jsonConvert.convert<String>(json['end_date']);
+  if (endDate != null) {
+    formContentEntity.endDate = endDate;
+  }
+  final String? timeOrArrival = jsonConvert.convert<String>(json['time_or_arrival']);
+  if (timeOrArrival != null) {
+    formContentEntity.timeOrArrival = timeOrArrival;
+  }
+  final String? movingCompany = jsonConvert.convert<String>(json['moving_company']);
+  if (movingCompany != null) {
+    formContentEntity.movingCompany = movingCompany;
+  }
+  final String? personInCharge = jsonConvert.convert<String>(json['person_in_charge']);
+  if (personInCharge != null) {
+    formContentEntity.personInCharge = personInCharge;
+  }
+  final String? mobileNumber = jsonConvert.convert<String>(json['mobile_number']);
+  if (mobileNumber != null) {
+    formContentEntity.mobileNumber = mobileNumber;
+  }
+  final String? companyAddress = jsonConvert.convert<String>(json['company_address']);
+  if (companyAddress != null) {
+    formContentEntity.companyAddress = companyAddress;
+  }
+  final String? dateOfEntry = jsonConvert.convert<String>(json['date_of_entry']);
+  if (dateOfEntry != null) {
+    formContentEntity.dateOfEntry = dateOfEntry;
+  }
+  final String? guestName = jsonConvert.convert<String>(json['guest_name']);
+  if (guestName != null) {
+    formContentEntity.guestName = guestName;
+  }
+  final String? guestMobileNumber = jsonConvert.convert<String>(json['guest_mobile_number']);
+  if (guestMobileNumber != null) {
+    formContentEntity.guestMobileNumber = guestMobileNumber;
+  }
+  final String? renovationStartDate = jsonConvert.convert<String>(json['renovation_start_date']);
+  if (renovationStartDate != null) {
+    formContentEntity.renovationStartDate = renovationStartDate;
+  }
+  final String? renovationEndDate = jsonConvert.convert<String>(json['renovation_end_date']);
+  if (renovationEndDate != null) {
+    formContentEntity.renovationEndDate = renovationEndDate;
+  }
+  final String? hackingStartDate = jsonConvert.convert<String>(json['hacking_start_date']);
+  if (hackingStartDate != null) {
+    formContentEntity.hackingStartDate = hackingStartDate;
+  }
+  final String? hackingEndDate = jsonConvert.convert<String>(json['hacking_end_date']);
+  if (hackingEndDate != null) {
+    formContentEntity.hackingEndDate = hackingEndDate;
+  }
+  final String? renovationCompany = jsonConvert.convert<String>(json['renovation_company']);
+  if (renovationCompany != null) {
+    formContentEntity.renovationCompany = renovationCompany;
+  }
+  final String? listOfRenovationWorks = jsonConvert.convert<String>(json['list_of_renovation_works']);
+  if (listOfRenovationWorks != null) {
+    formContentEntity.listOfRenovationWorks = listOfRenovationWorks;
+  }
+  return formContentEntity;
+}
+
+Map<String, dynamic> $FormContentEntityToJson(FormContentEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['type_of_application'] = entity.typeOfApplication;
+  data['notes_to_recipient'] = entity.notesToRecipient;
+  data['notes_to_management'] = entity.notesToManagement;
+  data['attachments'] = entity.attachments;
+  data['signature'] = entity.signature;
+  data['signatureByteData'] = entity.signatureByteData;
+  data['ownership_status'] = entity.ownershipStatus;
+  data['vehicle_number'] = entity.vehicleNumber;
+  data['iu_number'] = entity.iuNumber;
+  data['vehicle_make_model_colour'] = entity.vehicleMakeModelColour;
+  data['start_date'] = entity.startDate;
+  data['end_date'] = entity.endDate;
+  data['time_or_arrival'] = entity.timeOrArrival;
+  data['moving_company'] = entity.movingCompany;
+  data['person_in_charge'] = entity.personInCharge;
+  data['mobile_number'] = entity.mobileNumber;
+  data['company_address'] = entity.companyAddress;
+  data['date_of_entry'] = entity.dateOfEntry;
+  data['guest_name'] = entity.guestName;
+  data['guest_mobile_number'] = entity.guestMobileNumber;
+  data['renovation_start_date'] = entity.renovationStartDate;
+  data['renovation_end_date'] = entity.renovationEndDate;
+  data['hacking_start_date'] = entity.hackingStartDate;
+  data['hacking_end_date'] = entity.hackingEndDate;
+  data['renovation_company'] = entity.renovationCompany;
+  data['list_of_renovation_works'] = entity.listOfRenovationWorks;
+  return data;
+}
+
+extension FormContentEntityExtension on FormContentEntity {
+  FormContentEntity copyWith({
+    String? typeOfApplication,
+    String? notesToRecipient,
+    String? notesToManagement,
+    List<String>? attachments,
+    String? signature,
+    dynamic signatureByteData,
+    String? ownershipStatus,
+    String? vehicleNumber,
+    String? iuNumber,
+    String? vehicleMakeModelColour,
+    String? startDate,
+    String? endDate,
+    String? timeOrArrival,
+    String? movingCompany,
+    String? personInCharge,
+    String? mobileNumber,
+    String? companyAddress,
+    String? dateOfEntry,
+    String? guestName,
+    String? guestMobileNumber,
+    String? renovationStartDate,
+    String? renovationEndDate,
+    String? hackingStartDate,
+    String? hackingEndDate,
+    String? renovationCompany,
+    String? listOfRenovationWorks,
+  }) {
+    return FormContentEntity()
+      ..typeOfApplication = typeOfApplication ?? this.typeOfApplication
+      ..notesToRecipient = notesToRecipient ?? this.notesToRecipient
+      ..notesToManagement = notesToManagement ?? this.notesToManagement
+      ..attachments = attachments ?? this.attachments
+      ..signature = signature ?? this.signature
+      ..signatureByteData = signatureByteData ?? this.signatureByteData
+      ..ownershipStatus = ownershipStatus ?? this.ownershipStatus
+      ..vehicleNumber = vehicleNumber ?? this.vehicleNumber
+      ..iuNumber = iuNumber ?? this.iuNumber
+      ..vehicleMakeModelColour = vehicleMakeModelColour ?? this.vehicleMakeModelColour
+      ..startDate = startDate ?? this.startDate
+      ..endDate = endDate ?? this.endDate
+      ..timeOrArrival = timeOrArrival ?? this.timeOrArrival
+      ..movingCompany = movingCompany ?? this.movingCompany
+      ..personInCharge = personInCharge ?? this.personInCharge
+      ..mobileNumber = mobileNumber ?? this.mobileNumber
+      ..companyAddress = companyAddress ?? this.companyAddress
+      ..dateOfEntry = dateOfEntry ?? this.dateOfEntry
+      ..guestName = guestName ?? this.guestName
+      ..guestMobileNumber = guestMobileNumber ?? this.guestMobileNumber
+      ..renovationStartDate = renovationStartDate ?? this.renovationStartDate
+      ..renovationEndDate = renovationEndDate ?? this.renovationEndDate
+      ..hackingStartDate = hackingStartDate ?? this.hackingStartDate
+      ..hackingEndDate = hackingEndDate ?? this.hackingEndDate
+      ..renovationCompany = renovationCompany ?? this.renovationCompany
+      ..listOfRenovationWorks = listOfRenovationWorks ?? this.listOfRenovationWorks;
+  }
+}

+ 70 - 0
packages/cs_domain/lib/generated/json/form_detail_entity.g.dart

@@ -0,0 +1,70 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/form_detail_entity.dart';
+import 'package:domain/entity/form_content_entity.dart';
+
+
+FormDetailEntity $FormDetailEntityFromJson(Map<String, dynamic> json) {
+  final FormDetailEntity formDetailEntity = FormDetailEntity();
+  final String? id = jsonConvert.convert<String>(json['id']);
+  if (id != null) {
+    formDetailEntity.id = id;
+  }
+  final String? userId = jsonConvert.convert<String>(json['user_id']);
+  if (userId != null) {
+    formDetailEntity.userId = userId;
+  }
+  final FormContentEntity? content = jsonConvert.convert<FormContentEntity>(json['content']);
+  if (content != null) {
+    formDetailEntity.content = content;
+  }
+  final int? status = jsonConvert.convert<int>(json['status']);
+  if (status != null) {
+    formDetailEntity.status = status;
+  }
+  final String? sentOn = jsonConvert.convert<String>(json['sent_on']);
+  if (sentOn != null) {
+    formDetailEntity.sentOn = sentOn;
+  }
+  final String? rejectedOn = jsonConvert.convert<String>(json['rejected_on']);
+  if (rejectedOn != null) {
+    formDetailEntity.rejectedOn = rejectedOn;
+  }
+  final String? approvedOn = jsonConvert.convert<String>(json['approved_on']);
+  if (approvedOn != null) {
+    formDetailEntity.approvedOn = approvedOn;
+  }
+  return formDetailEntity;
+}
+
+Map<String, dynamic> $FormDetailEntityToJson(FormDetailEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['id'] = entity.id;
+  data['user_id'] = entity.userId;
+  data['content'] = entity.content?.toJson();
+  data['status'] = entity.status;
+  data['sent_on'] = entity.sentOn;
+  data['rejected_on'] = entity.rejectedOn;
+  data['approved_on'] = entity.approvedOn;
+  return data;
+}
+
+extension FormDetailEntityExtension on FormDetailEntity {
+  FormDetailEntity copyWith({
+    String? id,
+    String? userId,
+    FormContentEntity? content,
+    int? status,
+    String? sentOn,
+    String? rejectedOn,
+    String? approvedOn,
+  }) {
+    return FormDetailEntity()
+      ..id = id ?? this.id
+      ..userId = userId ?? this.userId
+      ..content = content ?? this.content
+      ..status = status ?? this.status
+      ..sentOn = sentOn ?? this.sentOn
+      ..rejectedOn = rejectedOn ?? this.rejectedOn
+      ..approvedOn = approvedOn ?? this.approvedOn;
+  }
+}

+ 9 - 2
packages/cs_domain/lib/generated/json/form_list_entity.g.dart

@@ -19,10 +19,14 @@ FormListEntity $FormListEntityFromJson(Map<String, dynamic> json) {
   if (name != null) {
     formListEntity.name = name;
   }
-  final String? price = jsonConvert.convert<String>(json['price']);
+  final double? price = jsonConvert.convert<double>(json['price']);
   if (price != null) {
     formListEntity.price = price;
   }
+  final double? deposit = jsonConvert.convert<double>(json['deposit']);
+  if (deposit != null) {
+    formListEntity.deposit = deposit;
+  }
   final String? description = jsonConvert.convert<String>(json['description']);
   if (description != null) {
     formListEntity.description = description;
@@ -37,6 +41,7 @@ Map<String, dynamic> $FormListEntityToJson(FormListEntity entity) {
   data['icon'] = entity.icon;
   data['name'] = entity.name;
   data['price'] = entity.price;
+  data['deposit'] = entity.deposit;
   data['description'] = entity.description;
   return data;
 }
@@ -47,7 +52,8 @@ extension FormListEntityExtension on FormListEntity {
     String? typeId,
     String? icon,
     String? name,
-    String? price,
+    double? price,
+    double? deposit,
     String? description,
   }) {
     return FormListEntity()
@@ -56,6 +62,7 @@ extension FormListEntityExtension on FormListEntity {
       ..icon = icon ?? this.icon
       ..name = name ?? this.name
       ..price = price ?? this.price
+      ..deposit = deposit ?? this.deposit
       ..description = description ?? this.description;
   }
 }

+ 35 - 0
packages/cs_domain/lib/generated/json/form_option_entity.g.dart

@@ -0,0 +1,35 @@
+import 'package:domain/generated/json/base/json_convert_content.dart';
+import 'package:domain/entity/form_option_entity.dart';
+
+FormOptionEntity $FormOptionEntityFromJson(Map<String, dynamic> json) {
+  final FormOptionEntity formOptionEntity = FormOptionEntity();
+  final List<String>? typeOfApplication = (json['type_of_application'] as List<dynamic>?)?.map(
+          (e) => jsonConvert.convert<String>(e) as String).toList();
+  if (typeOfApplication != null) {
+    formOptionEntity.typeOfApplication = typeOfApplication;
+  }
+  final List<String>? ownershipStatus = (json['ownership_status'] as List<dynamic>?)?.map(
+          (e) => jsonConvert.convert<String>(e) as String).toList();
+  if (ownershipStatus != null) {
+    formOptionEntity.ownershipStatus = ownershipStatus;
+  }
+  return formOptionEntity;
+}
+
+Map<String, dynamic> $FormOptionEntityToJson(FormOptionEntity entity) {
+  final Map<String, dynamic> data = <String, dynamic>{};
+  data['type_of_application'] = entity.typeOfApplication;
+  data['ownership_status'] = entity.ownershipStatus;
+  return data;
+}
+
+extension FormOptionEntityExtension on FormOptionEntity {
+  FormOptionEntity copyWith({
+    List<String>? typeOfApplication,
+    List<String>? ownershipStatus,
+  }) {
+    return FormOptionEntity()
+      ..typeOfApplication = typeOfApplication ?? this.typeOfApplication
+      ..ownershipStatus = ownershipStatus ?? this.ownershipStatus;
+  }
+}

+ 4 - 40
packages/cs_domain/lib/generated/json/form_submitted_entity.g.dart

@@ -1,5 +1,7 @@
 import 'package:domain/generated/json/base/json_convert_content.dart';
 import 'package:domain/entity/form_submitted_entity.dart';
+import 'package:domain/entity/form_content_entity.dart';
+
 import 'package:domain/entity/id_name_entity.dart';
 
 
@@ -17,7 +19,7 @@ FormSubmittedEntity $FormSubmittedEntityFromJson(Map<String, dynamic> json) {
   if (estateOnlineFormId != null) {
     formSubmittedEntity.estateOnlineFormId = estateOnlineFormId;
   }
-  final FormSubmittedContent? content = jsonConvert.convert<FormSubmittedContent>(json['content']);
+  final FormContentEntity? content = jsonConvert.convert<FormContentEntity>(json['content']);
   if (content != null) {
     formSubmittedEntity.content = content;
   }
@@ -63,7 +65,7 @@ extension FormSubmittedEntityExtension on FormSubmittedEntity {
     String? id,
     String? userId,
     String? estateOnlineFormId,
-    FormSubmittedContent? content,
+    FormContentEntity? content,
     String? sentOn,
     String? rejectedOn,
     String? approvedOn,
@@ -83,44 +85,6 @@ extension FormSubmittedEntityExtension on FormSubmittedEntity {
   }
 }
 
-FormSubmittedContent $FormSubmittedContentFromJson(Map<String, dynamic> json) {
-  final FormSubmittedContent formSubmittedContent = FormSubmittedContent();
-  final String? notesToRecipient = jsonConvert.convert<String>(json['notes_to_recipient']);
-  if (notesToRecipient != null) {
-    formSubmittedContent.notesToRecipient = notesToRecipient;
-  }
-  final String? notesToManagement = jsonConvert.convert<String>(json['notes_to_management']);
-  if (notesToManagement != null) {
-    formSubmittedContent.notesToManagement = notesToManagement;
-  }
-  final String? typeOfApplication = jsonConvert.convert<String>(json['type_of_application']);
-  if (typeOfApplication != null) {
-    formSubmittedContent.typeOfApplication = typeOfApplication;
-  }
-  return formSubmittedContent;
-}
-
-Map<String, dynamic> $FormSubmittedContentToJson(FormSubmittedContent entity) {
-  final Map<String, dynamic> data = <String, dynamic>{};
-  data['notes_to_recipient'] = entity.notesToRecipient;
-  data['notes_to_management'] = entity.notesToManagement;
-  data['type_of_application'] = entity.typeOfApplication;
-  return data;
-}
-
-extension FormSubmittedContentExtension on FormSubmittedContent {
-  FormSubmittedContent copyWith({
-    String? notesToRecipient,
-    String? notesToManagement,
-    String? typeOfApplication,
-  }) {
-    return FormSubmittedContent()
-      ..notesToRecipient = notesToRecipient ?? this.notesToRecipient
-      ..notesToManagement = notesToManagement ?? this.notesToManagement
-      ..typeOfApplication = typeOfApplication ?? this.typeOfApplication;
-  }
-}
-
 FormSubmittedEstateOnlineForm $FormSubmittedEstateOnlineFormFromJson(Map<String, dynamic> json) {
   final FormSubmittedEstateOnlineForm formSubmittedEstateOnlineForm = FormSubmittedEstateOnlineForm();
   final String? id = jsonConvert.convert<String>(json['id']);

+ 189 - 0
packages/cs_domain/lib/repository/form_repository.dart

@@ -1,13 +1,19 @@
+import 'dart:typed_data';
+
 import 'package:domain/entity/feedback_detail_entity.dart';
+import 'package:domain/entity/form_option_entity.dart';
 import 'package:plugin_platform/platform_export.dart';
 import 'package:plugin_platform/http/dio_engine.dart';
 import 'package:plugin_platform/http/http_result.dart';
 import 'package:riverpod_annotation/riverpod_annotation.dart';
 import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
 
 import '../constants/api_constants.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
 import 'package:plugin_basic/provider/http_provider/http_provider.dart';
+import '../entity/form_content_entity.dart';
+import '../entity/form_detail_entity.dart';
 import '../entity/form_list_entity.dart';
 import '../entity/form_submitted_page_entity.dart';
 import '../entity/id_name_entity.dart';
@@ -131,5 +137,188 @@ class FormRepository {
     return result.convert();
   }
 
+  /// 获取表单的选项
+  Future<HttpResult<FormOptionEntity>> fetchFormOption({
+    required String? typeId,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['type_id'] = typeId ?? "";
+
+    final result = await dioEngine.requestNetResult(
+      ApiConstants.apiFormOption,
+      params: params,
+      method: HttpMethod.GET,
+      isShowLoadingDialog: true,
+      networkDebounce: true,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      final json = result.getDataJson();
+      var data = FormOptionEntity.fromJson(json!);
+      return result.convert<FormOptionEntity>(data: data);
+    }
+    return result.convert();
+  }
+
+  /// 上传表单
+  Future<HttpResult> submitForm({
+    required String? estateFormId,
+    required String? typeId,
+    required FormContentEntity content,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    Map<String, String> paths = {};
+    params['estate_online_form_id'] = estateFormId ?? "";
+
+    //选择参数添加
+    if (Utils.isNotEmpty(content.typeOfApplication)) {
+      params["type_of_application"] = content.typeOfApplication!;
+    }
+
+    if (Utils.isNotEmpty(content.notesToRecipient)) {
+      params["notes_to_recipient"] = content.notesToRecipient!;
+    }
+
+    if (Utils.isNotEmpty(content.notesToManagement)) {
+      params["notes_to_management"] = content.notesToManagement!;
+    }
+
+    if (Utils.isNotEmpty(content.ownershipStatus)) {
+      params["ownership_status"] = content.ownershipStatus!;
+    }
+
+    if (Utils.isNotEmpty(content.vehicleNumber)) {
+      params["vehicle_number"] = content.vehicleNumber!;
+    }
+
+    if (Utils.isNotEmpty(content.iuNumber)) {
+      params["iu_number"] = content.iuNumber!;
+    }
+
+    if (Utils.isNotEmpty(content.vehicleMakeModelColour)) {
+      params["vehicle_make_model_colour"] = content.vehicleMakeModelColour!;
+    }
+
+    if (Utils.isNotEmpty(content.startDate)) {
+      params["start_date"] = content.startDate!;
+    }
+
+    if (Utils.isNotEmpty(content.endDate)) {
+      params["end_date"] = content.endDate!;
+    }
+
+    if (Utils.isNotEmpty(content.timeOrArrival)) {
+      params["time_or_arrival"] = "${content.timeOrArrival!}:00";
+    }
+
+    if (Utils.isNotEmpty(content.movingCompany)) {
+      params["moving_company"] = content.movingCompany!;
+    }
+
+    if (Utils.isNotEmpty(content.personInCharge)) {
+      params["person_in_charge"] = content.personInCharge!;
+    }
+
+    if (Utils.isNotEmpty(content.mobileNumber)) {
+      params["mobile_number"] = content.mobileNumber!;
+    }
+
+    if (Utils.isNotEmpty(content.companyAddress)) {
+      params["company_address"] = content.companyAddress!;
+    }
+
+    if (Utils.isNotEmpty(content.dateOfEntry)) {
+      params["date_of_entry"] = content.dateOfEntry!;
+    }
+
+    if (Utils.isNotEmpty(content.guestName)) {
+      params["guest_name"] = content.guestName!;
+    }
+
+    if (Utils.isNotEmpty(content.guestMobileNumber)) {
+      params["guest_mobile_number"] = content.guestMobileNumber!;
+    }
+
+    if (Utils.isNotEmpty(content.renovationStartDate)) {
+      params["renovation_start_date"] = content.renovationStartDate!;
+    }
+
+    if (Utils.isNotEmpty(content.renovationEndDate)) {
+      params["renovation_end_date"] = content.renovationEndDate!;
+    }
+
+    if (Utils.isNotEmpty(content.hackingStartDate)) {
+      params["hacking_start_date"] = content.hackingStartDate!;
+    }
+
+    if (Utils.isNotEmpty(content.hackingEndDate)) {
+      params["hacking_end_date"] = content.hackingEndDate!;
+    }
+
+    if (Utils.isNotEmpty(content.renovationCompany)) {
+      params["renovation_company"] = content.renovationCompany!;
+    }
+
+    if (Utils.isNotEmpty(content.listOfRenovationWorks)) {
+      params["list_of_renovation_works"] = content.listOfRenovationWorks!;
+    }
+
+    //attachments 添加
+    if (content.attachments != null && content.attachments!.isNotEmpty) {
+      content.attachments!.asMap().forEach((index, path) {
+        paths["attachments[$index]"] = path;
+      });
+    }
+
+    //signature 添加使用 ByteData 数据
+    Map<String, Uint8List> streams = {};
+    if (content.signatureByteData != null && content.signatureByteData is ByteData) {
+      streams["signature"] = (content.signatureByteData as ByteData).buffer.asUint8List();
+    }
+
+    final result = await dioEngine.requestNetResult(
+      "${ApiConstants.apiFormSubmit}$typeId",
+      params: params,
+      paths: paths,
+      pathStreams: streams,
+      method: HttpMethod.POST,
+      isShowLoadingDialog: true,
+      networkDebounce: true,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      return result.convert();
+    }
+    return result.convert();
+  }
+
+  /// 获取表单的详情数据
+  Future<HttpResult<FormDetailEntity>> fetchFormDetail({
+    required String? estateFormId,
+    required String? taskId,
+    CancelToken? cancelToken,
+  }) async {
+    Map<String, String> params = {};
+    params['estate_online_form_id'] = estateFormId ?? "";
+    params['id'] = taskId ?? "";
+
+    final result = await dioEngine.requestNetResult(
+      ApiConstants.apiFormDetail,
+      params: params,
+      method: HttpMethod.GET,
+      cancelToken: cancelToken,
+    );
+
+    if (result.isSuccess) {
+      final json = result.getDataJson();
+      var data = FormDetailEntity.fromJson(json!);
+      return result.convert<FormDetailEntity>(data: data);
+    }
+    return result.convert();
+  }
 
 }

+ 1 - 1
packages/cs_router/lib/componentRouter/main_service.dart

@@ -7,6 +7,6 @@ abstract class MainService {
 
   void startMainPage({BuildContext? context});
 
-  void startSettingPage({BuildContext? context});
+  void startFeedbackCreatePage({BuildContext? context});
 
 }

+ 7 - 8
packages/cs_widgets/lib/my_button.dart

@@ -40,7 +40,7 @@ class MyButton extends StatelessWidget {
     this.fontWeight,
     this.type = ClickType.none,
     this.milliseconds = 500,
-    this.isEnabled = true, // 控制按钮是否可用
+    this.enable = true, // 控制按钮是否可用
   }) : super(key: key);
 
   final String text;
@@ -61,22 +61,21 @@ class MyButton extends StatelessWidget {
   final FontWeight? fontWeight;
   final ClickType type;
   final int milliseconds;
-  final bool isEnabled; // 控制按钮是否可用
+  final bool enable; // 控制按钮是否可用
 
   @override
   Widget build(BuildContext context) {
     return TextButton(
-        onPressed: isEnabled
+        onPressed: enable
             ? (type == ClickType.debounce
             ? onPressed?.debounce(milliseconds)
             : type == ClickType.throttle
             ? onPressed?.throttle(milliseconds)
             : onPressed)
-            : null, // 如果按钮不可用,则 onPressed 设为 null
+            : (){},
         style: ButtonStyle(
-          foregroundColor: MaterialStateProperty.resolveWith(
-                (states) {
-              if (states.contains(MaterialState.disabled)) {
+          foregroundColor: MaterialStateProperty.resolveWith((states) {
+              if (!enable) {
                 return DarkThemeUtil.multiColors(
                     context, disabledTextColor ?? Colors.grey,
                     darkColor: Colors.grey);
@@ -87,7 +86,7 @@ class MyButton extends StatelessWidget {
             },
           ),
           backgroundColor: MaterialStateProperty.resolveWith((states) {
-            if (states.contains(MaterialState.disabled)) {
+            if (!enable) {
               return disabledBackgroundColor;
             }
             return backgroundColor;