浏览代码

[feat]亲密度分析,截图回复-对话分析Tab,增加上传卡片和选项卡片

hezihao 7 月之前
父节点
当前提交
ebb89580cc

+ 1 - 0
assets/string/base/string.xml

@@ -282,6 +282,7 @@
     <string name="intimacy_analyse_upload_screenshot_sample_publish_time">刚刚</string>
 
     <string name="intimacy_analyse_sample_image">示例图</string>
+    <string name="intimacy_analyse_look_analyse">查看分析</string>
 
     <string name="next_step">下一步</string>
     <string name="recently">最近</string>

+ 4 - 33
lib/module/intimacy_analyse/intimacy_analyse_upload/intimacy_analyse_upload_page.dart

@@ -20,6 +20,7 @@ import '../../../widget/gradient_text.dart';
 import '../widget/intimacy_analyse_report_widget.dart';
 import '../widget/intimacy_user_widget.dart';
 import '../widget/option_select_widget.dart';
+import '../widget/step/upload_step_card.dart';
 import '../widget/step_card.dart';
 import 'intimacy_analyse_upload_controller.dart';
 
@@ -130,45 +131,15 @@ class IntimacyAnalyseUploadPage
 
   /// 上传步骤卡片
   Widget _buildUploadStepCard() {
-    return StepCard(
-      bgImageProvider: Assets.images.bgIntimacyAnalyseUploadCard.provider(),
+    return UploadStepCard(
       stepLabel: StringFormatUtil.formatStr(
         StringName.intimacyAnalyseStep,
         1.toString(),
       ),
       stepTitle: StringName.intimacyAnalyseStepTitleSelectImage,
       stepDesc: StringName.intimacyAnalyseUploadCardTip,
-      topIconWidget: Assets.images.iconIntimacyAnalyseUploadTop.image(
-        height: 63.h,
-        width: 103.w,
-      ),
-      contentWidget: Column(
-        children: [
-          // 图片九宫格
-          Container(
-            margin: EdgeInsets.only(left: 12.w, right: 12.w),
-            padding: EdgeInsets.only(
-              left: 12.w,
-              top: 12.h,
-              right: 12.w,
-              bottom: 12.h,
-            ),
-            decoration: BoxDecoration(
-              color: ColorName.white,
-              borderRadius: BorderRadius.circular(16.r),
-            ),
-            child: UploadNineGrid(
-              mode: Mode.edit,
-              imageSrcList: ["", "", "", "", "", "", ""],
-              maxCount: 9,
-              spacing: 8.0,
-            ),
-          ),
-          SizedBox(height: 10.h),
-          // 当前的亲密关系
-          _buildRecommendIntimacy(),
-        ],
-      ),
+      // 底部,添加上当前的亲密关系
+      bottomChild: _buildRecommendIntimacy(),
     );
   }
 

+ 78 - 3
lib/module/intimacy_analyse/screenshot_reply/conversation_analysis/conversation_analysis_controller.dart

@@ -1,10 +1,85 @@
+import 'package:flutter/cupertino.dart';
+import 'package:get/get.dart';
 import 'package:injectable/injectable.dart';
 import 'package:keyboard/base/base_controller.dart';
+import 'package:wechat_assets_picker/wechat_assets_picker.dart';
+
+import '../../../../data/bean/option_select_config.dart';
+import '../../../../data/bean/option_select_item.dart';
+import '../../../../utils/image_picker_util.dart';
 
 /// 对话分析Controller
 @injectable
 class ConversationAnalysisController extends BaseController {
-  /// 点击上传截图按钮
-  void clickUploadScreenshotBtn() {
+  /// 是否是上传页
+  Rx<bool> isUploadPage = false.obs;
+
+  /// 是否已解锁
+  Rx<bool> isUnlock = false.obs;
+
+  /// 选项列表
+  RxList<OptionSelectConfig> optionSelectConfigList =
+      <OptionSelectConfig>[].obs;
+
+  @override
+  void onReady() {
+    super.onReady();
+    _initDirectionOptionSelectConfigList();
+  }
+
+  void _initDirectionOptionSelectConfigList() {
+    optionSelectConfigList.add(
+      OptionSelectConfig("对于TA", "", [
+        OptionSelectItem("现在的需求", false),
+        OptionSelectItem("真实想法", false),
+        OptionSelectItem("渣渣鉴定", false),
+      ]),
+    );
+    optionSelectConfigList.add(
+      OptionSelectConfig("对于我", "", [
+        OptionSelectItem("帮回", false),
+        OptionSelectItem("告白", false),
+        OptionSelectItem("复合", false),
+      ]),
+    );
+  }
+
+  /// 选中选项
+  void selectOption(
+      OptionSelectConfig rowConfig,
+      OptionSelectItem optionItem,
+      ) {
+    // 先全部反选
+    rowConfig.options =
+        rowConfig.options.map((ele) {
+          ele.selected = false;
+          return ele;
+        }).toList();
+    // 再勾选当前的选中项
+    optionItem.selected = true;
+    // 由于Rx响应式变量,无法监听对象中嵌套对象的某个属性的变化,导致页面不会刷新,需要手动刷新页面
+    optionSelectConfigList.refresh();
+  }
+
+  /// 点击解锁按钮
+  void clickUnlockBtn(BuildContext context) async {}
+
+  /// 点击查看分析按钮
+  void clickLookAnalyseBtn(BuildContext context) async {}
+
+  /// 点击上传按钮
+  void clickUploadBtn(BuildContext context) async {
+    // 跳转到图片选择,并返回选择的图片列表
+    List<AssetEntity> selectedAssetList = await ImagePickerUtil.pickImage(
+      context,
+      maxAssetsCount: 9,
+    );
+    // 选择了图片,切换到上传视图
+    if (selectedAssetList.isNotEmpty) {
+      isUploadPage.value = true;
+    } else {
+      // 没选择图片,切换到例子视图
+      isUploadPage.value = false;
+    }
   }
-}
+}

+ 177 - 12
lib/module/intimacy_analyse/screenshot_reply/conversation_analysis/conversation_analysis_view.dart

@@ -1,10 +1,15 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart';
 import 'package:keyboard/base/base_view.dart';
 
+import '../../../../data/bean/option_select_config.dart';
+import '../../../../data/bean/option_select_item.dart';
 import '../../../../resource/assets.gen.dart';
 import '../../../../resource/colors.gen.dart';
 import '../../../../resource/string.gen.dart';
+import '../../widget/option_select_widget.dart';
+import '../../widget/step/upload_step_card.dart';
 import '../../widget/step_card.dart';
 import 'conversation_analysis_controller.dart';
 
@@ -22,19 +27,104 @@ class ConversationAnalysisView
   Widget buildBody(BuildContext context) {
     return Stack(
       children: [
-        Column(
-          children: [
-            // 上传聊天记录例子卡片
-            _buildChatRecordSampleCard(),
-          ],
-        ),
+        Obx(() {
+          return _buildContentList();
+        }),
         // 上传截图按钮
         Positioned.fill(
           child: Align(
             alignment: Alignment.bottomCenter,
-            child: _buildBottomLayout(context),
+            child: Obx(() {
+              return _buildBottomLayout(context);
+            }),
+          ),
+        ),
+      ],
+    );
+  }
+
+  /// 内容列表
+  Widget _buildContentList() {
+    Widget contentWidget;
+    if (controller.isUploadPage.value) {
+      contentWidget = Column(
+        children: [
+          // 上传聊天记录卡片
+          _buildUploadCard(),
+          // 选项卡片
+          _buildOptionCard(),
+          // 距离底部有一定间距
+          SizedBox(height: 90.h),
+        ],
+      );
+    } else {
+      // 例子列表
+      contentWidget = Column(
+        children: [
+          // 上传聊天记录例子卡片
+          _buildChatRecordSampleCard(),
+        ],
+      );
+    }
+    return SingleChildScrollView(child: contentWidget);
+  }
+
+  /// 上传步骤卡片
+  Widget _buildUploadCard() {
+    return UploadStepCard(
+      stepTitle: StringName.intimacyConversationAnalysis,
+      stepDesc: StringName.intimacyConversationAnalysisCardTip,
+    );
+  }
+
+  /// 选项卡片
+  Widget _buildOptionCard() {
+    return StepCard(
+      hasStep: false,
+      contentWidget: Column(
+        children: [
+          Container(
+            margin: EdgeInsets.only(left: 12.w, top: 17.h, right: 12.w),
+            padding: EdgeInsets.only(
+              left: 12.w,
+              top: 12.h,
+              right: 12.w,
+              bottom: 12.h,
+            ),
+            decoration: BoxDecoration(
+              color: ColorName.white,
+              borderRadius: BorderRadius.circular(16.r),
+            ),
+            child: Obx(() {
+              return Column(
+                children: [
+                  // 添加选项行
+                  for (var optionConfig in controller.optionSelectConfigList)
+                    _buildOptionRow(optionConfig),
+                ],
+              );
+            }),
           ),
+        ],
+      ),
+    );
+  }
+
+  /// 构建一行选择选项行
+  Widget _buildOptionRow(OptionSelectConfig config) {
+    return Column(
+      children: [
+        // 选择项
+        OptionSelectWidget(
+          optionSelect: config,
+          optionSelectCallback: (
+            OptionSelectConfig rowConfig,
+            OptionSelectItem optionItem,
+          ) {
+            controller.selectOption(rowConfig, optionItem);
+          },
         ),
+        SizedBox(height: 20.h),
       ],
     );
   }
@@ -98,11 +188,72 @@ class ConversationAnalysisView
     );
   }
 
+  /// 解锁按钮
+  Widget _buildUnlockBtn(BuildContext context) {
+    return GestureDetector(
+      onTap: () {
+        controller.clickUnlockBtn(context);
+      },
+      child: Container(
+        margin: EdgeInsets.symmetric(horizontal: 16.w),
+        padding: EdgeInsets.symmetric(vertical: 14.h),
+        width: double.maxFinite,
+        decoration: ShapeDecoration(
+          color: ColorName.colorBrand,
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(50.r),
+          ),
+        ),
+        child: Row(
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: [
+            Assets.images.iconIntimacyAnalyseUnlock.image(
+              width: 22,
+              height: 22,
+            ),
+            SizedBox(width: 4.w),
+            Text(
+              StringName.intimacyUnlockAnalyse,
+              style: TextStyle(
+                color: ColorName.white,
+                fontSize: 16.sp,
+                fontWeight: FontWeight.w500,
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
   /// 上传截图按钮
-  Widget _buildUploadScreenshotBtn() {
+  Widget _buildUploadScreenshotBtn(BuildContext context) {
+    return _buildGradientBtn(
+      btnText: StringName.intimacyUploadScreenshot,
+      onPressed: () {
+        controller.clickUploadBtn(context);
+      },
+    );
+  }
+
+  /// 查看分析按钮
+  Widget _buildLookAnalyseBtn(BuildContext context) {
+    return _buildGradientBtn(
+      btnText: StringName.intimacyAnalyseLookAnalyse,
+      onPressed: () {
+        controller.clickLookAnalyseBtn(context);
+      },
+    );
+  }
+
+  /// 渐变按钮
+  Widget _buildGradientBtn({
+    required String btnText,
+    required VoidCallback onPressed,
+  }) {
     return GestureDetector(
       onTap: () {
-        controller.clickUploadScreenshotBtn();
+        onPressed();
       },
       child: Container(
         margin: EdgeInsets.symmetric(horizontal: 16.w),
@@ -121,7 +272,7 @@ class ConversationAnalysisView
         ),
         child: Center(
           child: Text(
-            StringName.intimacyUploadScreenshot,
+            btnText,
             style: TextStyle(
               color: ColorName.white,
               fontSize: 16.sp,
@@ -135,13 +286,27 @@ class ConversationAnalysisView
 
   /// 底部布局
   Widget _buildBottomLayout(BuildContext context) {
+    Widget btn;
+    // 已解锁
+    if (controller.isUnlock.value) {
+      btn = _buildUnlockBtn(context);
+    } else {
+      // 未解锁,已在上传阶段,则显示查看分析按钮
+      if (controller.isUploadPage.value) {
+        btn = _buildLookAnalyseBtn(context);
+      } else {
+        // 例子阶段,则显示上传截图按钮
+        btn = _buildUploadScreenshotBtn(context);
+      }
+    }
     return Column(
       // 高度包裹内容
       mainAxisSize: MainAxisSize.min,
       crossAxisAlignment: CrossAxisAlignment.start,
       children: [
-        // 上传截图按钮
-        _buildUploadScreenshotBtn(), SizedBox(height: 20.h),
+        // 操作按钮
+        btn,
+        SizedBox(height: 20.h),
       ],
     );
   }

+ 2 - 2
lib/module/intimacy_analyse/widget/option_select_widget.dart

@@ -78,7 +78,7 @@ class OptionSelectWidget extends StatelessWidget {
       direction: Axis.horizontal,
       alignment: WrapAlignment.start,
       // 主轴间距
-      spacing: 9.0,
+      spacing: 8.0,
       // 交叉轴间距
       runSpacing: 7.0,
       children: [
@@ -124,7 +124,7 @@ class OptionSelectWidget extends StatelessWidget {
         optionSelectCallback(rowConfig, optionItem);
       },
       child: Container(
-        padding: EdgeInsets.symmetric(horizontal: 18.w, vertical: 8.h),
+        padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h),
         decoration: bgDecoration,
         child: Text(
           optionItem.name,

+ 73 - 0
lib/module/intimacy_analyse/widget/step/upload_step_card.dart

@@ -0,0 +1,73 @@
+import 'package:flutter/cupertino.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+
+import '../../../../resource/assets.gen.dart';
+import '../../../../resource/colors.gen.dart';
+import '../../intimacy_analyse_upload/widget/upload_nine_grid.dart';
+import '../step_card.dart';
+
+/// 上传步骤卡片
+class UploadStepCard extends StatelessWidget {
+  /// 步骤标签
+  final String? stepLabel;
+
+  /// 步骤标题
+  final String? stepTitle;
+
+  /// 步骤描述
+  final String? stepDesc;
+
+  /// 底部的子组件,可以没有
+  final Widget? bottomChild;
+
+  const UploadStepCard({
+    super.key,
+    this.stepLabel,
+    required this.stepTitle,
+    required this.stepDesc,
+    this.bottomChild,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return StepCard(
+      bgImageProvider: Assets.images.bgIntimacyAnalyseUploadCard.provider(),
+      stepLabel: stepLabel,
+      stepTitle: stepTitle,
+      stepDesc: stepDesc,
+      // 顶部的图标
+      topIconWidget: Assets.images.iconIntimacyAnalyseUploadTop.image(
+        height: 63.h,
+        width: 103.w,
+      ),
+      contentWidget: Column(
+        children: [
+          // 图片九宫格
+          Container(
+            margin: EdgeInsets.only(left: 12.w, right: 12.w),
+            padding: EdgeInsets.only(
+              left: 12.w,
+              top: 12.h,
+              right: 12.w,
+              bottom: 12.h,
+            ),
+            decoration: BoxDecoration(
+              color: ColorName.white,
+              borderRadius: BorderRadius.circular(16.r),
+            ),
+            // 图片九宫格
+            child: UploadNineGrid(
+              mode: Mode.edit,
+              imageSrcList: ["", "", "", "", "", "", ""],
+              maxCount: 9,
+              spacing: 8.0,
+            ),
+          ),
+          SizedBox(height: 10.h),
+          // 当前的亲密关系
+          bottomChild ?? SizedBox(),
+        ],
+      ),
+    );
+  }
+}

+ 82 - 28
lib/module/intimacy_analyse/widget/step_card.dart

@@ -1,6 +1,5 @@
 import 'package:flutter/cupertino.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
-import 'package:get/get.dart';
 import '../../../resource/colors.gen.dart';
 import '../../../widget/gradient_text.dart';
 import '../intimacy_analyse_upload/widget/step_label_widget.dart';
@@ -8,16 +7,16 @@ import '../intimacy_analyse_upload/widget/step_label_widget.dart';
 /// 步骤卡片,支持设置卡片背景、步骤标题、步骤描述、顶部图标和内容区域
 class StepCard extends StatelessWidget {
   /// 卡片背景
-  final ImageProvider bgImageProvider;
+  final ImageProvider? bgImageProvider;
 
   /// 步骤标签
   final String? stepLabel;
 
   /// 步骤标题
-  final String stepTitle;
+  final String? stepTitle;
 
   /// 步骤描述
-  final String stepDesc;
+  final String? stepDesc;
 
   /// 顶部图标
   final Image? topIconWidget;
@@ -25,18 +24,44 @@ class StepCard extends StatelessWidget {
   /// 内容组件
   final Widget contentWidget;
 
+  /// 是否有步骤
+  final bool hasStep;
+
   const StepCard({
     super.key,
-    required this.bgImageProvider,
-    required this.stepLabel,
-    required this.stepTitle,
-    required this.stepDesc,
+    this.bgImageProvider,
+    this.stepLabel,
+    this.stepTitle,
+    this.stepDesc,
+    this.hasStep = true,
     required this.contentWidget,
     this.topIconWidget,
   });
 
   @override
   Widget build(BuildContext context) {
+    BoxDecoration decoration;
+    // 没有背景图,使用渐变背景
+    if (bgImageProvider == null) {
+      decoration = BoxDecoration(
+        gradient: LinearGradient(
+          colors: [
+            Color(0xFFEFE9FF),
+            Color(0xFFFBFAFF),
+          ],
+          begin: Alignment.topCenter,
+          end: Alignment.bottomCenter,
+        ),
+        shape: BoxShape.rectangle,
+        border: Border.all(color: ColorName.white80, width: 1.w),
+        borderRadius: BorderRadius.all(Radius.circular(20.r)),
+      );
+    } else {
+      // 背景图
+      decoration = BoxDecoration(
+        image: DecorationImage(image: bgImageProvider!, fit: BoxFit.fill),
+      );
+    }
     return Container(
       margin: EdgeInsets.only(left: 12.w, top: 10.h, right: 12.w),
       child: Stack(
@@ -49,27 +74,12 @@ class StepCard extends StatelessWidget {
               : Positioned(top: -11.h, right: 0, child: topIconWidget!),
           // 卡片背景
           Container(
-            decoration: BoxDecoration(
-              image: DecorationImage(image: bgImageProvider, fit: BoxFit.fill),
-            ),
+            decoration: decoration,
             child: Column(
               // 左对齐
               crossAxisAlignment: CrossAxisAlignment.start,
               children: [
-                // 步骤标题
-                Container(
-                  margin: EdgeInsets.only(
-                    // 存在步骤标签时,才有左边距
-                    left: hasStepLabel() ? 12.w : 0,
-                    top: 16.h,
-                  ),
-                  child: _buildStepTitle(),
-                ),
-                SizedBox(height: 4.h),
-                // 步骤描述
-                stepDesc.isNotEmpty
-                    ? _buildStepDesc(stepDesc)
-                    : SizedBox(height: 6.h),
+                _buildStepLayout(),
                 // 内容区域
                 contentWidget,
                 SizedBox(height: 12.h),
@@ -81,17 +91,61 @@ class StepCard extends StatelessWidget {
     );
   }
 
+  /// 步骤
+  Widget _buildStepLayout() {
+    if (!hasStep) {
+      return SizedBox();
+    }
+
+    String stepDescStr = stepDesc ?? "";
+
+    return Column(
+      children: [
+        // 步骤标题
+        Container(
+          margin: EdgeInsets.only(
+            // 存在步骤标签时,才有左边距
+            left: _hasStepLabel() ? 12.w : 0,
+            top: 16.h,
+            bottom: 4.h,
+          ),
+          child: _buildStepTitle(),
+        ),
+        SizedBox(height: 4.h),
+        // 步骤描述
+        stepDescStr.isNotEmpty
+            ? _buildStepDesc(stepDescStr)
+            : SizedBox(height: 6.h),
+        SizedBox(height: 14.h),
+      ],
+    );
+  }
+
   /// 是否有步骤标签
-  bool hasStepLabel() {
+  bool _hasStepLabel() {
     String stepLabelStr = stepLabel ?? "";
     return stepLabelStr.isNotEmpty == true;
   }
 
+  /// 是否有步骤标题
+  bool _hasStepTitle() {
+    String stepTitleStr = stepTitle ?? "";
+    return stepTitleStr.isNotEmpty == true;
+  }
+
+  /// 是否有步骤标题
+  bool _hasStepDesc() {
+    String stepDescStr = stepDesc ?? "";
+    return stepDescStr.isNotEmpty == true;
+  }
+
   /// 步骤标题
   Widget _buildStepTitle() {
+    String stepTitleStr = stepTitle ?? "";
+
     // 步骤标签
     Widget stepLabelWidget;
-    if (hasStepLabel()) {
+    if (_hasStepLabel()) {
       stepLabelWidget = StepLabelWidget(label: stepLabel ?? "");
     } else {
       stepLabelWidget = SizedBox();
@@ -107,7 +161,7 @@ class StepCard extends StatelessWidget {
           // 渐变颜色
           colors: [ColorName.stepTitleColor1, ColorName.stepTitleColor2],
           child: Text(
-            stepTitle,
+            stepTitleStr,
             style: TextStyle(fontSize: 20.sp, fontWeight: FontWeight.w700),
           ),
         ),

+ 2 - 0
lib/resource/string.gen.dart

@@ -198,6 +198,7 @@ class StringName {
   static final String intimacyAnalyseUploadScreenshotSampleDesc = 'intimacy_analyse_upload_screenshot_sample_desc'.tr; // 祝我恢复单身生活 ✌
   static final String intimacyAnalyseUploadScreenshotSamplePublishTime = 'intimacy_analyse_upload_screenshot_sample_publish_time'.tr; // 刚刚
   static final String intimacyAnalyseSampleImage = 'intimacy_analyse_sample_image'.tr; // 示例图
+  static final String intimacyAnalyseLookAnalyse = 'intimacy_analyse_look_analyse'.tr; // 查看分析
   static final String nextStep = 'next_step'.tr; // 下一步
   static final String recently = 'recently'.tr; // 最近
 }
@@ -401,6 +402,7 @@ class StringMultiSource {
       'intimacy_analyse_upload_screenshot_sample_desc': '祝我恢复单身生活 ✌',
       'intimacy_analyse_upload_screenshot_sample_publish_time': '刚刚',
       'intimacy_analyse_sample_image': '示例图',
+      'intimacy_analyse_look_analyse': '查看分析',
       'next_step': '下一步',
       'recently': '最近',
     },