liukai 1 тиждень тому
батько
коміт
575cf404d0
29 змінених файлів з 972 додано та 45 видалено
  1. 253 0
      packages/cpt_main/lib/modules/feedback/create/feedback_create_page.dart
  2. 54 0
      packages/cpt_main/lib/modules/feedback/create/feedback_create_state.dart
  3. 103 0
      packages/cpt_main/lib/modules/feedback/create/feedback_create_view_model.dart
  4. 27 0
      packages/cpt_main/lib/modules/feedback/create/feedback_create_view_model.g.dart
  5. 74 0
      packages/cpt_main/lib/modules/feedback/create_success/feedback_create_success_page.dart
  6. 215 0
      packages/cpt_main/lib/modules/feedback/detail/feedback_detail_page.dart
  7. 18 0
      packages/cpt_main/lib/modules/feedback/detail/feedback_detail_state.dart
  8. 15 0
      packages/cpt_main/lib/modules/feedback/detail/feedback_detail_view_model.dart
  9. 27 0
      packages/cpt_main/lib/modules/feedback/detail/feedback_detail_view_model.g.dart
  10. 4 1
      packages/cpt_main/lib/modules/feedback/history/feedback_history.dart
  11. 2 1
      packages/cpt_main/lib/modules/feedback/item_feedback.dart
  12. 4 1
      packages/cpt_main/lib/modules/feedback/progress/feedback_progress.dart
  13. 2 1
      packages/cpt_main/lib/modules/feedback/send/feedback_send_large.dart
  14. 3 1
      packages/cpt_main/lib/modules/feedback/send/feedback_send_small.dart
  15. 10 19
      packages/cpt_main/lib/modules/visitor/register/visitor_register_page.dart
  16. 0 6
      packages/cpt_main/lib/modules/visitor/register/visitor_register_state.dart
  17. 1 3
      packages/cpt_main/lib/modules/visitor/register/visitor_register_view_model.dart
  18. 1 1
      packages/cpt_main/lib/modules/visitor/register/visitor_register_view_model.g.dart
  19. 6 0
      packages/cpt_main/lib/router/page/main_page_router.dart
  20. 60 0
      packages/cpt_main/lib/router/page/main_page_router.gr.dart
  21. 1 0
      packages/cs_plugin_platform/lib/engine/image/image_nine_grid.dart
  22. 4 2
      packages/cs_resources/lib/generated/intl/messages_en.dart
  23. 3 2
      packages/cs_resources/lib/generated/intl/messages_zh_CN.dart
  24. 3 2
      packages/cs_resources/lib/generated/intl/messages_zh_HK.dart
  25. 12 2
      packages/cs_resources/lib/generated/l10n.dart
  26. 2 1
      packages/cs_resources/lib/l10n/intl_en.arb
  27. 2 1
      packages/cs_resources/lib/l10n/intl_zh_CN.arb
  28. 2 1
      packages/cs_resources/lib/l10n/intl_zh_HK.arb
  29. 64 0
      packages/cs_widgets/lib/shatter/picker_container.dart

+ 253 - 0
packages/cpt_main/lib/modules/feedback/create/feedback_create_page.dart

@@ -0,0 +1,253 @@
+import 'package:cpt_main/modules/feedback/create/feedback_create_state.dart';
+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/image/image_nine_grid.dart';
+import 'package:router/ext/auto_router_extensions.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_field.dart';
+import 'package:widgets/my_text_view.dart';
+import 'package:widgets/shatter/form_require_text.dart';
+import 'package:widgets/shatter/picker_container.dart';
+import 'package:widgets/widget_export.dart';
+import '../../../router/page/main_page_router.dart';
+import 'feedback_create_view_model.dart';
+
+@RoutePage()
+class FeedbackCreatePage extends HookConsumerWidget {
+  const FeedbackCreatePage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const FeedbackCreatePageRoute());
+    } else {
+      appRouter.push(const FeedbackCreatePageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(feedbackCreateViewModelProvider.notifier);
+    final state = ref.watch(feedbackCreateViewModelProvider);
+    final noteCount = useState(0);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, S.current.create_new_feedback),
+      backgroundColor: context.appColors.whiteBG,
+      body: SingleChildScrollView(
+        scrollDirection: Axis.vertical,
+        physics: const BouncingScrollPhysics(),
+        child: Container(
+          margin: const EdgeInsets.symmetric(horizontal: 15),
+          width: double.infinity,
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              //选择类型
+              FormRequireText(
+                text: S.current.full_name,
+                textColor: context.appColors.textBlack,
+                fontSize: 17,
+              ).marginOnly(top: 14.5),
+              // 选择器
+              PickerContainer(
+                content: state.selectedOption ?? "",
+                hint: S.current.choose_category,
+                margin: const EdgeInsets.only(top: 16),
+                onClick: viewModel.pickCategory,
+              ),
+
+              //Title
+              FormRequireText(
+                text: S.current.title,
+                textColor: context.appColors.textBlack,
+                fontSize: 17,
+              ).marginOnly(top: 14.5),
+              // 表单
+              _buildInputLayout(
+                context,
+                state,
+                "title",
+                marginTop: 16,
+                textInputType: TextInputType.text,
+                textInputAction: TextInputAction.next,
+                errorText: state.titleErrorText,
+                onSubmit: (formKey, value) {
+                  state.formData[formKey]!['focusNode'].unfocus();
+                  FocusScope.of(context).requestFocus(state.formData['desc']!['focusNode']);
+                },
+              ),
+
+              // DESC
+              MyTextView(
+                S.current.describe_your_feedback,
+                textColor: context.appColors.textBlack,
+                fontSize: 17,
+                marginTop: 14.5,
+                isFontMedium: true,
+              ),
+              //大文本框
+              IgnoreKeyboardDismiss(
+                child: Container(
+                  height: 177,
+                  margin: const EdgeInsets.only(top: 16),
+                  padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15),
+                  decoration: BoxDecoration(
+                    color: context.appColors.authFiledBG,
+                    borderRadius: const BorderRadius.all(Radius.circular(5)),
+                  ),
+                  child: Stack(
+                    children: [
+                      TextField(
+                        cursorColor: context.appColors.authFiledText,
+                        cursorWidth: 1.5,
+                        autofocus: false,
+                        enabled: true,
+                        focusNode: state.formData["desc"]!['focusNode'],
+                        controller: state.formData["desc"]!['controller'],
+                        decoration: InputDecoration(
+                          isDense: true,
+                          isCollapsed: true,
+                          border: InputBorder.none,
+                          hintText: state.formData["desc"]!['hintText'],
+                          hintStyle: TextStyle(
+                            color: context.appColors.authFiledHint,
+                            fontSize: 16.0,
+                            fontWeight: FontWeight.w500,
+                          ),
+                        ),
+                        style: TextStyle(
+                          color: context.appColors.authFiledText,
+                          fontSize: 16.0,
+                          fontWeight: FontWeight.w500,
+                        ),
+                        textInputAction: TextInputAction.done,
+                        onSubmitted: (value) {
+                          FocusScope.of(context).unfocus();
+                        },
+                        maxLines: null,
+                        expands: true,
+                        onChanged: (text) {
+                          // 当文本改变时,更新字符数量
+                          noteCount.value = text.length;
+                        },
+                      ),
+                      Positioned(
+                        bottom: 0.0,
+                        right: 0.0,
+                        child: Text(
+                          S.current.characters(noteCount.value),
+                          style: TextStyle(
+                            color: context.appColors.textBlack,
+                            fontSize: 15.0,
+                          ),
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+              ),
+
+              MyTextView(
+                S.current.upload_pictures,
+                textColor: context.appColors.textBlack,
+                fontSize: 17,
+                marginTop: 14.5,
+                isFontMedium: true,
+              ),
+
+              MyTextView(
+                S.current.up_to_max_images,
+                fontSize: 13,
+                marginTop: 5,
+                marginBottom: 14,
+                isFontRegular: true,
+                textColor: context.appColors.textDarkGray999,
+              ),
+
+              ImageNineGrid(
+                isSelectEnable: true,
+                maxImages: 10,
+                spacing: 10,
+                aspectRatio: 108 / 80,
+                initialImages: state.imgList,
+                onImagesChanged: (list) {
+                  viewModel.setImgList(list);
+                },
+              ),
+
+              MyButton(
+                onPressed: viewModel.submitFeedback,
+                text: S.current.submit,
+                textColor: Colors.white,
+                backgroundColor: context.appColors.btnBgDefault,
+                fontWeight: FontWeight.w500,
+                type: ClickType.throttle,
+                fontSize: 16,
+                minHeight: 50,
+                radius: 5,
+              ).marginOnly(top: 25, bottom: 25),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+
+  /// 输入框
+  Widget _buildInputLayout(
+    BuildContext context,
+    FeedbackCreateState state,
+    String key, {
+    double marginTop = 0,
+    bool? showRightIcon = false, //是否展示右侧的布局
+    Widget? rightWidget, //右侧的布局
+    TextInputType textInputType = TextInputType.text,
+    String? errorText,
+    bool obscureText = false,
+    bool enable = true,
+    TextInputAction textInputAction = TextInputAction.done,
+    Function? onSubmit,
+  }) {
+    return IgnoreKeyboardDismiss(
+      child: MyTextField(
+        key,
+        fillBackgroundColor: context.appColors.authFiledBG,
+        state.formData[key]!['value'],
+        hintStyle: TextStyle(
+          color: context.appColors.authFiledHint,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        controller: state.formData[key]!['controller'],
+        focusNode: state.formData[key]!['focusNode'],
+        margin: EdgeInsets.only(top: marginTop),
+        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 3),
+        showDivider: false,
+        height: 44,
+        enabled: enable,
+        style: TextStyle(
+          color: context.appColors.authFiledText,
+          fontSize: 16.0,
+          fontWeight: FontWeight.w500,
+        ),
+        inputType: textInputType,
+        textInputAction: textInputAction,
+        onSubmit: onSubmit,
+        cursorColor: context.appColors.authFiledText,
+        obscureText: obscureText,
+        errorText: errorText,
+        showLeftIcon: true,
+        showRightIcon: showRightIcon,
+        rightWidget: rightWidget,
+      ),
+    );
+  }
+}

+ 54 - 0
packages/cpt_main/lib/modules/feedback/create/feedback_create_state.dart

@@ -0,0 +1,54 @@
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:flutter/material.dart';
+
+class FeedbackCreateState {
+//表单的校验与数据
+  final Map<String, Map<String, dynamic>> formData;
+
+  //表单的错误信息展示
+  String? titleErrorText;
+
+  //类型选项
+  final List<String> optionList = ["条件1", "条件2", "条件3", "条件4"];
+  String? selectedOption;
+
+  //选择的图片
+  List<String> imgList;
+
+  // ===================================  Begin  ↓  ===================================
+
+  FeedbackCreateState({
+    Map<String, Map<String, dynamic>>? formData,
+    this.titleErrorText,
+    required this.imgList,
+    this.selectedOption,
+  }) : formData = formData ??
+            {
+              'title': {
+                'value': '',
+                'controller': TextEditingController(),
+                'focusNode': FocusNode(),
+                'obsecure': false,
+              },
+              'desc': {
+                'value': '',
+                'controller': TextEditingController(),
+                'focusNode': FocusNode(),
+                'hintText': S.current.type_here,
+                'obsecure': false,
+              },
+            };
+
+  FeedbackCreateState copyWith({
+    String? titleErrorText,
+    String? selectedOption,
+    List<String>? imgList,
+  }) {
+    return FeedbackCreateState(
+      formData: this.formData,
+      titleErrorText: titleErrorText,
+      imgList: imgList ?? this.imgList,
+      selectedOption: selectedOption ?? this.selectedOption,
+    );
+  }
+}

+ 103 - 0
packages/cpt_main/lib/modules/feedback/create/feedback_create_view_model.dart

@@ -0,0 +1,103 @@
+import 'package:cs_resources/generated/l10n.dart';
+import 'package:flutter/material.dart';
+import 'package:plugin_platform/engine/toast/toast_engine.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+import 'package:shared/utils/log_utils.dart';
+import 'package:shared/utils/util.dart';
+import 'package:widgets/picker/option_pick_util.dart';
+
+import '../../main/main_page.dart';
+import '../create_success/feedback_create_success_page.dart';
+import 'feedback_create_state.dart';
+
+part 'feedback_create_view_model.g.dart';
+
+@riverpod
+class FeedbackCreateViewModel extends _$FeedbackCreateViewModel {
+  @override
+  FeedbackCreateState build() {
+    final state = FeedbackCreateState(imgList: []);
+    initListener(state);
+    ref.onDispose(() {
+      onDispose(state);
+    });
+
+    return state;
+  }
+
+  //选择选项
+  void pickCategory() {
+    _dismissKeyboard();
+
+    OptionPickerUtil.showCupertinoOptionPicker(
+      items: state.optionList,
+      initialSelectIndex: 0,
+      onPickerChanged: (_, index) {
+        state = state.copyWith(selectedOption: state.optionList[index]);
+      },
+    );
+  }
+
+  void _dismissKeyboard() {
+    final FocusNode titleFocusNode = state.formData['title']!['focusNode'];
+    final FocusNode descFocusNode = state.formData['desc']!['focusNode'];
+    titleFocusNode.unfocus();
+    descFocusNode.unfocus();
+  }
+
+  ///提交反馈
+  void submitFeedback() {
+    state = state.copyWith(titleErrorText: null);
+
+    _dismissKeyboard();
+
+    final TextEditingController titleController = state.formData['title']!['controller'];
+    final TextEditingController descController = state.formData['desc']!['controller'];
+
+    final title = titleController.text;
+    final desc = descController.text;
+
+    Log.d('当前待提交的 option:${state.selectedOption} title:$title desc:$desc imgList:${state.imgList}');
+
+    if (Utils.isEmpty(state.selectedOption)) {
+      ToastEngine.show(S.current.choose_category);
+      return;
+    }
+
+    if (Utils.isEmpty(title)) {
+      state = state.copyWith(titleErrorText: "Title cannot be empty!");
+      return;
+    }
+
+    //执行密码登录
+    ToastEngine.show('准备执行请求 option:${state.selectedOption} title:$title desc:$desc imgList:${state.imgList}');
+
+    //去成功页面
+    FeedbackCreateSuccessPage.startInstance();
+  }
+
+  //选中图片
+  void setImgList(List<String> list) {
+    state = state.copyWith(imgList: list);
+  }
+
+  //初始化监听
+  void initListener(FeedbackCreateState initState) {
+    final FocusNode titleFocusNode = initState.formData['title']!['focusNode'];
+
+    titleFocusNode.addListener(() {
+      // 获取焦点的时候清空错误文本
+      if (titleFocusNode.hasFocus) {
+        state = state.copyWith(titleErrorText: null);
+      }
+    });
+  }
+
+  //销毁资源
+  void onDispose(FeedbackCreateState initState) {
+    final FocusNode titleFocusNode = initState.formData['title']!['focusNode'];
+    titleFocusNode.dispose();
+
+    Log.d("FeedbackCreateViewModel 销毁 onDispose");
+  }
+}

+ 27 - 0
packages/cpt_main/lib/modules/feedback/create/feedback_create_view_model.g.dart

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'feedback_create_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$feedbackCreateViewModelHash() =>
+    r'fc34ceec68ee5e8a6175a9a3672a4ff2f60d4c61';
+
+/// See also [FeedbackCreateViewModel].
+@ProviderFor(FeedbackCreateViewModel)
+final feedbackCreateViewModelProvider = AutoDisposeNotifierProvider<
+    FeedbackCreateViewModel, FeedbackCreateState>.internal(
+  FeedbackCreateViewModel.new,
+  name: r'feedbackCreateViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$feedbackCreateViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$FeedbackCreateViewModel = AutoDisposeNotifier<FeedbackCreateState>;
+// ignore_for_file: type=lint
+// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

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

@@ -0,0 +1,74 @@
+import 'package:cpt_main/modules/demo_page.dart';
+import 'package:cpt_main/modules/main/main_page.dart';
+import 'package:cs_resources/generated/assets.dart';
+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:hooks_riverpod/hooks_riverpod.dart';
+import 'package:router/ext/auto_router_extensions.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 '../../../router/page/main_page_router.dart';
+
+@RoutePage()
+class FeedbackCreateSuccessPage extends HookConsumerWidget {
+  const FeedbackCreateSuccessPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.popAndPush(const FeedbackCreateSuccessPageRoute());
+    } else {
+      appRouter.popAndPush(const FeedbackCreateSuccessPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, S.current.published_successfully),
+      backgroundColor: context.appColors.whiteBG,
+      body: Column(
+        children: [
+          Column(
+            mainAxisSize: MainAxisSize.min,
+            children: [
+              const MyAssetImage(Assets.mainSuccessIcon, width: 54, height: 54),
+              MyTextView(
+                S.current.published_successful_txt,
+                marginTop: 12,
+                marginLeft: 55,
+                textAlign: TextAlign.center,
+                marginRight: 55,
+                fontSize: 18,
+                textColor: context.appColors.textBlack,
+                isFontMedium: true,
+              ),
+            ],
+          ).marginOnly(top: 68),
+
+          const Spacer(),
+
+          MyButton(
+            onPressed: () {
+              MainPage.startInstance(context: context);
+            },
+            text: S.current.back_home,
+            textColor: Colors.white,
+            backgroundColor: context.appColors.btnBgDefault,
+            fontWeight: FontWeight.w500,
+            type: ClickType.throttle,
+            fontSize: 16,
+            minHeight: 50,
+            radius: 0,
+          )
+        ],
+      ),
+    );
+  }
+}

+ 215 - 0
packages/cpt_main/lib/modules/feedback/detail/feedback_detail_page.dart

@@ -0,0 +1,215 @@
+import 'package:cpt_main/modules/demo_page.dart';
+import 'package:cs_resources/generated/assets.dart';
+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:hooks_riverpod/hooks_riverpod.dart';
+import 'package:plugin_platform/engine/image/image_nine_grid.dart';
+import 'package:router/ext/auto_router_extensions.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_appbar.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+import '../../../router/page/main_page_router.dart';
+import 'feedback_detail_view_model.dart';
+
+@RoutePage()
+class FeedbackDetailPage extends HookConsumerWidget {
+  const FeedbackDetailPage({Key? key}) : super(key: key);
+
+  //启动当前页面
+  static void startInstance({BuildContext? context}) {
+    if (context != null) {
+      context.router.push(const FeedbackDetailPageRoute());
+    } else {
+      appRouter.push(const FeedbackDetailPageRoute());
+    }
+  }
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final viewModel = ref.watch(feedbackDetailViewModelProvider.notifier);
+    final state = ref.watch(feedbackDetailViewModelProvider);
+
+    return Scaffold(
+      appBar: MyAppBar.appBar(context, S.current.feedback_details, showBottomDivider: true),
+      backgroundColor: context.appColors.backgroundDark,
+      body: SingleChildScrollView(
+          scrollDirection: Axis.vertical,
+          physics: const BouncingScrollPhysics(),
+          child: Column(
+            mainAxisSize: MainAxisSize.max,
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Container(
+                color: context.appColors.whiteBG,
+                width: double.infinity,
+                padding: const EdgeInsets.symmetric(horizontal: 10),
+                height: 85,
+                child: Column(
+                  mainAxisAlignment: MainAxisAlignment.center,
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  children: [
+                    MyTextView(
+                      "Exchange old houses for new ones",
+                      fontSize: 21,
+                      isFontMedium: true,
+                      textColor: context.appColors.textBlack,
+                    ),
+                    MyTextView(
+                      "18 Sep 2024 18:00  |  Security  |  In Progress",
+                      fontSize: 12,
+                      marginTop: 8,
+                      isFontRegular: true,
+                      textColor: context.appColors.textDarkGray,
+                    ),
+                  ],
+                ),
+              ),
+
+              //反馈的内容
+              Container(
+                width: double.infinity,
+                margin: const EdgeInsets.only(left: 12.5, right: 12.5, top: 12.5, bottom: 12.5),
+                padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 25),
+                decoration: BoxDecoration(
+                  color: context.appColors.whiteBG,
+                  borderRadius: BorderRadius.circular(6.0), // 圆角
+                  boxShadow: [
+                    BoxShadow(
+                      color: const Color(0xFFB8BFD9).withOpacity(0.3), // 阴影颜色
+                      offset: const Offset(0, 3), // 阴影的偏移量
+                      blurRadius: 8.0, // 模糊半径
+                      spreadRadius: 3.0, // 扩散半径
+                    ),
+                  ],
+                ),
+                child: Column(
+                  children: [
+                    MyTextView(
+                      "Why are there no implementation rules andapplication methods for exchanging old houses for new ones in Jiang han District?",
+                      fontSize: 15,
+                      marginBottom: 15,
+                      isFontRegular: true,
+                      textColor: context.appColors.textDarkGray,
+                    ),
+
+                    //九宫格展示
+                    ImageNineGrid(
+                      isSelectEnable: false,
+                      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/OE8piEBa-tbqn-wNvWZl8coi4AlzoUD43upEkoAnIkYL8AA/641",
+                        "https://inews.gtimg.com/om_bt/OVx3YS2XJc1zbndGTkjPKW9J0W7kN8M0SIidT-3K4mb2YAA/641",
+                        "https://inews.gtimg.com/om_bt/OAVMydtx9BsJxf5i_thi4Oll9sR1px-Esmtv6UHSxoisEAA/641"
+                      ],
+                      onImagesChanged: (list) {},
+                    ),
+                  ],
+                ),
+              ),
+
+              //回复的数据
+              state.isReplyState ? _buildReplyWidget(context, ref) : _buildWaitingWidget(context)
+            ],
+          )),
+    );
+  }
+
+  Widget _buildReplyWidget(BuildContext context, WidgetRef ref) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        Row(
+          mainAxisSize: MainAxisSize.max,
+          mainAxisAlignment: MainAxisAlignment.start,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            MyTextView(
+              S.current.administrator_reply,
+              fontSize: 18,
+              isFontRegular: true,
+              textColor: context.appColors.textBlack,
+            ).expanded(),
+            MyTextView(
+              "20 sep 2024 18:00",
+              fontSize: 12,
+              isFontRegular: true,
+              textColor: context.appColors.textDarkGray,
+            )
+          ],
+        ).marginOnly(left: 12.5, right: 12.5,bottom: 14,top: 2.5),
+
+        //回复的内容
+        Container(
+          width: double.infinity,
+          margin: const EdgeInsets.only(left: 12.5, right: 12.5, bottom: 13.5),
+          padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 25),
+          decoration: BoxDecoration(
+            color: context.appColors.whiteBG,
+            borderRadius: BorderRadius.circular(6.0), // 圆角
+            boxShadow: [
+              BoxShadow(
+                color: const Color(0xFFB8BFD9).withOpacity(0.3), // 阴影颜色
+                offset: const Offset(0, 3), // 阴影的偏移量
+                blurRadius: 8.0, // 模糊半径
+                spreadRadius: 3.0, // 扩散半径
+              ),
+            ],
+          ),
+          child: Column(
+            children: [
+              MyTextView(
+                "Although the policy of exchanging old houses for new houses in Jianghan District has been released, the specific implementation details and application methods are not yet clear. According to relevant reports, Jianghan District has issued multiple measures for the development of the real estate market, including promoting the trade in policy, but the specific implementation details and application methods have not vet been announced",
+                fontSize: 15,
+                marginBottom: 15,
+                isFontRegular: true,
+                textColor: context.appColors.textDarkGray,
+              ),
+
+              //九宫格展示
+              ImageNineGrid(
+                isSelectEnable: false,
+                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"
+                ],
+                onImagesChanged: (list) {},
+              ),
+            ],
+          ),
+        )
+      ],
+    );
+  }
+
+  Widget _buildWaitingWidget(BuildContext context) {
+    return SizedBox(
+      width: double.infinity,
+      child: Column(
+        children: [
+          const SizedBox(height: 40),
+          const MyAssetImage(Assets.mainFeedbackWaitingIcon, width: 38, height: 38),
+          MyTextView(
+            S.current.waiting_for_the_administrator,
+            fontSize: 15,
+            marginTop: 11,
+            marginBottom: 40,
+            isFontRegular: true,
+            textColor: context.appColors.textDarkGray,
+          )
+        ],
+      ),
+    );
+  }
+}

+ 18 - 0
packages/cpt_main/lib/modules/feedback/detail/feedback_detail_state.dart

@@ -0,0 +1,18 @@
+class FeedbackDetailState{
+
+  //是等待状态还是已完成状态(是否已经回复)
+  bool isReplyState;
+
+  FeedbackDetailState({
+     this.isReplyState = false,
+  });
+
+  FeedbackDetailState copyWith({
+    bool? isReplyState,
+  }) {
+    return FeedbackDetailState(
+      isReplyState: isReplyState ?? this.isReplyState,
+    );
+  }
+
+}

+ 15 - 0
packages/cpt_main/lib/modules/feedback/detail/feedback_detail_view_model.dart

@@ -0,0 +1,15 @@
+
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+
+import 'feedback_detail_state.dart';
+part 'feedback_detail_view_model.g.dart';
+
+@riverpod
+class FeedbackDetailViewModel extends _$FeedbackDetailViewModel {
+
+  @override
+  FeedbackDetailState build(){
+    return FeedbackDetailState();
+  }
+
+}

+ 27 - 0
packages/cpt_main/lib/modules/feedback/detail/feedback_detail_view_model.g.dart

@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'feedback_detail_view_model.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+String _$feedbackDetailViewModelHash() =>
+    r'c319af8c4d4805a867eb1f6481c9e6267e45cc5a';
+
+/// See also [FeedbackDetailViewModel].
+@ProviderFor(FeedbackDetailViewModel)
+final feedbackDetailViewModelProvider = AutoDisposeNotifierProvider<
+    FeedbackDetailViewModel, FeedbackDetailState>.internal(
+  FeedbackDetailViewModel.new,
+  name: r'feedbackDetailViewModelProvider',
+  debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
+      ? null
+      : _$feedbackDetailViewModelHash,
+  dependencies: null,
+  allTransitiveDependencies: null,
+);
+
+typedef _$FeedbackDetailViewModel = AutoDisposeNotifier<FeedbackDetailState>;
+// ignore_for_file: type=lint
+// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

+ 4 - 1
packages/cpt_main/lib/modules/feedback/history/feedback_history.dart

@@ -7,6 +7,7 @@ import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
 
+import '../detail/feedback_detail_page.dart';
 import '../item_feedback.dart';
 import 'feedback_history_view_model.dart';
 
@@ -44,7 +45,9 @@ class FeedbackHistoryScreen extends HookConsumerWidget {
             SliverList(
                 delegate: SliverChildBuilderDelegate(
                       (context, index) {
-                    return FeedbackItem(index: index, item: state.datas[index]);
+                    return FeedbackItem(index: index, item: state.datas[index]).onTap((){
+                      FeedbackDetailPage.startInstance(context: context);
+                    });
                   },
                   childCount: state.datas.length,
                 ))

+ 2 - 1
packages/cpt_main/lib/modules/feedback/item_feedback.dart

@@ -39,6 +39,7 @@ class FeedbackItem extends StatelessWidget {
             children: [
               const MyAssetImage(Assets.mainFeedbackItemIcon, width: 42.5, height: 44),
               Column(
+                crossAxisAlignment: CrossAxisAlignment.start,
                 children: [
 
                   MyTextView(
@@ -56,7 +57,7 @@ class FeedbackItem extends StatelessWidget {
                     isFontRegular: true,
                   ),
                 ],
-              ).expanded(),
+              ).marginOnly(left: 11).expanded(),
             ],
           ),
 

+ 4 - 1
packages/cpt_main/lib/modules/feedback/progress/feedback_progress.dart

@@ -7,6 +7,7 @@ import 'package:widgets/ext/ex_widget.dart';
 import 'package:widgets/load_state_layout.dart';
 import 'package:widgets/widget_export.dart';
 
+import '../detail/feedback_detail_page.dart';
 import '../item_feedback.dart';
 import 'feedback_progress_view_model.dart';
 
@@ -44,7 +45,9 @@ class FeedbackProgressScreen extends HookConsumerWidget {
             SliverList(
                 delegate: SliverChildBuilderDelegate(
                       (context, index) {
-                    return FeedbackItem(index: index, item: state.datas[index]);
+                    return FeedbackItem(index: index, item: state.datas[index]).onTap((){
+                      FeedbackDetailPage.startInstance(context: context);
+                    });
                   },
                   childCount: state.datas.length,
                 ))

+ 2 - 1
packages/cpt_main/lib/modules/feedback/send/feedback_send_large.dart

@@ -1,3 +1,4 @@
+import 'package:cpt_main/modules/feedback/create/feedback_create_page.dart';
 import 'package:cs_resources/generated/assets.dart';
 import 'package:cs_resources/generated/l10n.dart';
 import 'package:cs_resources/theme/app_colors_theme.dart';
@@ -39,7 +40,7 @@ class FeedbackSendLarge extends StatelessWidget {
             ),
             MyButton(
               onPressed: () {
-                ToastEngine.show("去填写表单");
+                FeedbackCreatePage.startInstance(context: context);
               },
               text: S.current.create_new_feedback,
               textColor: Colors.white,

+ 3 - 1
packages/cpt_main/lib/modules/feedback/send/feedback_send_small.dart

@@ -8,6 +8,8 @@ import 'package:widgets/my_button.dart';
 import 'package:widgets/my_load_image.dart';
 import 'package:widgets/my_text_view.dart';
 
+import '../create/feedback_create_page.dart';
+
 class FeedbackSendSmall extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
@@ -36,7 +38,7 @@ class FeedbackSendSmall extends StatelessWidget {
           ),
           MyButton(
             onPressed: () {
-              ToastEngine.show("去填写表单");
+              FeedbackCreatePage.startInstance(context: context);
             },
             text: S.current.create_new_feedback,
             textColor: Colors.white,

+ 10 - 19
packages/cpt_main/lib/modules/visitor/register/visitor_register_page.dart

@@ -7,6 +7,7 @@ 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:widgets/ext/ex_widget.dart';
 import 'package:widgets/my_appbar.dart';
 import 'package:widgets/my_button.dart';
@@ -15,6 +16,7 @@ import 'package:widgets/my_text_view.dart';
 import 'package:widgets/widget_export.dart';
 import 'package:widgets/my_text_field.dart';
 import 'package:widgets/shatter/form_require_text.dart';
+import 'package:widgets/shatter/picker_container.dart';
 
 import '../../../router/page/main_page_router.dart';
 import 'visitor_register_state.dart';
@@ -38,7 +40,7 @@ class VisitorRegisterPage extends HookConsumerWidget {
     final viewModel = ref.watch(visitorRegisterViewModelProvider.notifier);
     final state = ref.watch(visitorRegisterViewModelProvider);
     final noteCount = useState(0);
-   
+
     return Scaffold(
       appBar: MyAppBar.appBar(context, S.current.visitor_registration),
       backgroundColor: context.appColors.whiteBG,
@@ -145,24 +147,13 @@ class VisitorRegisterPage extends HookConsumerWidget {
                 marginTop: 14.5,
                 isFontMedium: true,
               ),
-              // 表单
-              _buildInputLayout(
-                context,
-                state,
-                "access_date",
-                marginTop: 15,
-                enable: false,
-                textInputType: TextInputType.text,
-                textInputAction: TextInputAction.next,
-                showRightIcon: true,
-                rightWidget: const MyAssetImage(Assets.mainVisitorRegisterDate, width: 21, height: 20).paddingOnly(top: 13, bottom: 13),
-                onSubmit: (formKey, value) {
-                  state.formData[formKey]!['focusNode'].unfocus();
-                  FocusScope.of(context).requestFocus(state.formData['note']!['focusNode']);
-                },
-              ).onTap(() {
-                viewModel.pickAccessDate();
-              }),
+              // 选择器
+              PickerContainer(
+                content: state.accessDate == null ? "" : DateTimeUtils.formatDate(state.accessDate, format: 'dd MMM yyyy'),
+                margin: const EdgeInsets.only(top: 16),
+                rightWidget: const MyAssetImage(Assets.mainVisitorRegisterDate, width: 21, height: 20),
+                onClick: viewModel.pickAccessDate,
+              ),
 
               // 备注
               MyTextView(

+ 0 - 6
packages/cpt_main/lib/modules/visitor/register/visitor_register_state.dart

@@ -46,12 +46,6 @@ class VisitorRegisterState {
                 'focusNode': FocusNode(),
                 'obsecure': false,
               },
-              'access_date': {
-                'value': '',
-                'controller': TextEditingController(),
-                'focusNode': FocusNode(),
-                'obsecure': false,
-              },
               'note': {
                 'value': '',
                 'controller': TextEditingController(),

+ 1 - 3
packages/cpt_main/lib/modules/visitor/register/visitor_register_view_model.dart

@@ -76,7 +76,7 @@ class VisitorRegisterViewModel extends _$VisitorRegisterViewModel {
     }
 
     //执行密码登录
-    ToastEngine.show('准备执行请求发送验证码 fullName:$fullName phone:$phone nric:$nric plateNumber:$plateNumber note:$note accessDate:$accessDate');
+    ToastEngine.show('准备执行请求 fullName:$fullName phone:$phone nric:$nric plateNumber:$plateNumber note:$note accessDate:$accessDate');
 
     //去首页
     MainPage.startInstance();
@@ -89,8 +89,6 @@ class VisitorRegisterViewModel extends _$VisitorRegisterViewModel {
       mode: CupertinoDatePickerMode.date,
       onDateTimeChanged: (date) {
        state = state.copyWith(accessDate: date);
-       final TextEditingController accessDateController = state.formData['access_date']!['controller'];
-       accessDateController.text = DateTimeUtils.formatDate(date,format: 'dd MMM yyyy');
       },
       title: S.current.access_date,
     );

+ 1 - 1
packages/cpt_main/lib/modules/visitor/register/visitor_register_view_model.g.dart

@@ -7,7 +7,7 @@ part of 'visitor_register_view_model.dart';
 // **************************************************************************
 
 String _$visitorRegisterViewModelHash() =>
-    r'efcd5105243eb7a8ec68d0ff5d428e7eb72fded0';
+    r'7ce971f03307d867b5069f6abff1a28ac4eea1eb';
 
 /// See also [VisitorRegisterViewModel].
 @ProviderFor(VisitorRegisterViewModel)

+ 6 - 0
packages/cpt_main/lib/router/page/main_page_router.dart

@@ -23,6 +23,9 @@ import '../../modules/home/latest_news/publish/latest_news_publish_screen.dart';
 import '../../modules/home/latest_news/latest_news_page.dart';
 import '../../modules/home/management_guides/management_guides_page.dart';
 import '../../modules/visitor/register/visitor_register_page.dart';
+import '../../modules/feedback/create/feedback_create_page.dart';
+import '../../modules/feedback/detail/feedback_detail_page.dart';
+import '../../modules/feedback/create_success/feedback_create_success_page.dart';
 
 part 'main_page_router.gr.dart';
 
@@ -75,5 +78,8 @@ class MainPageRouter extends _$MainPageRouter {
         ),
         CustomRoute(page: ManagementGuidesPageRoute.page, path: RouterPath.homeManagementGuides, transitionsBuilder: applySlideTransition),
         CustomRoute(page: VisitorRegisterPageRoute.page, path: RouterPath.visitorRegister, transitionsBuilder: applySlideTransition),
+        CustomRoute(page: FeedbackCreatePageRoute.page, path: RouterPath.feedbackCreate, transitionsBuilder: applySlideTransition),
+        CustomRoute(page: FeedbackCreateSuccessPageRoute.page, path: RouterPath.feedbackCreateSuccess, transitionsBuilder: applySlideTransition),
+        CustomRoute(page: FeedbackDetailPageRoute.page, path: RouterPath.feedbackDetail, transitionsBuilder: applySlideTransition),
       ];
 }

+ 60 - 0
packages/cpt_main/lib/router/page/main_page_router.gr.dart

@@ -15,6 +15,24 @@ abstract class _$MainPageRouter extends RootStackRouter {
 
   @override
   final Map<String, PageFactory> pagesMap = {
+    FeedbackCreatePageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const FeedbackCreatePage(),
+      );
+    },
+    FeedbackCreateSuccessPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const FeedbackCreateSuccessPage(),
+      );
+    },
+    FeedbackDetailPageRoute.name: (routeData) {
+      return AutoRoutePage<dynamic>(
+        routeData: routeData,
+        child: const FeedbackDetailPage(),
+      );
+    },
     FeedbackHistoryPageRoute.name: (routeData) {
       return AutoRoutePage<dynamic>(
         routeData: routeData,
@@ -139,6 +157,48 @@ abstract class _$MainPageRouter extends RootStackRouter {
 }
 
 /// generated route for
+/// [FeedbackCreatePage]
+class FeedbackCreatePageRoute extends PageRouteInfo<void> {
+  const FeedbackCreatePageRoute({List<PageRouteInfo>? children})
+      : super(
+          FeedbackCreatePageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'FeedbackCreatePageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
+/// [FeedbackCreateSuccessPage]
+class FeedbackCreateSuccessPageRoute extends PageRouteInfo<void> {
+  const FeedbackCreateSuccessPageRoute({List<PageRouteInfo>? children})
+      : super(
+          FeedbackCreateSuccessPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'FeedbackCreateSuccessPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
+/// [FeedbackDetailPage]
+class FeedbackDetailPageRoute extends PageRouteInfo<void> {
+  const FeedbackDetailPageRoute({List<PageRouteInfo>? children})
+      : super(
+          FeedbackDetailPageRoute.name,
+          initialChildren: children,
+        );
+
+  static const String name = 'FeedbackDetailPageRoute';
+
+  static const PageInfo<void> page = PageInfo<void>(name);
+}
+
+/// generated route for
 /// [FeedbackHistoryScreen]
 class FeedbackHistoryPageRoute extends PageRouteInfo<void> {
   const FeedbackHistoryPageRoute({List<PageRouteInfo>? children})

+ 1 - 0
packages/cs_plugin_platform/lib/engine/image/image_nine_grid.dart

@@ -9,6 +9,7 @@ import 'package:widgets/my_text_view.dart';
 import 'image_preview.dart';
 import 'package:cs_resources/generated/l10n.dart';
 
+/// 九宫格的图片选择与图片展示
 class ImageNineGrid extends StatefulWidget {
   final bool isSelectEnable; // 是否能选择
   final List<String> initialImages; // 初始化图片集合

+ 4 - 2
packages/cs_resources/lib/generated/intl/messages_en.dart

@@ -26,8 +26,6 @@ class MessageLookup extends MessageLookupByLibrary {
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
-        "Up_to_max_images": MessageLookupByLibrary.simpleMessage(
-            "(Up to 10 images can be uploaded)"),
         "access_date": MessageLookupByLibrary.simpleMessage("Access Date"),
         "account_deactivate_alert": MessageLookupByLibrary.simpleMessage(
             "Are you sure you want to deactivate your account? You will not be able to login into the app once you proceed with the request."),
@@ -75,6 +73,8 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("Estate or Building Name?"),
         "facility": MessageLookupByLibrary.simpleMessage("Facility"),
         "feedback": MessageLookupByLibrary.simpleMessage("FeedBack"),
+        "feedback_details":
+            MessageLookupByLibrary.simpleMessage("FeedBack Details"),
         "feedback_msg_1": MessageLookupByLibrary.simpleMessage(
             "Help us keep your estate beautiful"),
         "feedback_msg_2": MessageLookupByLibrary.simpleMessage(
@@ -191,6 +191,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "tries_left": MessageLookupByLibrary.simpleMessage("Tries Left"),
         "type_here": MessageLookupByLibrary.simpleMessage("Type Here"),
         "unit_number": MessageLookupByLibrary.simpleMessage("Unit Number"),
+        "up_to_max_images": MessageLookupByLibrary.simpleMessage(
+            "(Up to 10 images can be uploaded)"),
         "upload": MessageLookupByLibrary.simpleMessage("Upload"),
         "upload_doc_desc": MessageLookupByLibrary.simpleMessage(
             "The Management requires that you upload the following documents to verify your tenancy. You may redact sensitive financia information"),

+ 3 - 2
packages/cs_resources/lib/generated/intl/messages_zh_CN.dart

@@ -26,8 +26,6 @@ class MessageLookup extends MessageLookupByLibrary {
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
-        "Up_to_max_images":
-            MessageLookupByLibrary.simpleMessage("(您最多可以上传10张图片)"),
         "access_date": MessageLookupByLibrary.simpleMessage("访问日期"),
         "account_deactivate_alert": MessageLookupByLibrary.simpleMessage(
             "您确定要停用您的帐户吗?一旦您继续执行请求,您将无法登录应用程序。"),
@@ -65,6 +63,7 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("房产或建筑名称?"),
         "facility": MessageLookupByLibrary.simpleMessage("设施"),
         "feedback": MessageLookupByLibrary.simpleMessage("反馈"),
+        "feedback_details": MessageLookupByLibrary.simpleMessage("反馈详情"),
         "feedback_msg_1": MessageLookupByLibrary.simpleMessage("帮助我们保持您的房产美丽"),
         "feedback_msg_2": MessageLookupByLibrary.simpleMessage(
             "有些事情需要我们关注,或者如果你有一个很棒的建议,我们想听听你的意见!"),
@@ -156,6 +155,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "tries_left": MessageLookupByLibrary.simpleMessage("次尝试机会"),
         "type_here": MessageLookupByLibrary.simpleMessage("在此输入"),
         "unit_number": MessageLookupByLibrary.simpleMessage("单元"),
+        "up_to_max_images":
+            MessageLookupByLibrary.simpleMessage("(您最多可以上传10张图片)"),
         "upload": MessageLookupByLibrary.simpleMessage("上传"),
         "upload_doc_desc": MessageLookupByLibrary.simpleMessage(
             "管理员要求您上传以下文件以验证您的租约。您可以编辑敏感的财务信息"),

+ 3 - 2
packages/cs_resources/lib/generated/intl/messages_zh_HK.dart

@@ -26,8 +26,6 @@ class MessageLookup extends MessageLookupByLibrary {
 
   final messages = _notInlinedMessages(_notInlinedMessages);
   static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
-        "Up_to_max_images":
-            MessageLookupByLibrary.simpleMessage("(您最多可以上传10张图片)"),
         "access_date": MessageLookupByLibrary.simpleMessage("访问日期"),
         "account_deactivate_alert": MessageLookupByLibrary.simpleMessage(
             "您确定要停用您的帐户吗?一旦您继续执行请求,您将无法登录应用程序。"),
@@ -65,6 +63,7 @@ class MessageLookup extends MessageLookupByLibrary {
             MessageLookupByLibrary.simpleMessage("房产或建筑名称?"),
         "facility": MessageLookupByLibrary.simpleMessage("設施"),
         "feedback": MessageLookupByLibrary.simpleMessage("反馈"),
+        "feedback_details": MessageLookupByLibrary.simpleMessage("反馈详情"),
         "feedback_msg_1": MessageLookupByLibrary.simpleMessage("帮助我们保持您的房产美丽"),
         "feedback_msg_2": MessageLookupByLibrary.simpleMessage(
             "有些事情需要我们关注,或者如果你有一个很棒的建议,我们想听听你的意见!"),
@@ -143,6 +142,8 @@ class MessageLookup extends MessageLookupByLibrary {
         "tries_left": MessageLookupByLibrary.simpleMessage("次尝试机会"),
         "type_here": MessageLookupByLibrary.simpleMessage("在此输入"),
         "unit_number": MessageLookupByLibrary.simpleMessage("单元"),
+        "up_to_max_images":
+            MessageLookupByLibrary.simpleMessage("(您最多可以上传10张图片)"),
         "upload": MessageLookupByLibrary.simpleMessage("上传"),
         "upload_doc_desc": MessageLookupByLibrary.simpleMessage(
             "管理员要求您上传以下文件以验证您的租约。您可以编辑敏感的财务信息"),

+ 12 - 2
packages/cs_resources/lib/generated/l10n.dart

@@ -1321,10 +1321,10 @@ class S {
   }
 
   /// `(Up to 10 images can be uploaded)`
-  String get Up_to_max_images {
+  String get up_to_max_images {
     return Intl.message(
       '(Up to 10 images can be uploaded)',
-      name: 'Up_to_max_images',
+      name: 'up_to_max_images',
       desc: '',
       args: [],
     );
@@ -1380,6 +1380,16 @@ class S {
     );
   }
 
+  /// `FeedBack Details`
+  String get feedback_details {
+    return Intl.message(
+      'FeedBack Details',
+      name: 'feedback_details',
+      desc: '',
+      args: [],
+    );
+  }
+
   /// `Other`
   String get other {
     return Intl.message(

+ 2 - 1
packages/cs_resources/lib/l10n/intl_en.arb

@@ -126,11 +126,12 @@
   "describe_your_feedback": "Describe Your FeedBack",
   "upload_pictures": "Upload Pictures",
   "send_feedback": "Send FeedBack",
-  "Up_to_max_images": "(Up to 10 images can be uploaded)",
+  "up_to_max_images": "(Up to 10 images can be uploaded)",
   "published_successfully": "Published Successfully",
   "published_successful_txt": "Your feedback has been successfully sent! We will reply to you as soon as possible! thank you!",
   "back_home": "Back Home",
   "waiting_for_the_administrator": "Waiting for the administrator",
   "administrator_reply": "Administrator Reply",
+  "feedback_details": "FeedBack Details",
   "other": "Other"
 }

+ 2 - 1
packages/cs_resources/lib/l10n/intl_zh_CN.arb

@@ -126,11 +126,12 @@
   "describe_your_feedback": "描述您的反馈",
   "upload_pictures": "上传图片",
   "send_feedback": "发送反馈",
-  "Up_to_max_images": "(您最多可以上传10张图片)",
+  "up_to_max_images": "(您最多可以上传10张图片)",
   "published_successfully": "发布成功",
   "published_successful_txt": "您的反馈已发送成功,我们会尽快回复您的反馈,谢谢!",
   "back_home": "返回首页",
   "waiting_for_the_administrator": "等待管理员回复",
   "administrator_reply": "管理员回复",
+  "feedback_details": "反馈详情",
   "other": "其他"
 }

+ 2 - 1
packages/cs_resources/lib/l10n/intl_zh_HK.arb

@@ -112,11 +112,12 @@
   "describe_your_feedback": "描述您的反馈",
   "upload_pictures": "上传图片",
   "send_feedback": "发送反馈",
-  "Up_to_max_images": "(您最多可以上传10张图片)",
+  "up_to_max_images": "(您最多可以上传10张图片)",
   "published_successfully": "发布成功",
   "published_successful_txt": "您的反馈已发送成功,我们会尽快回复您的反馈,谢谢!",
   "back_home": "返回首页",
   "waiting_for_the_administrator": "等待管理员回复",
   "administrator_reply": "管理员回复",
+  "feedback_details": "反馈详情",
   "other": "其他"
 }

+ 64 - 0
packages/cs_widgets/lib/shatter/picker_container.dart

@@ -0,0 +1,64 @@
+import 'package:cs_resources/generated/assets.dart';
+import 'package:cs_resources/theme/app_colors_theme.dart';
+import 'package:flutter/material.dart';
+import 'package:widgets/ext/ex_widget.dart';
+import 'package:widgets/my_load_image.dart';
+import 'package:widgets/my_text_view.dart';
+
+//下拉选的默认样式
+class PickerContainer extends StatelessWidget {
+  final bool enable;
+  final String? hint;
+  final String? content;
+  final Widget? rightWidget;
+  final double height;
+  final Color? bgColor;
+  final EdgeInsetsGeometry? margin;
+  final VoidCallback onClick;
+
+  const PickerContainer({
+    required this.onClick,
+    this.enable = true,
+    this.hint,
+    this.content,
+    this.margin,
+    this.rightWidget,
+    this.bgColor,
+    this.height = 55,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+        height: height,
+        margin: margin,
+        padding: const EdgeInsets.symmetric(horizontal: 15),
+        decoration: BoxDecoration(
+          color: context.appColors.authFiledBG,
+          borderRadius: const BorderRadius.all(Radius.circular(5)),
+        ),
+        child: Row(
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            MyTextView(
+              content ?? "",
+              hint: hint,
+              textColor: context.appColors.textBlack,
+              isFontMedium: true,
+              fontSize: 16,
+            ).expanded(),
+            rightWidget != null
+                ? rightWidget!
+                : const MyAssetImage(
+                    Assets.baseServiceTriangleDropDownIcon,
+                    width: 11.5,
+                    height: 6.5,
+                  ),
+          ],
+        )).onTap(() {
+      if (enable) {
+        onClick.call();
+      }
+    });
+  }
+}