瀏覽代碼

[feat]亲密度分析,实现预测方向,选择项

hezihao 7 月之前
父節點
當前提交
96801303d4

+ 9 - 0
assets/color/business_color.xml

@@ -36,4 +36,13 @@
 
     <!-- Ai模式选中时的背景颜色 -->
     <color name="bg_ai_model_selected">#FFDDCFFD</color>
+
+    <!-- 选项选择,未选中时的背景色 -->
+    <color name="bg_option_select_normal">#FFF6F5FA</color>
+    <!-- 选项选择,已选中时的渐变色 -->
+    <color name="bg_option_select_selected1">#FF7D46FC</color>
+    <color name="bg_option_select_selected2">#FFBC87FF</color>
+
+    <!-- 亲密度分析,添加预测方向 -->
+    <color name="bg_add_prediction_direction">#B2755BAB</color>
 </resources>

二進制
assets/images/icon_add_prediction_direction.webp


+ 16 - 0
lib/data/api/response/intimacy_analyze_config_response.dart

@@ -0,0 +1,16 @@
+import 'package:json_annotation/json_annotation.dart';
+
+import '../../bean/intimacy_analyze_config.dart';
+
+part 'intimacy_analyze_config_response.g.dart';
+
+@JsonSerializable()
+class IntimacyAnalyzeConfigResponse {
+  @JsonKey(name: "config")
+  late final IntimacyAnalyzeConfig config;
+
+  IntimacyAnalyzeConfigResponse({required this.config});
+
+  factory IntimacyAnalyzeConfigResponse.fromJson(Map<String, dynamic> json) =>
+      _$IntimacyAnalyzeConfigResponseFromJson(json);
+}

+ 19 - 0
lib/data/api/response/intimacy_analyze_config_response.g.dart

@@ -0,0 +1,19 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'intimacy_analyze_config_response.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+IntimacyAnalyzeConfigResponse _$IntimacyAnalyzeConfigResponseFromJson(
+  Map<String, dynamic> json,
+) => IntimacyAnalyzeConfigResponse(
+  config: IntimacyAnalyzeConfig.fromJson(
+    json['config'] as Map<String, dynamic>,
+  ),
+);
+
+Map<String, dynamic> _$IntimacyAnalyzeConfigResponseToJson(
+  IntimacyAnalyzeConfigResponse instance,
+) => <String, dynamic>{'config': instance.config};

+ 57 - 0
lib/data/bean/intimacy_analyze_config.dart

@@ -0,0 +1,57 @@
+import 'package:json_annotation/json_annotation.dart';
+
+import 'intimacy_analyze_direction.dart';
+
+part 'intimacy_analyze_config.g.dart';
+
+/// 亲密度配置
+@JsonSerializable()
+class IntimacyAnalyzeConfig {
+  // 默认分析结果,markdown格式
+  @JsonKey(name: 'defaultContent')
+  String? defaultContent;
+
+  // 最大图片上传数
+  @JsonKey(name: 'maxImageCount')
+  int? maxImageCount;
+
+  // 最小图片上传数
+  @JsonKey(name: 'minImageCount')
+  int? minImageCount;
+
+  // 是否可以自定义方向
+  @JsonKey(name: 'custom')
+  bool? custom;
+
+  // 最大自定义字符数
+  @JsonKey(name: 'maxCustomWords')
+  int? maxCustomWords;
+
+  // 最小自定义字符数
+  @JsonKey(name: 'minCustomWords')
+  int? minCustomWords;
+
+  // 预测方向
+  @JsonKey(name: 'direction')
+  List<IntimacyAnalyzeDirection>? direction;
+
+  // 模型选项
+  @JsonKey(name: 'models')
+  List<String>? models;
+
+  IntimacyAnalyzeConfig(
+    this.defaultContent,
+    this.maxImageCount,
+    this.minImageCount,
+    this.custom,
+    this.maxCustomWords,
+    this.minCustomWords,
+    this.direction,
+    this.models,
+  );
+
+  factory IntimacyAnalyzeConfig.fromJson(Map<String, dynamic> json) =>
+      _$IntimacyAnalyzeConfigFromJson(json);
+
+  Map<String, dynamic> toJson() => _$IntimacyAnalyzeConfigToJson(this);
+}

+ 35 - 0
lib/data/bean/intimacy_analyze_config.g.dart

@@ -0,0 +1,35 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'intimacy_analyze_config.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+IntimacyAnalyzeConfig _$IntimacyAnalyzeConfigFromJson(
+  Map<String, dynamic> json,
+) => IntimacyAnalyzeConfig(
+  json['defaultContent'] as String?,
+  (json['maxImageCount'] as num?)?.toInt(),
+  (json['minImageCount'] as num?)?.toInt(),
+  json['custom'] as bool?,
+  (json['maxCustomWords'] as num?)?.toInt(),
+  (json['minCustomWords'] as num?)?.toInt(),
+  (json['direction'] as List<dynamic>?)
+      ?.map((e) => IntimacyAnalyzeDirection.fromJson(e as Map<String, dynamic>))
+      .toList(),
+  (json['models'] as List<dynamic>?)?.map((e) => e as String).toList(),
+);
+
+Map<String, dynamic> _$IntimacyAnalyzeConfigToJson(
+  IntimacyAnalyzeConfig instance,
+) => <String, dynamic>{
+  'defaultContent': instance.defaultContent,
+  'maxImageCount': instance.maxImageCount,
+  'minImageCount': instance.minImageCount,
+  'custom': instance.custom,
+  'maxCustomWords': instance.maxCustomWords,
+  'minCustomWords': instance.minCustomWords,
+  'direction': instance.direction,
+  'models': instance.models,
+};

+ 26 - 0
lib/data/bean/intimacy_analyze_direction.dart

@@ -0,0 +1,26 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'intimacy_analyze_direction.g.dart';
+
+/// 亲密度-预测方向
+@JsonSerializable()
+class IntimacyAnalyzeDirection {
+  // 标题
+  @JsonKey(name: 'title')
+  String? title;
+
+  // icon地址
+  @JsonKey(name: 'iconUrl')
+  String? iconUrl;
+
+  // 模型选项
+  @JsonKey(name: 'options')
+  List<String>? options;
+
+  IntimacyAnalyzeDirection(this.title, this.iconUrl, this.options);
+
+  factory IntimacyAnalyzeDirection.fromJson(Map<String, dynamic> json) =>
+      _$IntimacyAnalyzeDirectionFromJson(json);
+
+  Map<String, dynamic> toJson() => _$IntimacyAnalyzeDirectionToJson(this);
+}

+ 23 - 0
lib/data/bean/intimacy_analyze_direction.g.dart

@@ -0,0 +1,23 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'intimacy_analyze_direction.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+IntimacyAnalyzeDirection _$IntimacyAnalyzeDirectionFromJson(
+  Map<String, dynamic> json,
+) => IntimacyAnalyzeDirection(
+  json['title'] as String?,
+  json['iconUrl'] as String?,
+  (json['options'] as List<dynamic>?)?.map((e) => e as String).toList(),
+);
+
+Map<String, dynamic> _$IntimacyAnalyzeDirectionToJson(
+  IntimacyAnalyzeDirection instance,
+) => <String, dynamic>{
+  'title': instance.title,
+  'iconUrl': instance.iconUrl,
+  'options': instance.options,
+};

+ 28 - 0
lib/data/bean/option_select_config.dart

@@ -0,0 +1,28 @@
+import 'package:json_annotation/json_annotation.dart';
+
+import 'option_select_item.dart';
+
+part 'option_select_config.g.dart';
+
+/// 选项选择实体类
+@JsonSerializable()
+class OptionSelectConfig {
+  // 标题
+  @JsonKey(name: 'title')
+  String title;
+
+  // icon地址
+  @JsonKey(name: 'iconUrl')
+  String iconUrl;
+
+  // 选项列表
+  @JsonKey(name: 'options')
+  List<OptionSelectItem> options;
+
+  OptionSelectConfig(this.title, this.iconUrl, this.options);
+
+  factory OptionSelectConfig.fromJson(Map<String, dynamic> json) =>
+      _$OptionSelectConfigFromJson(json);
+
+  Map<String, dynamic> toJson() => _$OptionSelectConfigToJson(this);
+}

+ 23 - 0
lib/data/bean/option_select_config.g.dart

@@ -0,0 +1,23 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'option_select_config.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+OptionSelectConfig _$OptionSelectConfigFromJson(Map<String, dynamic> json) =>
+    OptionSelectConfig(
+      json['title'] as String,
+      json['iconUrl'] as String,
+      (json['options'] as List<dynamic>)
+          .map((e) => OptionSelectItem.fromJson(e as Map<String, dynamic>))
+          .toList(),
+    );
+
+Map<String, dynamic> _$OptionSelectConfigToJson(OptionSelectConfig instance) =>
+    <String, dynamic>{
+      'title': instance.title,
+      'iconUrl': instance.iconUrl,
+      'options': instance.options,
+    };

+ 22 - 0
lib/data/bean/option_select_item.dart

@@ -0,0 +1,22 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'option_select_item.g.dart';
+
+/// 选项选择实体类
+@JsonSerializable()
+class OptionSelectItem {
+  // 名称
+  @JsonKey(name: 'name')
+  String name;
+
+  // 是否选中
+  @JsonKey(name: 'selected')
+  bool selected;
+
+  OptionSelectItem(this.name, this.selected);
+
+  factory OptionSelectItem.fromJson(Map<String, dynamic> json) =>
+      _$OptionSelectItemFromJson(json);
+
+  Map<String, dynamic> toJson() => _$OptionSelectItemToJson(this);
+}

+ 13 - 0
lib/data/bean/option_select_item.g.dart

@@ -0,0 +1,13 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'option_select_item.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+OptionSelectItem _$OptionSelectItemFromJson(Map<String, dynamic> json) =>
+    OptionSelectItem(json['name'] as String, json['selected'] as bool);
+
+Map<String, dynamic> _$OptionSelectItemToJson(OptionSelectItem instance) =>
+    <String, dynamic>{'name': instance.name, 'selected': instance.selected};

+ 55 - 0
lib/module/intimacy_analyse/intimacy_analyse_upload/intimacy_analyse_upload_controller.dart

@@ -2,6 +2,8 @@ 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 '../../../router/app_page_arguments.dart';
 import '../../../utils/atmob_log.dart';
 
@@ -20,12 +22,45 @@ class IntimacyAnalyseUploadController extends BaseController {
   /// 当前应用的Ai模型
   Rx<String> currentAiModel = 'DeepSeek R1'.obs;
 
+  /// 预测方向的选项列表
+  RxList<OptionSelectConfig> directionOptionSelectConfigList =
+      <OptionSelectConfig>[].obs;
+
   @override
   void onInit() {
     super.onInit();
     _initArgs();
   }
 
+  @override
+  void onReady() {
+    super.onReady();
+    _initDirectionOptionSelectConfigList();
+  }
+
+  void _initDirectionOptionSelectConfigList() {
+    directionOptionSelectConfigList.add(
+      OptionSelectConfig("初相识", "", [
+        OptionSelectItem("缘分指数", false),
+        OptionSelectItem("暧昧进展", false),
+        OptionSelectItem("感情调整", false),
+      ]),
+    );
+    directionOptionSelectConfigList.add(
+      OptionSelectConfig("恋爱", "", [
+        OptionSelectItem("复合几率", false),
+        OptionSelectItem("占有欲", false),
+        OptionSelectItem("相爱相杀", false),
+      ]),
+    );
+    directionOptionSelectConfigList.add(
+      OptionSelectConfig("未来", "", [
+        OptionSelectItem("结婚几率", false),
+        OptionSelectItem("情感未来", false),
+      ]),
+    );
+  }
+
   /// 初始化参数
   void _initArgs() {
     final arguments = Get.arguments as Map<String, dynamic>?;
@@ -51,4 +86,24 @@ class IntimacyAnalyseUploadController extends BaseController {
   void switchAiModel(String newAiModel) {
     currentAiModel.value = newAiModel;
   }
+
+  /// 添加预测方向
+  void addDirection() {}
+
+  /// 预测方向,选中选项
+  void selectDirectionOption(
+    OptionSelectConfig rowConfig,
+    OptionSelectItem optionItem,
+  ) {
+    // 先全部反选
+    rowConfig.options =
+        rowConfig.options.map((ele) {
+          ele.selected = false;
+          return ele;
+        }).toList();
+    // 再勾选当前的选中项
+    optionItem.selected = true;
+    // 由于Rx响应式变量,无法监听对象中嵌套对象的某个属性的变化,导致页面不会刷新,需要手动刷新页面
+    directionOptionSelectConfigList.refresh();
+  }
 }

+ 88 - 20
lib/module/intimacy_analyse/intimacy_analyse_upload/intimacy_analyse_upload_page.dart

@@ -1,17 +1,15 @@
+import 'package:dotted_border/dotted_border.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
 import 'package:get/get.dart';
 import 'package:keyboard/base/base_page.dart';
+import 'package:keyboard/data/bean/option_select_config.dart';
+import 'package:keyboard/data/bean/option_select_item.dart';
 import 'package:keyboard/module/intimacy_analyse/intimacy_analyse_upload/popup/ai_model_select_popup.dart';
-import 'package:keyboard/module/intimacy_analyse/intimacy_analyse_upload/widget/step_label_widget.dart';
-import 'package:keyboard/module/intimacy_analyse/intimacy_analyse_upload/widget/upload_add_widget.dart';
-import 'package:keyboard/module/intimacy_analyse/intimacy_analyse_upload/widget/upload_item_widget.dart';
 import 'package:keyboard/module/intimacy_analyse/intimacy_analyse_upload/widget/upload_nine_grid.dart';
 import 'package:keyboard/resource/colors.gen.dart';
 import 'package:keyboard/resource/string.gen.dart';
-import 'package:sprintf/sprintf.dart';
 import 'package:wechat_assets_picker/wechat_assets_picker.dart';
-
 import '../../../resource/assets.gen.dart';
 import '../../../router/app_page_arguments.dart';
 import '../../../router/app_pages.dart';
@@ -19,6 +17,7 @@ import '../../../utils/string_format_util.dart';
 import '../../../widget/actionbtn/action_btn.dart';
 import '../../../widget/gradient_text.dart';
 import '../widget/intimacy_user_widget.dart';
+import '../widget/option_select_widget.dart';
 import '../widget/step_card.dart';
 import 'intimacy_analyse_upload_controller.dart';
 
@@ -183,7 +182,6 @@ class IntimacyAnalyseUploadPage
       stepDesc: StringName.intimacyAnalysePredictionDirectionCardTip,
       contentWidget: Column(
         children: [
-          // 九宫格
           Container(
             margin: EdgeInsets.only(left: 12.w, right: 12.w),
             padding: EdgeInsets.only(
@@ -196,26 +194,96 @@ class IntimacyAnalyseUploadPage
               color: ColorName.white,
               borderRadius: BorderRadius.circular(16.r),
             ),
-            child: UploadNineGrid(
-              mode: Mode.preview,
-              imageSrcList: [
-                "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png",
-                "",
-                "",
-                "",
-                "",
-                "",
-                "",
+            child: Obx(() {
+              return Column(
+                children: [
+                  // 添加预测方向按钮
+                  _buildAddDirectionBtn(),
+                  SizedBox(height: 22.h),
+                  // 添加选项行
+                  for (var optionConfig
+                      in controller.directionOptionSelectConfigList)
+                    _buildOptionRow(optionConfig),
+                ],
+              );
+            }),
+          ),
+        ],
+      ),
+    );
+  }
+
+  /// 添加预测方向按钮
+  Widget _buildAddDirectionBtn() {
+    return Container(
+      // 左侧对齐
+      alignment: Alignment.centerLeft,
+      child: GestureDetector(
+        onTap: () {
+          controller.addDirection();
+        },
+        child: DottedBorder(
+          // 虚线颜色
+          color: ColorName.bgAddPredictionDirection,
+          // 虚线密集程度
+          dashPattern: [5, 3],
+          // 线条宽度
+          strokeWidth: 1.0.w,
+          // 圆角矩形,要使用 RRect 类型,才能有效
+          borderType: BorderType.RRect,
+          // 圆角半径
+          radius: Radius.circular(31.r),
+          child: Container(
+            padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h),
+            child: Row(
+              // 包裹内容
+              mainAxisSize: MainAxisSize.min,
+              // 文字和图标都居中
+              mainAxisAlignment: MainAxisAlignment.center,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                // 图标
+                Assets.images.iconAddPredictionDirection.image(
+                  width: 18.w,
+                  height: 18.w,
+                ),
+                SizedBox(width: 2.w),
+                // 文字
+                Text(
+                  StringName.intimacyAnalyseAddPredictionDirection,
+                  style: TextStyle(
+                    color: ColorName.uploadAddText,
+                    fontSize: 14.sp,
+                    fontWeight: FontWeight.w400,
+                  ),
+                ),
               ],
-              maxCount: 9,
-              spacing: 8.0,
             ),
           ),
-        ],
+        ),
       ),
     );
   }
 
+  /// 构建一行选择选项行
+  Widget _buildOptionRow(OptionSelectConfig config) {
+    return Column(
+      children: [
+        // 选择项
+        OptionSelectWidget(
+          optionSelect: config,
+          optionSelectCallback: (
+            OptionSelectConfig rowConfig,
+            OptionSelectItem optionItem,
+          ) {
+            controller.selectDirectionOption(rowConfig, optionItem);
+          },
+        ),
+        SizedBox(height: 20.h),
+      ],
+    );
+  }
+
   /// 推荐的亲密关系
   Widget _buildRecommendIntimacy() {
     return Container(
@@ -438,7 +506,7 @@ class IntimacyAnalyseUploadPage
                 _buildUploadStepCard(),
                 // 预测方向卡片
                 _buildPredictionDirectionStepCard(),
-                SizedBox(height: 50.h),
+                SizedBox(height: 80.h),
               ],
             ),
           ),

+ 141 - 0
lib/module/intimacy_analyse/widget/option_select_widget.dart

@@ -0,0 +1,141 @@
+import 'package:cached_network_image/cached_network_image.dart';
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:keyboard/data/bean/option_select_item.dart';
+
+import '../../../data/bean/option_select_config.dart';
+import '../../../resource/colors.gen.dart';
+
+/// 切换选中时回调
+typedef OnOptionSelectCallback =
+    void Function(OptionSelectConfig config, OptionSelectItem optionItem);
+
+/// 选项选择组件
+class OptionSelectWidget extends StatelessWidget {
+  /// 选项行的配置
+  final OptionSelectConfig optionSelect;
+
+  /// 切换选中时回调
+  final OnOptionSelectCallback optionSelectCallback;
+
+  const OptionSelectWidget({
+    super.key,
+    required this.optionSelect,
+    required this.optionSelectCallback,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        // 标题
+        _buildTitle(),
+        SizedBox(height: 8.h),
+        // 选项
+        _buildOptionList(),
+      ],
+    );
+  }
+
+  /// 图标和标题
+  Widget _buildTitle() {
+    String icon = optionSelect.iconUrl;
+    return Row(
+      children: [
+        Visibility(
+          visible: icon.isNotEmpty,
+          child: Row(
+            children: [
+              // 图标
+              CachedNetworkImage(
+                imageUrl: icon,
+                height: 14.h,
+                width: 14.w,
+                fit: BoxFit.fill,
+              ),
+              SizedBox(width: 2),
+            ],
+          ),
+        ),
+        // 标题
+        Text(
+          optionSelect.title,
+          style: TextStyle(
+            fontSize: 12.sp,
+            fontWeight: FontWeight.w500,
+            color: ColorName.black80,
+          ),
+        ),
+      ],
+    );
+  }
+
+  /// 选项列表
+  Widget _buildOptionList() {
+    return Wrap(
+      direction: Axis.horizontal,
+      alignment: WrapAlignment.start,
+      // 主轴间距
+      spacing: 9.0,
+      // 交叉轴间距
+      runSpacing: 7.0,
+      children: [
+        for (var option in optionSelect.options)
+          _buildOptionItem(optionSelect, option),
+      ],
+    );
+  }
+
+  /// 选项
+  /// [rowConfig] 选项行的配置
+  /// [optionItem] 当前构建的那一项
+  Widget _buildOptionItem(
+    OptionSelectConfig rowConfig,
+    OptionSelectItem optionItem,
+  ) {
+    // 背景圆角
+    double bgBorderRadius = 31.r;
+
+    // 背景,选中时为渐变色,未选中时为灰色
+    BoxDecoration bgDecoration;
+    if (optionItem.selected) {
+      bgDecoration = BoxDecoration(
+        gradient: LinearGradient(
+          colors: [
+            ColorName.bgOptionSelectSelected1,
+            ColorName.bgOptionSelectSelected2,
+          ],
+          begin: Alignment.centerLeft,
+          end: Alignment.centerRight,
+        ),
+        borderRadius: BorderRadius.circular(bgBorderRadius),
+      );
+    } else {
+      bgDecoration = BoxDecoration(
+        color: ColorName.bgOptionSelectNormal,
+        borderRadius: BorderRadius.circular(bgBorderRadius),
+      );
+    }
+
+    return GestureDetector(
+      onTap: () {
+        optionSelectCallback(rowConfig, optionItem);
+      },
+      child: Container(
+        padding: EdgeInsets.symmetric(horizontal: 18.w, vertical: 8.h),
+        decoration: bgDecoration,
+        child: Text(
+          optionItem.name,
+          style: TextStyle(
+            fontSize: 13.sp,
+            fontWeight: FontWeight.w400,
+            // 文字颜色,选中时为白色,未选中时为黑色
+            color: optionItem.selected ? ColorName.white : ColorName.black80,
+          ),
+        ),
+      ),
+    );
+  }
+}

+ 5 - 0
lib/resource/assets.gen.dart

@@ -215,6 +215,10 @@ class $AssetsImagesGen {
   AssetGenImage get iconAboutArrowLeft =>
       const AssetGenImage('assets/images/icon_about_arrow_left.webp');
 
+  /// File path: assets/images/icon_add_prediction_direction.webp
+  AssetGenImage get iconAddPredictionDirection =>
+      const AssetGenImage('assets/images/icon_add_prediction_direction.webp');
+
   /// File path: assets/images/icon_alipay_payment.webp
   AssetGenImage get iconAlipayPayment =>
       const AssetGenImage('assets/images/icon_alipay_payment.webp');
@@ -831,6 +835,7 @@ class $AssetsImagesGen {
     bgTicketDialogPrices2,
     gifDiscountUnlockButton,
     iconAboutArrowLeft,
+    iconAddPredictionDirection,
     iconAlipayPayment,
     iconAlipayScanPayment,
     iconArrowRight,

+ 12 - 0
lib/resource/colors.gen.dart

@@ -22,6 +22,9 @@ class ColorName {
   /// Color: #FFF5F6F8
   static const Color bgColorPrimary = Color(0xFFF5F6F8);
 
+  /// Color: #B2755BAB
+  static const Color bgAddPredictionDirection = Color(0xB2755BAB);
+
   /// Color: #FFDDCFFD
   static const Color bgAiModelSelected = Color(0xFFDDCFFD);
 
@@ -34,6 +37,15 @@ class ColorName {
   /// Color: #FFEBF0FF
   static const Color bgIntimacyRelationColor2 = Color(0xFFEBF0FF);
 
+  /// Color: #FFF6F5FA
+  static const Color bgOptionSelectNormal = Color(0xFFF6F5FA);
+
+  /// Color: #FF7D46FC
+  static const Color bgOptionSelectSelected1 = Color(0xFF7D46FC);
+
+  /// Color: #FFBC87FF
+  static const Color bgOptionSelectSelected2 = Color(0xFFBC87FF);
+
   /// Color: #FF7B7DFF
   static const Color bgStep = Color(0xFF7B7DFF);