Parcourir la source

Merge branch 'v1.0.0' of http://git.atmob.com:28999/Atmob-Flutter/AiKeyboard2025 into v1.0.0

hezihao il y a 7 mois
Parent
commit
2e3f288a65
53 fichiers modifiés avec 1548 ajouts et 471 suppressions
  1. BIN
      assets/images/bg_agreement_again_dialog.webp
  2. BIN
      assets/images/bg_agreement_dialog.webp
  3. BIN
      assets/images/bg_heart_fill.png
  4. BIN
      assets/images/bg_new_discount_item_select.webp
  5. BIN
      assets/images/bg_new_discount_item_unselect.webp
  6. BIN
      assets/images/bg_splash.webp
  7. BIN
      assets/images/icon_new_discount_item_select.webp
  8. BIN
      assets/images/icon_new_discount_membership_card_1.webp
  9. BIN
      assets/images/icon_new_discount_membership_card_2.webp
  10. BIN
      assets/images/icon_new_discount_membership_card_3.webp
  11. BIN
      assets/images/icon_new_discount_membership_card_4.webp
  12. BIN
      assets/images/icon_new_discount_membership_card_5.webp
  13. BIN
      assets/images/icon_new_discount_membership_card_title.webp
  14. BIN
      assets/images/icon_system_keyboard.webp
  15. 18 2
      assets/string/base/string.xml
  16. 3 0
      lib/data/api/response/user_info_response.dart
  17. 18 15
      lib/data/api/response/user_info_response.g.dart
  18. 36 0
      lib/data/bean/intimacy_config_info.dart
  19. 32 0
      lib/data/bean/intimacy_config_info.g.dart
  20. 13 2
      lib/data/consts/constants.dart
  21. 5 0
      lib/data/consts/web_url.dart
  22. 1 1
      lib/data/repository/account_repository.dart
  23. 11 4
      lib/data/repository/config_repository.dart
  24. 4 3
      lib/data/repository/keyboard_repository.dart
  25. 53 1
      lib/data/repository/store_repository.dart
  26. 11 1
      lib/di/get_it.config.dart
  27. 205 0
      lib/dialog/agreement_again_dialog.dart
  28. 210 0
      lib/dialog/agreement_dialog.dart
  29. 23 9
      lib/dialog/custom_character/custom_character_another_add_dialog.dart
  30. 1 1
      lib/main.dart
  31. 6 2
      lib/module/keyboard_manage/keyboard_manage_controller.dart
  32. 22 13
      lib/module/main/main_controller.dart
  33. 2 1
      lib/module/new_user/new_user_controller.dart
  34. 2 8
      lib/module/new_user/step/intimacy/step_intimacy_stages_logic.dart
  35. 79 50
      lib/module/new_user/step/intimacy/step_intimacy_stages_view.dart
  36. 27 25
      lib/module/profile/profile_page.dart
  37. 71 0
      lib/module/splash/splash_controller.dart
  38. 25 0
      lib/module/splash/splash_page.dart
  39. 18 0
      lib/module/store/new_discount/member_card_bean.dart
  40. 100 12
      lib/module/store/new_discount/new_discount_controller.dart
  41. 352 276
      lib/module/store/new_discount/new_discount_page.dart
  42. 20 0
      lib/module/store/store_controller.dart
  43. 3 0
      lib/module/store/store_page.dart
  44. 6 1
      lib/module/store/suprise/goods_surprise_controller.dart
  45. 4 1
      lib/module/store/suprise/surprise_dialog.dart
  46. 4 1
      lib/module/store/ticket/discount_ticket_dialog.dart
  47. 1 1
      lib/module/user_info/user_info_page.dart
  48. 11 2
      lib/module/user_profile/user_profile_controller.dart
  49. 76 0
      lib/resource/assets.gen.dart
  50. 36 0
      lib/resource/string.gen.dart
  51. 2 1
      lib/router/app_pages.dart
  52. 36 37
      lib/utils/intimacy_util.dart
  53. 1 1
      lib/utils/privacy_compliance.dart

BIN
assets/images/bg_agreement_again_dialog.webp


BIN
assets/images/bg_agreement_dialog.webp


BIN
assets/images/bg_heart_fill.png


BIN
assets/images/bg_new_discount_item_select.webp


BIN
assets/images/bg_new_discount_item_unselect.webp


BIN
assets/images/bg_splash.webp


BIN
assets/images/icon_new_discount_item_select.webp


BIN
assets/images/icon_new_discount_membership_card_1.webp


BIN
assets/images/icon_new_discount_membership_card_2.webp


BIN
assets/images/icon_new_discount_membership_card_3.webp


BIN
assets/images/icon_new_discount_membership_card_4.webp


BIN
assets/images/icon_new_discount_membership_card_5.webp


BIN
assets/images/icon_new_discount_membership_card_title.webp


BIN
assets/images/icon_system_keyboard.webp


+ 18 - 2
assets/string/base/string.xml

@@ -169,6 +169,7 @@
     <string name="text_span_and">和</string>
     <string name="text_span_privacy_policy">《隐私政策》</string>
     <string name="text_span_service_terms">《服务条款》</string>
+    <string name="text_span_user_agreement">《用户协议》</string>
 
 
     <string name="member_continue_pay">继续支付</string>
@@ -392,6 +393,21 @@
     <string name="select_birthday_dialog_confirm">确定</string>
     <string name="new_user_result_intimacy_title">亲密度:</string>
     <string name="new_user_result_intimacy_desc">根据当前的亲密度,建议选择以下人设</string>
-
-
+    <string name="confirm_add">确认添加</string>
+    <string name="new_discount_member_card_desc">开通可畅享多种会员权益</string>
+    <string name="new_discount_member_card1_title">亲密度分析</string>
+    <string name="new_discount_member_card1_desc">探索人格/情感特质</string>
+    <string name="new_discount_member_card2_title">星座分析</string>
+    <string name="new_discount_member_card2_desc">指引你的星座缘分</string>
+    <string name="new_discount_member_card3_title">追爱自动回复</string>
+    <string name="new_discount_member_card3_desc">智能生成不踩雷</string>
+    <string name="new_discount_member_card4_title">Crush心情解析</string>
+    <string name="new_discount_member_card4_desc">分析真实想法</string>
+    <string name="new_discount_member_card5_title">N种精品人设</string>
+    <string name="new_discount_member_card5_desc">为你量身打造</string>
+    <string name="new_discount_unlock_now">立即解锁体验</string>
+    <string name="privacy_title">隐私政策及权限说明</string>
+    <string name="privacy_disagree">不同意</string>
+    <string name="privacy_disagree_and_exit">不同意并退出</string>
+    <string name="privacy_agree">同意</string>
 </resources>

+ 3 - 0
lib/data/api/response/user_info_response.dart

@@ -45,6 +45,9 @@ class UserInfoResponse {
   @JsonKey(name: 'name')
   String? name;
 
+  @JsonKey(name: 'account')
+  String? account;
+
   UserInfoResponse(this.name,
     this.userId,
     this.ssid,

+ 18 - 15
lib/data/api/response/user_info_response.g.dart

@@ -8,21 +8,23 @@ part of 'user_info_response.dart';
 
 UserInfoResponse _$UserInfoResponseFromJson(Map<String, dynamic> json) =>
     UserInfoResponse(
-      json['name'] as String?,
-      json['userId'] as String?,
-      json['ssid'] as String?,
-      json['deviceId'] as String?,
-      json['phone'] as String?,
-      (json['loginStatus'] as num?)?.toInt(),
-      json['channelName'] as String?,
-      (json['gender'] as num?)?.toInt(),
-      json['birthday'] as String?,
-      (json['intimacy'] as num?)?.toInt(),
-      json['userIdOrSsid'] as String?,
-      json['memberInfo'] == null
-          ? null
-          : MemberInfo.fromJson(json['memberInfo'] as Map<String, dynamic>),
-    )..imageUrl = json['imageUrl'] as String?;
+        json['name'] as String?,
+        json['userId'] as String?,
+        json['ssid'] as String?,
+        json['deviceId'] as String?,
+        json['phone'] as String?,
+        (json['loginStatus'] as num?)?.toInt(),
+        json['channelName'] as String?,
+        (json['gender'] as num?)?.toInt(),
+        json['birthday'] as String?,
+        (json['intimacy'] as num?)?.toInt(),
+        json['userIdOrSsid'] as String?,
+        json['memberInfo'] == null
+            ? null
+            : MemberInfo.fromJson(json['memberInfo'] as Map<String, dynamic>),
+      )
+      ..imageUrl = json['imageUrl'] as String?
+      ..account = json['account'] as String?;
 
 Map<String, dynamic> _$UserInfoResponseToJson(UserInfoResponse instance) =>
     <String, dynamic>{
@@ -39,4 +41,5 @@ Map<String, dynamic> _$UserInfoResponseToJson(UserInfoResponse instance) =>
       'imageUrl': instance.imageUrl,
       'memberInfo': instance.memberInfo,
       'name': instance.name,
+      'account': instance.account,
     };

+ 36 - 0
lib/data/bean/intimacy_config_info.dart

@@ -0,0 +1,36 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'intimacy_config_info.g.dart';
+
+@JsonSerializable()
+class IntimacyConfigInfo {
+  //亲密度列表
+  @JsonKey(name: 'intimacy')
+  List<IntimacyBean>? intimacy;
+
+  IntimacyConfigInfo(this.intimacy);
+  factory IntimacyConfigInfo.fromJson(Map<String, dynamic> json) =>
+      _$IntimacyConfigInfoFromJson(json);
+  Map<String, dynamic> toJson() => _$IntimacyConfigInfoToJson(this);
+}
+
+@JsonSerializable()
+class IntimacyBean {
+  @JsonKey(name: 'max')
+  final int? max;
+  @JsonKey(name: 'min')
+  final int? min;
+  @JsonKey(name: 'name')
+  final String? name;
+  @JsonKey(name: 'iconUrl')
+  final String? iconUrl;
+
+  IntimacyBean(this.max, this.min, this.name, this.iconUrl);
+
+
+  factory IntimacyBean.fromJson(Map<String, dynamic> json) =>
+      _$IntimacyBeanFromJson(json);
+
+  Map<String, dynamic> toJson() => _$IntimacyBeanToJson(this);
+}
+

+ 32 - 0
lib/data/bean/intimacy_config_info.g.dart

@@ -0,0 +1,32 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'intimacy_config_info.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+IntimacyConfigInfo _$IntimacyConfigInfoFromJson(Map<String, dynamic> json) =>
+    IntimacyConfigInfo(
+      (json['intimacy'] as List<dynamic>?)
+          ?.map((e) => IntimacyBean.fromJson(e as Map<String, dynamic>))
+          .toList(),
+    );
+
+Map<String, dynamic> _$IntimacyConfigInfoToJson(IntimacyConfigInfo instance) =>
+    <String, dynamic>{'intimacy': instance.intimacy};
+
+IntimacyBean _$IntimacyBeanFromJson(Map<String, dynamic> json) => IntimacyBean(
+  (json['max'] as num?)?.toInt(),
+  (json['min'] as num?)?.toInt(),
+  json['name'] as String?,
+  json['iconUrl'] as String?,
+);
+
+Map<String, dynamic> _$IntimacyBeanToJson(IntimacyBean instance) =>
+    <String, dynamic>{
+      'max': instance.max,
+      'min': instance.min,
+      'name': instance.name,
+      'iconUrl': instance.iconUrl,
+    };

+ 13 - 2
lib/data/consts/constants.dart

@@ -1,5 +1,7 @@
 
 
+import '../../utils/mmkv_util.dart';
+
 class Constants {
   Constants._();
 
@@ -18,9 +20,7 @@ class Constants {
   static const String _prodBaseUrl = "https://project-api.atmob.com";
 
 
-  static final String _keyIsLogin = 'keyIsLogin';
 
-  static final String _keyIsMember = 'keyIsMember';
 
   static String baseUrl = getBaseUrl();
 
@@ -41,6 +41,10 @@ class Constants {
   static const String keyIsLogin = 'keyIsLogin';
   static const String keyIsMember = 'keyIsMember';
 
+  // 首次进入应用
+  static const String isFirstIntro = 'isFirstIntro';
+
+
 }
 
 String getBaseUrl() {
@@ -56,6 +60,13 @@ String getBaseUrl() {
   }
 }
 
+bool isFirstIntro() {
+  return KVUtil.getBool(Constants.isFirstIntro, true);
+}
+
+void setFirstIntro(bool isFirst) {
+  KVUtil.putBool(Constants.isFirstIntro, isFirst);
+}
 
 
 

+ 5 - 0
lib/data/consts/web_url.dart

@@ -9,6 +9,9 @@ class WebUrl {
   static const String _kidPolicy =
       "https://doc.v8dashen.com/doc/298eb75d38dc2c4a";
 
+  static const String _userAgreement =
+      "https://doc.v8dashen.com/doc/546b8b5175a1b4db";
+
   static const String _qiyuService ="https://qiyu-kefu.atmob.com";
 
 
@@ -18,5 +21,7 @@ class WebUrl {
 
   static String get serviceAgreement => _serviceAgreement;
 
+  static String get userAgreement => _userAgreement;
+
   static String get qiyuService => _qiyuService;
 }

+ 1 - 1
lib/data/repository/account_repository.dart

@@ -216,7 +216,7 @@ class AccountRepository {
     KVUtil.putBool(Constants.keyIsMember, false);
     loginPhoneNum.value = null;
     isLogin.value = false;
-    // keyboardRepository.cleanData();
+    keyboardRepository.cleanData();
   }
 
   // 意见反馈

+ 11 - 4
lib/data/repository/config_repository.dart

@@ -6,6 +6,7 @@ import '../../di/get_it.dart';
 import '../../utils/async_util.dart';
 import '../../utils/atmob_log.dart';
 import '../../utils/http_handler.dart';
+import '../../utils/intimacy_util.dart';
 import '../api/atmob_api.dart';
 import '../api/request/config_request.dart';
 import '../api/response/config_response.dart';
@@ -14,6 +15,7 @@ import 'package:get/get.dart';
 
 import '../bean/custom_config_info.dart';
 import '../bean/default_avatar_info.dart';
+import '../bean/intimacy_config_info.dart';
 
 @lazySingleton
 class ConfigRepository {
@@ -29,6 +31,8 @@ class ConfigRepository {
   // 人物和键盘的头像
   final Rxn<DefaultAvatarInfo> defaultAvatarInfo = Rxn<DefaultAvatarInfo>();
 
+  final Rxn<IntimacyConfigInfo> intimacyConfigInfo = Rxn<IntimacyConfigInfo>();
+
   ConfigRepository(this.atmobApi) {
     AtmobLog.d(tag, '$tag....init');
     refreshConfig();
@@ -49,7 +53,12 @@ class ConfigRepository {
       if (list.isNotEmpty) {
         for (var config in list) {
           if (config.confCode == 'intimacy') {
-            AtmobLog.d(tag, '获取亲密度配置: ${config.value}');
+            intimacyConfigInfo.value = IntimacyConfigInfo.fromJson(
+              config.value,
+            );
+            AtmobLog.d(tag, '获取亲密度配置: ${intimacyConfigInfo.value?.toJson()}');
+
+            IntimacyUtil.setConfig(intimacyConfigInfo.value);
           } else if (config.confCode == 'default_avatar') {
             defaultAvatarInfo.value = DefaultAvatarInfo.fromJson(config.value);
             AtmobLog.d(tag, '获取默认头像配置: ${defaultAvatarInfo.value?.toJson()}');
@@ -82,7 +91,5 @@ class ConfigRepository {
         .then(HttpHandler.handle(true));
   }
 
-  static ConfigRepository getInstance() =>
-      getIt.get<ConfigRepository>();
-
+  static ConfigRepository getInstance() => getIt.get<ConfigRepository>();
 }

+ 4 - 3
lib/data/repository/keyboard_repository.dart

@@ -99,7 +99,8 @@ class KeyboardRepository {
 
   Future cleanData() async {
     _keyboardInfoList.clear();
-
+    _customKeyboardInfoList.clear();
+    _chooseKeyboardInfo.value = null;
     getKeyboardHomeInfo();
     getKeyboardLoveIndex();
   }
@@ -151,7 +152,7 @@ class KeyboardRepository {
             characterIds: characterIds,
           ),
         )
-        .then(HttpHandler.handle(false));
+        .then(HttpHandler.handle(true));
   }
 
   Future<void> keyboardCharacterStart({
@@ -165,7 +166,7 @@ class KeyboardRepository {
             characterIds: characterIds,
           ),
         )
-        .then(HttpHandler.handle(false));
+        .then(HttpHandler.handle(true));
   }
 
   // 更新键盘信息

+ 53 - 1
lib/data/repository/store_repository.dart

@@ -6,13 +6,17 @@ import 'package:keyboard/utils/http_handler.dart';
 import 'package:get/get.dart';
 import '../../base/app_base_request.dart';
 import '../../utils/async_util.dart';
+import '../../utils/atmob_log.dart';
+import '../../utils/error_handler.dart';
 import '../../utils/payment_status_manager.dart';
 import '../api/request/order_pay_request.dart';
 import '../api/request/order_status_request.dart';
 import '../api/response/item_retention_response.dart';
 import '../api/response/member_new_user_response.dart';
+import '../bean/character_info.dart';
 import '../bean/goods_info.dart';
 import '../bean/pay_way_info.dart';
+import '../consts/error_code.dart';
 import 'account_repository.dart';
 
 @lazySingleton
@@ -22,8 +26,41 @@ class StoreRepository {
   final AtmobApi atmobApi;
   final AccountRepository accountRepository;
 
+  CancelableFuture? goodsInfoFuture;
+
+  final RxList<GoodsInfo> _newDiscountGoodsInfoList = <GoodsInfo>[].obs;
+
+  RxList<GoodsInfo> get newDiscountGoodsInfoList => _newDiscountGoodsInfoList;
+
+  final RxList<PayWayInfo> _newDiscountPayWayList = <PayWayInfo>[].obs;
+
+  RxList<PayWayInfo> get newDiscountPayWayList => _newDiscountPayWayList;
+
+  final RxList<CharacterInfo> _charactersList = <CharacterInfo>[].obs;
+
+  RxList<CharacterInfo> get charactersList => _charactersList;
+
   StoreRepository(this.atmobApi, this.accountRepository) {
     print('$tag....init');
+    refreshNewDiscountGoodsInfoList();
+  }
+
+  void refreshNewDiscountGoodsInfoList() {
+    goodsInfoFuture?.cancel();
+    goodsInfoFuture = AsyncUtil.retryWithExponentialBackoff(
+      () => getMemberNewUserGoodsList(),
+      4,
+      predicate: (error) {
+        if (error is ServerErrorException) {
+          return error.code != ErrorCode.noLoginError;
+        }
+        return true;
+      },
+    );
+    goodsInfoFuture?.catchError((error) {
+      ErrorHandler.toastError(error);
+    });
+
   }
 
   Future<ItemListResponse> getGoodsInfoList() async {
@@ -35,7 +72,22 @@ class StoreRepository {
   Future<MemberNewUserResponse> getMemberNewUserGoodsList() async {
     return await atmobApi
         .getMemberUserResponse(AppBaseRequest())
-        .then(HttpHandler.handle(true));
+        .then(HttpHandler.handle(true))
+        .then((data) {
+          _newDiscountGoodsInfoList.clear();
+          _newDiscountPayWayList.clear();
+          _charactersList.clear();
+          if (data.goodsInfoList?.isNotEmpty == true) {
+            _newDiscountGoodsInfoList.addAll(data.goodsInfoList!);
+          }
+          if (data.payInfoList?.isNotEmpty == true) {
+            _newDiscountPayWayList.addAll(data.payInfoList!);
+          }
+          if (data.characterInfos?.isNotEmpty == true) {
+            _charactersList.addAll(data.characterInfos!);
+          }
+          return data;
+        });
   }
 
   Future<OrderPayResponse> submitAndRequestPay({

+ 11 - 1
lib/di/get_it.config.dart

@@ -73,6 +73,7 @@ import '../module/new_user/new_user_controller.dart' as _i701;
 import '../module/new_user/result/new_user_result_controller.dart' as _i576;
 import '../module/profile/edit/profile_edit_controller.dart' as _i344;
 import '../module/profile/profile_controller.dart' as _i244;
+import '../module/splash/splash_controller.dart' as _i973;
 import '../module/store/discount/discount_controller.dart' as _i333;
 import '../module/store/new_discount/new_discount_controller.dart' as _i326;
 import '../module/store/store_controller.dart' as _i344;
@@ -116,11 +117,11 @@ extension GetItInjectableX on _i174.GetIt {
     gh.factory<_i248.KeyboardGuidePageController>(
       () => _i248.KeyboardGuidePageController(),
     );
-    gh.factory<_i731.MainController>(() => _i731.MainController());
     gh.factory<_i333.DiscountController>(() => _i333.DiscountController());
     gh.factory<_i415.KeyboardMethodHandler>(
       () => _i415.KeyboardMethodHandler(),
     );
+    gh.factory<_i973.SplashController>(() => _i973.SplashController());
     gh.lazySingleton<_i495.WechatLoginService>(
       () => _i495.WechatLoginService(),
     );
@@ -379,6 +380,15 @@ extension GetItInjectableX on _i174.GetIt {
         gh<_i779.PaymentStatusManager>(),
       ),
     );
+    gh.factory<_i731.MainController>(
+      () => _i731.MainController(
+        gh<_i83.AccountRepository>(),
+        gh<_i274.KeyboardRepository>(),
+        gh<_i50.ConfigRepository>(),
+        gh<_i987.StoreRepository>(),
+        gh<_i421.CharactersRepository>(),
+      ),
+    );
     return this;
   }
 }

+ 205 - 0
lib/dialog/agreement_again_dialog.dart

@@ -0,0 +1,205 @@
+import 'package:flutter/gestures.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:get/get.dart';
+import 'package:keyboard/utils/common_expand.dart';
+
+import '../data/consts/web_url.dart';
+import '../module/browser/browser_page.dart';
+import '../resource/assets.gen.dart';
+import '../resource/colors.gen.dart';
+import '../resource/string.gen.dart';
+import '../utils/styles.dart';
+import '../widget/click_text_span.dart';
+
+class AgreementAgainDialog {
+  static final _tag = "AgreementAgainDialog";
+
+  static void show({
+    required VoidCallback cancelClick,
+    required VoidCallback sureClick,
+  }) {
+    SmartDialog.show(
+      tag: _tag,
+      backType: SmartBackType.block,
+      builder: (_) {
+        return _AgreementAgainDialog(cancelClick, sureClick);
+      },
+      alignment: Alignment.center,
+      clickMaskDismiss: true,
+    );
+  }
+
+  static void dismiss() {
+    SmartDialog.dismiss(tag: _tag);
+  }
+}
+
+class _AgreementAgainDialog extends Dialog {
+  final VoidCallback cancelClick;
+  final VoidCallback sureClick;
+
+  const _AgreementAgainDialog(this.cancelClick, this.sureClick);
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: 300.w,
+      decoration: BoxDecoration(
+        color: Colors.white,
+        borderRadius: BorderRadius.circular(20.w),
+      ),
+      child: Container(
+        width: 300.w,
+        decoration: BoxDecoration(
+          image: DecorationImage(
+            image: Assets.images.bgAgreementAgainDialog.provider(),
+            fit: BoxFit.contain,
+            alignment: Alignment.topCenter,
+          ),
+        ),
+        child: Column(
+          mainAxisSize: MainAxisSize.min,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            SizedBox(height: 29.55.w),
+            Text(
+              StringName.privacyTitle,
+              textAlign: TextAlign.center,
+              style: TextStyle(
+                color: const Color(0xFF202020),
+                fontSize: 16.sp,
+                fontWeight: FontWeight.w700,
+              ),
+            ),
+            SizedBox(height: 30.05.w),
+            SizedBox(
+              width: 240.w,
+              child: Opacity(
+                opacity: 0.80,
+                child: Text.rich(
+                  TextSpan(
+                    children: [
+                      TextSpan(
+                        text: '需要同意',
+                        style: TextStyle(
+                          color: Colors.black.withAlpha(204),
+                          fontSize: 14.sp,
+                          fontWeight: FontWeight.w400,
+                          height: 1.43,
+                        ),
+                      ),
+                      TextSpan(
+                        text: '《隐私政策》',
+                        style: TextStyle(
+                          color: const Color(0xFF374BFF),
+                          fontSize: 14.sp,
+                          fontWeight: FontWeight.w500,
+                          height: 1.43,
+                        ),
+                        recognizer:
+                            TapGestureRecognizer()
+                              ..onTap = () {
+                                BrowserPage.start(WebUrl.privacyPolicy);
+                              },
+                      ),
+                      TextSpan(
+                        text: '和',
+                        style: TextStyle(
+                          color: Colors.black.withAlpha(204),
+                          fontSize: 14.sp,
+                          fontWeight: FontWeight.w400,
+                          height: 1.43,
+                        ),
+                      ),
+                      TextSpan(
+                        text: '《用户协议》',
+                        recognizer:
+                            TapGestureRecognizer()
+                              ..onTap = () {
+                                BrowserPage.start(WebUrl.serviceAgreement);
+                              },
+                        style: TextStyle(
+                          color: const Color(0xFF374BFF),
+                          fontSize: 14.sp,
+                          fontWeight: FontWeight.w500,
+                          height: 1.43,
+                        ),
+                      ),
+                      TextSpan(
+                        text: '才能继续为您提供服务,如您选择不同意很遗憾我们难以继续为您继续服务。',
+                        style: TextStyle(
+                          color: Colors.black.withAlpha(204),
+                          fontSize: 14.sp,
+                          fontWeight: FontWeight.w400,
+                          height: 1.43,
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+              ),
+            ),
+            SizedBox(height: 30.w),
+            Container(
+              margin: EdgeInsets.only(left: 25.w, right: 25.w),
+              child: Row(
+                children: [
+                  Expanded(
+                    child: sureText(StringName.privacyAgree, () {
+                      sureClick();
+                    }),
+                  ),
+                ],
+              ),
+            ),
+            SizedBox(height: 18.w),
+            cancelText(StringName.privacyDisagreeAndExit, () => cancel()),
+            SizedBox(height: 30.w),
+          ],
+        ),
+      ),
+    );
+  }
+
+  void cancel() {
+    cancelClick();
+  }
+
+  Widget cancelText(String txt, VoidCallback onTap) {
+    return GestureDetector(
+      onTap: onTap,
+      child: Center(
+        child: Text(
+          txt,
+          style: TextStyle(
+            fontSize: 16.sp,
+            color: Colors.black.withAlpha(102),
+            fontWeight: FontWeight.w500,
+          ),
+        ),
+      ),
+    );
+  }
+
+  Widget sureText(String txt, VoidCallback onTap) {
+    return GestureDetector(
+      onTap: onTap,
+      child: Container(
+        decoration: Styles.getActivateButtonDecoration(50.r),
+        height: 40.w,
+        child: Center(
+          child: Text(
+            txt,
+            style: TextStyle(
+              fontSize: 16.sp,
+              color: Colors.white,
+              fontWeight: FontWeight.w500,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}

+ 210 - 0
lib/dialog/agreement_dialog.dart

@@ -0,0 +1,210 @@
+import 'package:flutter/gestures.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
+import 'package:get/get.dart';
+import 'package:keyboard/utils/common_expand.dart';
+
+import '../data/consts/web_url.dart';
+import '../module/browser/browser_page.dart';
+import '../resource/assets.gen.dart';
+import '../resource/colors.gen.dart';
+import '../resource/string.gen.dart';
+import '../utils/styles.dart';
+import '../widget/click_text_span.dart';
+
+class AgreementDialog {
+  static final _tag = "AgreementDialog";
+
+  static void show({
+    required VoidCallback cancelClick,
+    required VoidCallback sureClick,
+  }) {
+    SmartDialog.show(
+      tag: _tag,
+      backType: SmartBackType.block,
+      builder: (_) {
+        return _AgreementDialog(cancelClick, sureClick);
+      },
+      alignment: Alignment.center,
+      clickMaskDismiss: true,
+    );
+  }
+
+  static void dismiss() {
+    SmartDialog.dismiss(tag: _tag);
+  }
+}
+
+class _AgreementDialog extends Dialog {
+  final VoidCallback cancelClick;
+  final VoidCallback sureClick;
+
+  _AgreementDialog(this.cancelClick, this.sureClick);
+
+  @override
+  Widget build(BuildContext context) {
+    return Container(
+      width: 300.w,
+      decoration: BoxDecoration(
+        color: Colors.white,
+        borderRadius: BorderRadius.circular(20.w),
+      ),
+      child: Container(
+        width: 300.w,
+        decoration: BoxDecoration(
+          image: DecorationImage(
+            image: Assets.images.bgAgreementDialog.provider(),
+            fit: BoxFit.contain,
+            alignment: Alignment.topCenter,
+          ),
+        ),
+        child: Column(
+          mainAxisSize: MainAxisSize.min,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: [
+            SizedBox(height: 114.w),
+            SizedBox(
+              width: 241.w,
+              child: Opacity(
+                opacity: 0.80,
+                child: Text.rich(
+                  textAlign: TextAlign.start,
+                  TextSpan(
+                    children: [
+                      TextSpan(
+                        text:
+                            '亲爱的用户,为您提供更好的服务,我们需要您同意我们的用户协议和隐私政策。这些文件包含了关于您如何使用我们的服务、我们如何处理您的个人信息以及您的权利和责任的重要信息。请花些时间仔细阅读它们 ',
+                        style: TextStyle(
+                          color: Colors.black.withAlpha(204),
+                          fontSize: 14,
+                          fontWeight: FontWeight.w400,
+                          height: 1.43,
+                        ),
+                      ),
+                      TextSpan(
+                        text: '隐私政策 ',
+                        style: TextStyle(
+                          color: const Color(0xFF374BFF),
+                          fontSize: 14,
+                          fontWeight: FontWeight.w500,
+                          decoration: TextDecoration.underline,
+                          decorationColor: const Color(0xFF374BFF),
+                          height: 1.43,
+                        ),
+                        recognizer:
+                            TapGestureRecognizer()
+                              ..onTap = () {
+                                BrowserPage.start(WebUrl.privacyPolicy);
+                              },
+                      ),
+                      TextSpan(
+                        text: '和 ',
+                        style: TextStyle(
+                          color: Colors.black.withAlpha(204),
+                          fontSize: 14,
+                          fontWeight: FontWeight.w400,
+                          height: 1.43,
+                        ),
+                      ),
+
+                      TextSpan(
+                        text: '用户协议 ',
+                        style: TextStyle(
+                          color: const Color(0xFF374BFF),
+                          fontSize: 14,
+                          fontWeight: FontWeight.w500,
+                          decoration: TextDecoration.underline,
+                          decorationColor: const Color(0xFF374BFF),
+                          height: 1.43,
+                        ),
+                        recognizer:
+                            TapGestureRecognizer()
+                              ..onTap = () {
+                                BrowserPage.start(WebUrl.serviceAgreement);
+                              },
+                      ),
+                      TextSpan(
+                        text: '全文,如您同意,请点击点击下方的“同意”按钮。',
+                        style: TextStyle(
+                          color: Colors.black.withAlpha(204),
+                          fontSize: 14,
+                          fontWeight: FontWeight.w400,
+                          height: 1.43,
+                        ),
+                      ),
+                    ],
+                  ),
+                ),
+              ),
+            ),
+            SizedBox(height: 30.w),
+            Row(
+              mainAxisAlignment: MainAxisAlignment.center,
+              children: [
+                cancelText(StringName.privacyDisagree, () => cancel()),
+
+                SizedBox(width: 16.w),
+                sureText(StringName.privacyAgree, () {
+                  sureClick();
+                }),
+              ],
+            ),
+            SizedBox(height: 30.w),
+          ],
+        ),
+      ),
+    );
+  }
+
+  void cancel() {
+    cancelClick();
+  }
+
+  Widget cancelText(String txt, VoidCallback onTap) {
+    return GestureDetector(
+      onTap: onTap,
+      child: Container(
+        decoration: ShapeDecoration(
+          color: const Color(0xFFF5F4F9),
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(50.r),
+          ),
+        ),
+        width: 128.w,
+        height: 40.w,
+        child: Center(
+          child: Text(
+            txt,
+            style: TextStyle(
+              fontSize: 16.sp,
+              color: Colors.black.withAlpha(102),
+              fontWeight: FontWeight.w500,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+
+  Widget sureText(String txt, VoidCallback onTap) {
+    return GestureDetector(
+      onTap: onTap,
+      child: Container(
+        decoration: Styles.getActivateButtonDecoration(50.r),
+        width: 128.w,
+        height: 40.w,
+        child: Center(
+          child: Text(
+            txt,
+            style: TextStyle(
+              fontSize: 16.sp,
+              color: Colors.white,
+              fontWeight: FontWeight.w500,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+}

+ 23 - 9
lib/dialog/custom_character/custom_character_another_add_dialog.dart

@@ -135,7 +135,7 @@ class CustomCharacterAnotherAddDialog {
                               31.r,
                             ),
                             child: Text(
-                              StringName.profileSave,
+                              StringName.confirmAdd,
                               style: Styles.getTextStyleWhiteW500(16.sp),
                             ),
                           ),
@@ -183,7 +183,13 @@ class CustomCharacterAnotherAddDialog {
               _buildAvatar(imageUrl: keyboardInfo.imageUrl),
               SizedBox(width: 8.w),
               _buildKeyboardInfo(keyboardInfo),
-              selectedIndex.value == index?Assets.images.iconCustomCharacterAddDialogSelect.image(width: 26.w,height: 26.w,fit: BoxFit.contain):SizedBox()
+              selectedIndex.value == index
+                  ? Assets.images.iconCustomCharacterAddDialogSelect.image(
+                    width: 26.w,
+                    height: 26.w,
+                    fit: BoxFit.contain,
+                  )
+                  : SizedBox(),
             ],
           ),
         );
@@ -197,19 +203,27 @@ class CustomCharacterAnotherAddDialog {
       width: 60.r,
       height: 60.r,
       decoration: BoxDecoration(
-        borderRadius: BorderRadius.circular(8),
+        borderRadius: BorderRadius.circular(8.r),
         gradient: LinearGradient(
           begin: Alignment.topCenter,
           end: Alignment.bottomCenter,
           colors: [Color(0xffebe6ff), Color(0xffffe6fe)],
         ),
       ),
-      child: CachedNetworkImage(
-        imageUrl: imageUrl ?? "",
-        width: 60.r,
-        height: 60.r,
-        fit: BoxFit.cover,
-
+      child: ClipRRect(
+        borderRadius: BorderRadius.circular(8.r), // 可调整圆角大小
+        child: CachedNetworkImage(
+          imageUrl: imageUrl ?? "",
+          width: 60.r,
+          height: 60.r,
+          fit: BoxFit.contain,
+          errorWidget:
+              (_, __, ___) => Assets.images.iconSystemKeyboard.image(
+                width: 60.r,
+                height: 60.r,
+                fit: BoxFit.contain,
+              ),
+        ),
       ),
     );
   }

+ 1 - 1
lib/main.dart

@@ -143,7 +143,7 @@ class AppCommonConfig {
 
   // 路由配置
   static List<GetPage>? getPages = AppPage.pages;
-  static const initialRoute = RoutePath.mainTab;
+  static const initialRoute = RoutePath.splash;
 
   // 初始化绑定
   static Bindings initialBinding = AppBinding();

+ 6 - 2
lib/module/keyboard_manage/keyboard_manage_controller.dart

@@ -64,7 +64,7 @@ class KeyboardManageController extends BaseController
       _customKeyboardCharacterListChanged.value;
 
   // 存储排序前的定制人设列表,用于比较是否有变化
-  late List<CharacterInfo> _oldCustomCharacterList;
+   List<CharacterInfo> _oldCustomCharacterList = [];
 
   // 通用键盘列表
   final RxList<KeyboardInfo> _generalKeyboardInfoList = RxList();
@@ -334,7 +334,11 @@ class KeyboardManageController extends BaseController
     } else {
       _currentCustomIntimacy.value =
           _currentCustomKeyboardInfo.value.intimacy ?? 0;
-      _currentCustomKeyboardCharacterList.value = _oldCustomCharacterList;
+
+      if(_oldCustomCharacterList.isNotEmpty){
+        _currentCustomKeyboardCharacterList.value = _oldCustomCharacterList;
+      }
+
       _customIntimacyChanged.value = false;
       _customKeyboardCharacterListChanged.value = false;
       getGeneralKeyboard();

+ 22 - 13
lib/module/main/main_controller.dart

@@ -2,6 +2,11 @@ import 'package:flutter/cupertino.dart';
 import 'package:flutter/services.dart';
 import 'package:get/get.dart';
 import 'package:injectable/injectable.dart';
+import 'package:keyboard/data/repository/account_repository.dart';
+import 'package:keyboard/data/repository/characters_repository.dart';
+import 'package:keyboard/data/repository/config_repository.dart';
+import 'package:keyboard/data/repository/keyboard_repository.dart';
+import 'package:keyboard/data/repository/store_repository.dart';
 
 import '../../base/base_controller.dart';
 import '../../resource/assets.gen.dart';
@@ -17,6 +22,20 @@ class MainController extends BaseController {
 
   int get currentIndex => _currentIndex.value;
 
+  final AccountRepository accountRepository;
+  final KeyboardRepository keyboardRepository;
+  final ConfigRepository configRepository;
+  final StoreRepository storeRepository;
+  final CharactersRepository charactersRepository;
+
+  MainController(
+    this.accountRepository,
+    this.keyboardRepository,
+    this.configRepository,
+    this.storeRepository,
+    this.charactersRepository,
+  );
+
   final List<TabBean> tabBeans = [
     TabBean(
       StringName.mainTabKeyboard,
@@ -25,10 +44,7 @@ class MainController extends BaseController {
       AnimatedSwitcher(
         duration: Duration(milliseconds: 300),
         transitionBuilder: (Widget child, Animation<double> animation) {
-          return FadeTransition(
-            opacity: animation,
-            child: child,
-          );
+          return FadeTransition(opacity: animation, child: child);
         },
         child: KeyBoardView(),
       ),
@@ -42,13 +58,9 @@ class MainController extends BaseController {
         duration: Duration(milliseconds: 300),
 
         transitionBuilder: (Widget child, Animation<double> animation) {
-          return FadeTransition(
-            opacity: animation,
-            child: child,
-          );
+          return FadeTransition(opacity: animation, child: child);
         },
         child: CharacterView(),
-
       ),
     ),
     TabBean(
@@ -59,10 +71,7 @@ class MainController extends BaseController {
       AnimatedSwitcher(
         duration: Duration(milliseconds: 300),
         transitionBuilder: (Widget child, Animation<double> animation) {
-          return FadeTransition(
-            opacity: animation,
-            child: child,
-          );
+          return FadeTransition(opacity: animation, child: child);
         },
 
         child: MineView(),

+ 2 - 1
lib/module/new_user/new_user_controller.dart

@@ -15,6 +15,7 @@ import 'package:intl/intl.dart';
 import '../../base/base_controller.dart';
 import '../../data/api/response/keyboard_generate_response.dart';
 import '../../data/bean/default_avatar_info.dart';
+import '../../data/consts/constants.dart';
 import '../../data/repository/account_repository.dart';
 import 'package:get/get.dart';
 
@@ -63,7 +64,7 @@ class NewUserController extends BaseController
   @override
   void onInit() {
     super.onInit();
-
+    setFirstIntro(false);
     updateAvatarListsAndSelectFirst(currentDefaultAvatarInfo.value);
 
     ever<DefaultAvatarInfo?>(currentDefaultAvatarInfo, (info) {

+ 2 - 8
lib/module/new_user/step/intimacy/step_intimacy_stages_logic.dart

@@ -1,6 +1,7 @@
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 
+import '../../../../data/bean/intimacy_config_info.dart';
 import '../../../../utils/intimacy_util.dart';
 
 mixin StepIntimacyStagesLogic {
@@ -10,15 +11,8 @@ mixin StepIntimacyStagesLogic {
 
   int get currentIntimacyMedian => IntimacyUtil.getMedianByIndex(selectedIndex.value);
 
+  List<IntimacyBean>? get intimacyList => IntimacyUtil.intimacyList();
 
-  final List<String> stages = [
-    '初相识',
-    '追爱期ing',
-    '暧昧期ing',
-    '热恋期',
-    '伴侣',
-    '灵魂伴侣',
-  ];
   void selectIndex(int index) {
     selectedIndex.value = index;
   }

+ 79 - 50
lib/module/new_user/step/intimacy/step_intimacy_stages_view.dart

@@ -1,3 +1,4 @@
+import 'package:cached_network_image/cached_network_image.dart';
 import 'package:keyboard/base/base_page.dart';
 import 'package:keyboard/module/new_user/new_user_controller.dart';
 import 'package:flutter/material.dart';
@@ -51,11 +52,31 @@ class StepIntimacyStagesView extends BasePage<NewUserController> {
           Row(
             mainAxisAlignment: MainAxisAlignment.spaceBetween,
             children: [
-              Assets.images.iconNewUserStagesAmbiguous.image(
+              CachedNetworkImage(
+                imageUrl:
+                    controller
+                        .intimacyList?[controller.selectedIndex.value]
+                        .iconUrl ??
+                    "",
                 width: 211.w,
                 height: 339.w,
                 fit: BoxFit.contain,
+                placeholder:
+                    (context, url) =>
+                        Assets.images.iconNewUserStagesAmbiguous.image(
+                          width: 211.w,
+                          height: 339.w,
+                          fit: BoxFit.contain,
+                        ),
+                errorWidget:
+                    (_, __, ___) =>
+                        Assets.images.iconNewUserStagesAmbiguous.image(
+                          width: 211.w,
+                          height: 339.w,
+                          fit: BoxFit.contain,
+                        ),
               ),
+
               _buildStagesList(),
             ],
           ),
@@ -70,59 +91,67 @@ class StepIntimacyStagesView extends BasePage<NewUserController> {
       child: Obx(() {
         return Column(
           mainAxisSize: MainAxisSize.min,
-          children: List.generate(controller.stages.length, (index) {
-            final isSelected = controller.selectedIndex.value == index;
-            return GestureDetector(
-              onTap: () => controller.selectIndex(index),
-              child: Container(
-                height: 64.h,
-                width: 120.w,
-                alignment: Alignment.center,
-                child: AnimatedScale(
-                  scale: isSelected ? 1.0 : 0.82,
-                  duration: const Duration(milliseconds: 250),
-                  curve: Curves.easeOutCubic,
-                  child: Container(
-                    alignment: Alignment.center,
-                    decoration: BoxDecoration(
-                      color: isSelected ? null : Colors.white,
-                      gradient: isSelected
-                          ? LinearGradient(
-                        begin: Alignment(0.04, 0.21),
-                        end: Alignment(0.98, 0.76),
-                        colors: [
-                          const Color(0xFF7D46FC),
-                          const Color(0xFFBC87FF),
-                        ],
-                      )
-                          : null,
-                      boxShadow: isSelected
-                          ? [
-                        BoxShadow(
-                          color: const Color(0xFFCEBEFF),
-                          blurRadius: 5.80,
-                          offset: Offset(0, 4),
+          children:
+              (controller.intimacyList == null ||
+                      controller.intimacyList!.isEmpty)
+                  ? [SizedBox.shrink()]
+                  : List.generate(controller.intimacyList!.length, (index) {
+                    final isSelected = controller.selectedIndex.value == index;
+                    return GestureDetector(
+                      onTap: () => controller.selectIndex(index),
+                      child: Container(
+                        height: 64.h,
+                        width: 120.w,
+                        alignment: Alignment.center,
+                        child: AnimatedScale(
+                          scale: isSelected ? 1.0 : 0.82,
+                          duration: const Duration(milliseconds: 250),
+                          curve: Curves.easeOutCubic,
+                          child: Container(
+                            alignment: Alignment.center,
+                            decoration: BoxDecoration(
+                              color: isSelected ? null : Colors.white,
+                              gradient:
+                                  isSelected
+                                      ? LinearGradient(
+                                        begin: Alignment(0.04, 0.21),
+                                        end: Alignment(0.98, 0.76),
+                                        colors: [
+                                          const Color(0xFF7D46FC),
+                                          const Color(0xFFBC87FF),
+                                        ],
+                                      )
+                                      : null,
+                              boxShadow:
+                                  isSelected
+                                      ? [
+                                        BoxShadow(
+                                          color: const Color(0xFFCEBEFF),
+                                          blurRadius: 5.80,
+                                          offset: Offset(0, 4),
+                                        ),
+                                      ]
+                                      : [],
+                              borderRadius: BorderRadius.circular(17.r),
+                            ),
+                            child: Text(
+                              controller.intimacyList?[index].name ?? "",
+                              style: TextStyle(
+                                color:
+                                    isSelected
+                                        ? Colors.white
+                                        : Colors.black.withAlpha(153),
+                                fontSize: 17.14.sp,
+                                fontWeight: FontWeight.w500,
+                              ),
+                            ),
+                          ),
                         ),
-                      ]
-                          : [],
-                      borderRadius: BorderRadius.circular(17.r),
-                    ),
-                    child: Text(
-                      controller.stages[index],
-                      style: TextStyle(
-                        color: isSelected ? Colors.white : Colors.black.withAlpha(153),
-                        fontSize: 17.14.sp,
-                        fontWeight: FontWeight.w500,
                       ),
-                    ),
-                  ),
-                ),
-              ),
-            );
-          }),
+                    );
+                  }),
         );
       }),
     );
   }
-
 }

+ 27 - 25
lib/module/profile/profile_page.dart

@@ -115,9 +115,11 @@ class ProfilePage extends BasePage<ProfileController> {
       child: Column(
         children: [
           SizedBox(height: 45.h),
-          Container(
-            width: 47.w,
-            height: 19.h,
+          Row(
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: [Container(
+            padding: EdgeInsets.only(left: 8.w,right: 8.w),
+
             decoration: ShapeDecoration(
               color: Colors.white,
               shape: RoundedRectangleBorder(
@@ -126,28 +128,28 @@ class ProfilePage extends BasePage<ProfileController> {
               ),
             ),
             child:
-                (intimacy != null)
-                    ? Center(
-                      child: Text(
-                        IntimacyUtil.getIntimacyName(intimacy),
-                        style: TextStyle(
-                          color: const Color(0xFFFF73E0),
-                          fontSize: 11.sp,
-                          fontWeight: FontWeight.w500,
-                        ),
-                      ),
-                    )
-                    : Center(
-                      child: Text(
-                        "?",
-                        style: TextStyle(
-                          color: const Color(0xFFFF73E0),
-                          fontSize: 11.sp,
-                          fontWeight: FontWeight.w500,
-                        ),
-                      ),
-                    ),
-          ),
+            (intimacy != null)
+                ? Center(
+              child: Text(
+                IntimacyUtil.getIntimacyName(intimacy),
+                style: TextStyle(
+                  color: const Color(0xFFFF73E0),
+                  fontSize: 11.sp,
+                  fontWeight: FontWeight.w500,
+                ),
+              ),
+            )
+                : Center(
+              child: Text(
+                "?",
+                style: TextStyle(
+                  color: const Color(0xFFFF73E0),
+                  fontSize: 11.sp,
+                  fontWeight: FontWeight.w500,
+                ),
+              ),
+            ),
+          ),],)
         ],
       ),
     );

+ 71 - 0
lib/module/splash/splash_controller.dart

@@ -0,0 +1,71 @@
+import 'dart:async';
+import 'dart:io';
+
+import 'package:flutter/services.dart';
+import 'package:get/get_utils/src/platform/platform.dart';
+import 'package:injectable/injectable.dart';
+import 'package:keyboard/module/new_user/new_user_page.dart';
+
+import '../../base/base_controller.dart';
+import '../../data/consts/constants.dart';
+import '../../dialog/agreement_again_dialog.dart';
+import '../../dialog/agreement_dialog.dart';
+import '../../utils/privacy_compliance.dart';
+import '../main/main_page.dart';
+
+@injectable
+class SplashController extends BaseController {
+  final splashDelayedTime = 2;
+
+
+
+  @override
+  void onReady() {
+    final isAgreePrivacy = PrivacyCompliance.isAgreePrivacyPolicy();
+    if (isAgreePrivacy) {
+      isAgreePrivacyNextStep();
+    } else {
+      AgreementDialog.show(cancelClick: () {
+        AgreementAgainDialog.show(
+            cancelClick: () {
+              exitApp();
+            },
+            sureClick: () {
+              _agreePrivacy();
+              isAgreePrivacyNextStep();
+            });
+      }, sureClick: () {
+        _agreePrivacy();
+        isAgreePrivacyNextStep();
+      });
+    }
+  }
+
+  void isAgreePrivacyNextStep() {
+    _goMain(Duration(seconds: splashDelayedTime));
+  }
+
+
+  void _goMain(Duration delayTime, {Map<String, dynamic>? arguments}) {
+    Timer(delayTime, () {
+      if (isFirstIntro()) {
+        NewUserPage.start();
+      }else{
+        MainPage.start(arguments: arguments);
+      }
+    });
+  }
+
+  void exitApp() {
+    if (GetPlatform.isAndroid) {
+      SystemNavigator.pop();
+    } else {
+      exit(0);
+    }
+  }
+
+  void _agreePrivacy() async {
+
+    PrivacyCompliance.setPrivacyPolicy(true);
+  }
+}

+ 25 - 0
lib/module/splash/splash_page.dart

@@ -0,0 +1,25 @@
+import 'package:flutter/cupertino.dart';
+import 'package:get/get.dart';
+import 'package:keyboard/base/base_page.dart';
+import 'package:keyboard/module/splash/splash_controller.dart';
+
+import '../../resource/assets.gen.dart';
+
+class SplashPage extends BasePage<SplashController> {
+   SplashPage({super.key});
+
+  @override
+  final SplashController controller = Get.put(SplashController());
+   @override
+   bool immersive() {
+     return true;
+   }
+  @override
+  Widget buildBody(BuildContext context) {
+    return Assets.images.bgSplash.image(
+      width: double.infinity,
+      height: double.infinity,
+      fit: BoxFit.fill,
+    );
+  }
+}

+ 18 - 0
lib/module/store/new_discount/member_card_bean.dart

@@ -0,0 +1,18 @@
+
+import 'package:flutter/material.dart';
+
+import '../../../resource/assets.gen.dart';
+
+class MemberCardBean {
+  final AssetGenImage imageUrl;
+  final String title;
+  final String desc;
+  final Gradient gradient;
+
+  MemberCardBean({
+    required this.imageUrl,
+    required this.title,
+    required this.desc,
+    required this.gradient,
+  });
+}

+ 100 - 12
lib/module/store/new_discount/new_discount_controller.dart

@@ -6,6 +6,7 @@ import 'package:injectable/injectable.dart';
 import 'package:keyboard/base/base_controller.dart';
 import 'package:get/get.dart';
 import 'package:keyboard/data/bean/character_info.dart';
+import 'package:keyboard/module/store/new_discount/member_card_bean.dart';
 import '../../../data/api/response/user_info_response.dart';
 import '../../../data/bean/goods_info.dart';
 import '../../../data/bean/member_info.dart';
@@ -44,7 +45,9 @@ class NewDiscountController extends BaseController
 
   final PaymentStatusManager paymentStatusManager;
 
-  final RxList<GoodsInfo> goodsInfoList = <GoodsInfo>[].obs;
+  RxList<GoodsInfo> get goodsInfoList => storeRepository.newDiscountGoodsInfoList;
+
+  RxList<PayWayInfo> get payWayList => storeRepository.newDiscountPayWayList;
 
   final Rxn<GoodsInfo> _selectedGoodsInfoItem = Rxn<GoodsInfo>();
 
@@ -54,7 +57,6 @@ class NewDiscountController extends BaseController
 
   PayWayInfo? get selectedPayWay => _selectedPayWay.value;
 
-  final RxList<PayWayInfo> payWayList = <PayWayInfo>[].obs;
 
   CancelableFuture? _storeDataFuture;
 
@@ -68,7 +70,8 @@ class NewDiscountController extends BaseController
 
   final RxList<GoodsInfo> filteredGoodsList = <GoodsInfo>[].obs;
 
-  final RxList<CharacterInfo> _charactersList = <CharacterInfo>[].obs;
+  RxList<CharacterInfo> get _charactersList => storeRepository.charactersList;
+
   List<CharacterInfo> get charactersList => _charactersList;
 
 
@@ -89,6 +92,59 @@ class NewDiscountController extends BaseController
     Assets.images.iconNewDiscountBanner3,
   ];
 
+  final List<MemberCardBean> memberCardList = [
+    MemberCardBean(
+      imageUrl: Assets.images.iconNewDiscountMembershipCard1,
+      title: StringName.newDiscountMemberCard1Title,
+      desc: StringName.newDiscountMemberCard1Desc,
+      gradient: LinearGradient(
+        begin: Alignment(0.50, -0.00),
+        end: Alignment(0.50, 1.00),
+        colors: [const Color(0xFFF1EDFF), const Color(0xFFFAF8FF)],
+      ),
+    ),
+    MemberCardBean(
+      imageUrl: Assets.images.iconNewDiscountMembershipCard2,
+      title: StringName.newDiscountMemberCard2Title,
+      desc: StringName.newDiscountMemberCard2Desc,
+      gradient: LinearGradient(
+        begin: Alignment(0.50, -0.00),
+        end: Alignment(0.50, 1.00),
+        colors: [const Color(0xFFDCF4C0), const Color(0xFFFAFFF3)],
+      ),
+    ),
+    MemberCardBean(
+      imageUrl: Assets.images.iconNewDiscountMembershipCard3,
+      title: StringName.newDiscountMemberCard3Title,
+      desc: StringName.newDiscountMemberCard3Desc,
+      gradient: LinearGradient(
+        begin: Alignment(0.50, -0.00),
+        end: Alignment(0.50, 1.00),
+        colors: [const Color(0xFFF9DBFF), const Color(0xFFFFFBFE)],
+      ),
+    ),
+    MemberCardBean(
+      imageUrl: Assets.images.iconNewDiscountMembershipCard4,
+      title: StringName.newDiscountMemberCard4Title,
+      desc: StringName.newDiscountMemberCard4Desc,
+      gradient: LinearGradient(
+        begin: Alignment(0.50, -0.00),
+        end: Alignment(0.50, 1.00),
+        colors: [const Color(0xFFDBECFF), const Color(0xFFFBFBFF)],
+      ),
+    ),
+    MemberCardBean(
+      imageUrl: Assets.images.iconNewDiscountMembershipCard5,
+      title: StringName.newDiscountMemberCard5Title,
+      desc: StringName.newDiscountMemberCard5Desc,
+      gradient: LinearGradient(
+        begin: Alignment(0.50, -0.00),
+        end: Alignment(0.50, 1.00),
+        colors: [const Color(0xFFFFF7DB), const Color(0xFFFFFDFB)],
+      ),
+    ),
+  ];
+
   NewDiscountController(
     this.storeRepository,
     this.accountRepository,
@@ -100,14 +156,16 @@ class NewDiscountController extends BaseController
   }
 
   void refreshStoreData() {
-    _storeDataFuture?.cancel();
-    _storeDataFuture = AsyncUtil.retryWithExponentialBackoff(
-      () => _requestGoodsInfoList(),
-      4,
-    );
-    _storeDataFuture?.catchError((error) {
-      ErrorHandler.toastError(error);
-    });
+    // _storeDataFuture?.cancel();
+    // _storeDataFuture = AsyncUtil.retryWithExponentialBackoff(
+    //   () => _requestGoodsInfoList(),
+    //   4,
+    // );
+    // _storeDataFuture?.catchError((error) {
+    //   ErrorHandler.toastError(error);
+    // });
+
+    storeRepository.refreshNewDiscountGoodsInfoList();
   }
 
   Future<void> _requestGoodsInfoList() async {
@@ -421,9 +479,39 @@ class NewDiscountController extends BaseController
   @override
   void onReady() {
     super.onReady();
-    refreshStoreData();
+    // refreshStoreData();
+  }
+
+  @override
+  void onInit() {
+    super.onInit();
+
+
+    if (goodsInfoList.isNotEmpty) {
+      _selectedGoodsInfoItem.value = goodsInfoList.first;
+    }
+
+    if (payWayList.isNotEmpty) {
+      _selectedPayWay.value = payWayList.first;
+      updateFilteredGoodsList();
+    }
+    
+    ever<List<GoodsInfo>>(goodsInfoList, (list) {
+      if (list.isNotEmpty) {
+        _selectedGoodsInfoItem.value = list.first;
+      }
+    });
+
+
+    ever<List<PayWayInfo>>(payWayList, (list) {
+      if (list.isNotEmpty) {
+        _selectedPayWay.value = list.first;
+        updateFilteredGoodsList();
+      }
+    });
   }
 
+
   @override
   void onClose() {
     super.onClose();

+ 352 - 276
lib/module/store/new_discount/new_discount_page.dart

@@ -50,15 +50,20 @@ class NewDiscountPage extends BasePage<NewDiscountController> {
             ),
             width: 360.w,
             height: 392.w,
-
             child: SingleChildScrollView(
-              child: Expanded(
-                child: Column(
-                  children: [
-                    _buildGoodsCard(),
-                    SizedBox(height: 200.w),
-                  ],
-                ),
+              child: Column(
+                children: [
+                  SizedBox(height: 16.w),
+                  _buildGoodsCard(),
+                  SizedBox(height: 12.w),
+                  _buildPayWayCard(),
+                  SizedBox(height: 8.w),
+                  _buildSelectedDesc(),
+                  SizedBox(height: 30.w),
+                  _buildMemberCard(),
+
+                  SizedBox(height: 200.w),
+                ],
               ),
             ),
           ),
@@ -269,98 +274,42 @@ class NewDiscountPage extends BasePage<NewDiscountController> {
             onTap: controller.clickPayNow,
             child: Container(
               width: 328.w,
-              height: 54.h,
+              height: 56.w,
               decoration: ShapeDecoration(
-                gradient: LinearGradient(
-                  begin: Alignment(0.60, -0.39),
-                  end: Alignment(0.60, 0.95),
-                  colors: [
-                    const Color(0xFFF95FAC),
-                    const Color(0xFFFD5E4D),
-                    const Color(0xFFFD5E4D),
-                    const Color(0xFFFB8A3C),
-                  ],
-                ),
                 shape: RoundedRectangleBorder(
-                  borderRadius: BorderRadius.circular(30.55.r),
+                  side: BorderSide(width: 2.w, color: const Color(0xFFFFF6C9)),
+                  borderRadius: BorderRadius.circular(30.55),
                 ),
               ),
-              child: Center(
-                child: Text(
-                  StringName.storePayNow,
-                  style: Styles.getTextStyleWhiteW500(17.sp),
+              child: Container(
+                width: 328,
+                height: 54,
+                decoration: ShapeDecoration(
+                  gradient: LinearGradient(
+                    begin: Alignment(0.60, -0.39),
+                    end: Alignment(0.60, 0.95),
+                    colors: [
+                      const Color(0xFFF95FAC),
+                      const Color(0xFFFD4D99),
+                      const Color(0xFFFF3E75),
+                      const Color(0xFFFF0F53),
+                    ],
+                  ),
+                  shape: RoundedRectangleBorder(
+                    borderRadius: BorderRadius.circular(30.55),
+                  ),
+                ),
+                child: Center(
+                  child: Text(
+                    StringName.newDiscountUnlockNow,
+                    style: Styles.getTextStyleWhiteW500(17.sp),
+                  ),
                 ),
               ),
             ),
           ),
           SizedBox(height: 11.h),
-          Row(
-            mainAxisAlignment: MainAxisAlignment.center,
-            children: [
-              Obx(() {
-                return GestureDetector(
-                  behavior: HitTestBehavior.opaque,
-                  onTap: () {
-                    controller.isAgree.value = !controller.isAgree.value;
-                  },
-                  child:
-                      controller.isAgree.value
-                          ? Assets.images.iconStoreAgreePrivacy.image(
-                            width: 16.w,
-                            height: 16.w,
-                          )
-                          : SizedBox(
-                            child: Container(
-                              padding: EdgeInsets.all(1.w),
-                              width: 16.w,
-                              height: 16.w,
-                              child: Container(
-                                decoration: BoxDecoration(
-                                  shape: BoxShape.circle,
-                                  border: Border.all(
-                                    color: Colors.black.withAlpha(153),
-                                    width: 1.w,
-                                  ),
-                                ),
-                              ),
-                            ),
-                          ),
-                );
-              }),
-              Text.rich(
-                TextSpan(
-                  children: [
-                    TextSpan(
-                      text: StringName.textSpanIHaveReadAndAgree,
-                      style: TextStyle(
-                        color: Colors.black.withAlpha(153),
-                        fontSize: 10.sp,
-                        fontWeight: FontWeight.w400,
-                      ),
-                    ),
-                    ClickTextSpan(
-                      text: StringName.textSpanPrivacyPolicy,
-                      url: WebUrl.privacyPolicy,
-                    ),
-
-                    TextSpan(
-                      text: StringName.textSpanAnd,
-                      style: TextStyle(
-                        color: Colors.black.withAlpha(153),
-                        fontSize: 10.sp,
-                        fontWeight: FontWeight.w400,
-                      ),
-                    ),
-
-                    ClickTextSpan(
-                      text: StringName.textSpanServiceTerms,
-                      url: WebUrl.serviceAgreement,
-                    ),
-                  ],
-                ),
-              ),
-            ],
-          ),
+          _buildPrivacyTextSpan(),
         ],
       ),
     );
@@ -369,42 +318,30 @@ class NewDiscountPage extends BasePage<NewDiscountController> {
   Widget _buildGoodsCard() {
     return Container(
       margin: EdgeInsets.symmetric(horizontal: 16.w),
-      padding: EdgeInsets.only(
-        top: 16.w,
-        left: 16.w,
-        right: 16.w,
-        bottom: 24.w,
-      ),
-      decoration: BoxDecoration(
-        color: Colors.white,
-        borderRadius: BorderRadius.only(
-          topLeft: Radius.circular(16.r),
-          topRight: Radius.circular(16.r),
-        ),
-      ),
+
       child: Column(
         crossAxisAlignment: CrossAxisAlignment.start,
         mainAxisAlignment: MainAxisAlignment.start,
         children: [
-
-          SizedBox(height: 16.h),
           Obx(() {
+            final goodsList = controller.filteredGoodsList;
             return Column(
-              children:
-                  controller.filteredGoodsList.map((item) {
-                    return Obx(() {
-                      return GestureDetector(
-                        onTap: () => controller.onGoodsItemClick(item),
-                        child: _buildGoodsItem(
-                          item,
-                          controller.selectedGoodsInfoItem?.id == item.id,
-                        ),
-                      );
-                    });
-                  }).toList(),
+              children: List.generate(goodsList.length, (index) {
+                final item = goodsList[index];
+                final isSelected =
+                    controller.selectedGoodsInfoItem?.id == item.id;
+                return Column(
+                  children: [
+                    GestureDetector(
+                      onTap: () => controller.onGoodsItemClick(item),
+                      child: _buildGoodsItem(item, isSelected),
+                    ),
+                    if (index != goodsList.length - 1) SizedBox(height: 10.w),
+                  ],
+                );
+              }),
             );
           }),
-          _buildPayWayCard(),
         ],
       ),
     );
@@ -414,6 +351,7 @@ class NewDiscountPage extends BasePage<NewDiscountController> {
     return GestureDetector(
       onTap: () => controller.clickPayWaySwitch(),
       child: Container(
+        margin: EdgeInsets.symmetric(horizontal: 16.w),
         height: 36.h,
         padding: EdgeInsets.symmetric(horizontal: 10.w),
         decoration: ShapeDecoration(
@@ -465,170 +403,308 @@ class NewDiscountPage extends BasePage<NewDiscountController> {
 
   Widget _buildGoodsItem(item, bool isSelected) {
     return Container(
-      margin: EdgeInsets.only(bottom: 8.h),
-
+      height: 70.w,
+      width: 328.w,
+      padding: EdgeInsets.symmetric(horizontal: 16.w),
+      decoration:
+          isSelected
+              ? BoxDecoration(
+                borderRadius: BorderRadius.circular(16.w),
+                image: DecorationImage(
+                  image: Assets.images.bgNewDiscountItemSelect.provider(),
+                  fit: BoxFit.fill,
+                ),
+              )
+              : BoxDecoration(
+                borderRadius: BorderRadius.circular(16.w),
+                image: DecorationImage(
+                  image: Assets.images.bgNewDiscountItemUnselect.provider(),
+                  fit: BoxFit.fill,
+                ),
+              ),
+      child: Row(
+        children: [
+          Text(
+            "¥",
+            style: TextStyle(
+              color:
+                  isSelected
+                      ? const Color(0xFFFF684E)
+                      : Colors.black.withAlpha(204),
+              fontSize: 16.sp,
+              fontWeight: FontWeight.w700,
+            ),
+          ),
+          Text(
+            '${item.amountText}',
+            textAlign: TextAlign.center,
+            style: TextStyle(
+              color:
+                  isSelected
+                      ? const Color(0xFFFF684E)
+                      : Colors.black.withAlpha(204),
+              fontSize: 29.sp,
+              fontWeight: FontWeight.w700,
+            ),
+          ),
+          SizedBox(width: 9.w),
+          Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: [
+              Row(
+                children: [
+                  Text(
+                    item.name,
+                    style: TextStyle(
+                      color: Colors.black.withAlpha(204),
+                      fontSize: 14.sp,
+                      fontWeight: FontWeight.w500,
+                    ),
+                  ),
 
-      decoration: ShapeDecoration(
-        color: Colors.white,
-        shape: RoundedRectangleBorder(
-          side: BorderSide(
-            width: 2.w,
-            color: Colors.black.withAlpha( 26),
+                  SizedBox(width: 4.5.w),
+                  if (item.mostDesc?.isNotEmpty == true)
+                    Container(
+                      padding: EdgeInsets.symmetric(
+                        horizontal: 4.w,
+                        vertical: 2.w,
+                      ),
+                      margin: EdgeInsets.only(bottom: 4.w),
+                      decoration: ShapeDecoration(
+                        gradient: LinearGradient(
+                          begin: Alignment(0.00, 0.50),
+                          end: Alignment(1.00, 0.50),
+                          colors: [
+                            const Color(0xFFFF684E),
+                            const Color(0xFFFF4F9A),
+                          ],
+                        ),
+                        shape: RoundedRectangleBorder(
+                          borderRadius: BorderRadius.only(
+                            topLeft: Radius.circular(10.50),
+                            topRight: Radius.circular(10.50),
+                            bottomRight: Radius.circular(10.50),
+                          ),
+                        ),
+                      ),
+                      child: Text(
+                        item.mostDesc!,
+                        style: TextStyle(
+                          color: Colors.white,
+                          fontSize: 12.sp,
+                          fontWeight: FontWeight.w500,
+                        ),
+                      ),
+                    ),
+                ],
+              ),
+              Text(
+                item.priceDesc,
+                style: TextStyle(
+                  color: Colors.black.withAlpha(153),
+                  fontSize: 12.sp,
+                  fontWeight: FontWeight.w400,
+                ),
+              ),
+            ],
           ),
-          borderRadius: BorderRadius.circular(16),
-        ),
+          Spacer(),
+          isSelected
+              ? Assets.images.iconCustomCharacterAddDialogSelect.image(
+                width: 20.w,
+                height: 20.w,
+                fit: BoxFit.contain,
+              )
+              : Container(
+                width: 20.w,
+                height: 20.w,
+                decoration: ShapeDecoration(
+                  color: Colors.white,
+                  shape: OvalBorder(
+                    side: BorderSide(
+                      width: 2.w,
+                      color: const Color(0xFFE6E6E6),
+                    ),
+                  ),
+                ),
+              ),
+        ],
       ),
-      child: Row(
+    );
+  }
+
+  _buildSelectedDesc() {
+    return Obx(() {
+      return Container(
+        margin: EdgeInsets.symmetric(horizontal: 16.w),
+        child: Row(
+          children: [
+            Text(
+              controller.selectedGoodsInfoItem?.selectDesc ?? "",
+              style: TextStyle(
+                color: Colors.black.withAlpha(102),
+                fontSize: 12.sp,
+                fontWeight: FontWeight.w400,
+              ),
+            ),
+          ],
+        ),
+      );
+    });
+  }
+
+  Widget _buildMemberCard() {
+    return Container(
+      margin: EdgeInsets.symmetric(horizontal: 16.w),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.start,
+        crossAxisAlignment: CrossAxisAlignment.start,
         children: [
+          Assets.images.iconNewDiscountMembershipCardTitle.image(
+            width: 79.w,
+            height: 24.w,
+          ),
+          SizedBox(height: 6.w),
           Text(
-            '¥${item.amountText}',
-            textAlign: TextAlign.center,
-            style:
-            isSelected
-                ? Styles.getTextStyleFF7F14W500(12.sp)
-                : Styles.getTextStyleWhiteW500(12.sp),
-          )
-          // Container(
-          //   width: 212.w,
-          //   height: 70.h,
-          //   decoration: ShapeDecoration(
-          //     gradient:
-          //         isSelected
-          //             ? LinearGradient(
-          //               begin: Alignment(-0.06, 0.50),
-          //               end: Alignment(1.14, 0.50),
-          //               colors: [
-          //                 const Color(0xFFFFF895),
-          //                 const Color(0xFFFFE941),
-          //               ],
-          //             )
-          //             : null,
-          //     color: isSelected ? null : const Color(0xFFFFFDEE),
-          //     shape: RoundedRectangleBorder(
-          //       side: BorderSide(width: 1, color: const Color(0xFFFEE86B)),
-          //       borderRadius: BorderRadius.circular(isSelected ? 8 : 10.r),
-          //     ),
-          //   ),
-          //   child: Stack(
-          //     children: [
-          //       if (isSelected)
-          //         IgnorePointer(
-          //           child: Assets.images.bgStoreSelectedItem.image(
-          //             width: 212.w,
-          //             height: 70.h,
-          //             fit: BoxFit.fill,
-          //           ),
-          //         ),
-          //       Padding(
-          //         padding: EdgeInsets.only(left: 16.w),
-          //         child: Column(
-          //           crossAxisAlignment: CrossAxisAlignment.start,
-          //           mainAxisAlignment: MainAxisAlignment.center,
-          //           children: [
-          //             Row(
-          //               children: [
-          //                 RichText(
-          //                   text: TextSpan(
-          //                     children: [
-          //                       TextSpan(
-          //                         text: '¥',
-          //                         style: Styles.getTextStyleFF663300W700(14.sp),
-          //                       ),
-          //                       TextSpan(
-          //                         text: item.priceDescNumber,
-          //                         style: Styles.getTextStyleFF663300W700(18.sp),
-          //                       ),
-          //                       TextSpan(
-          //                         text: item.priceDescUnit,
-          //                         style: Styles.getTextStyleFF663300W400(13.sp),
-          //                       ),
-          //                     ],
-          //                   ),
-          //                 ),
-          //                 if (item.mostDesc?.isNotEmpty == true)
-          //                   Container(
-          //                     padding: EdgeInsets.only(
-          //                       left: 16.w,
-          //                       top: 2.h,
-          //                       bottom: 2.h,
-          //                     ),
-          //                     decoration: BoxDecoration(
-          //                       image: DecorationImage(
-          //                         image: Assets.images.iconStoreMost.provider(),
-          //                         fit: BoxFit.cover,
-          //                         alignment: Alignment.bottomLeft,
-          //                       ),
-          //                     ),
-          //                     child: Text(
-          //                       item.mostDesc!,
-          //                       style: TextStyle(
-          //                         color: Colors.white,
-          //                         fontSize: 12.sp,
-          //                         fontWeight: FontWeight.w500,
-          //                         letterSpacing: -0.60,
-          //                       ),
-          //                     ),
-          //                   ),
-          //               ],
-          //             ),
-          //             Text(
-          //               item.description!,
-          //               style: Styles.getTextStyle99673300W400(12.sp),
-          //             ),
-          //           ],
-          //         ),
-          //       ),
-          //     ],
-          //   ),
-          // ),
-          // // 右侧
-          // Expanded(
-          //   child: Column(
-          //     mainAxisAlignment: MainAxisAlignment.center,
-          //     crossAxisAlignment: CrossAxisAlignment.center,
-          //     children: [
-          //       Text(
-          //         item.name,
-          //         style:
-          //             isSelected
-          //                 ? Styles.getTextStyleFFECBBW500(15.sp)
-          //                 : Styles.getTextStyleFF663300W500(15.sp),
-          //       ),
-          //       Container(
-          //         padding: EdgeInsets.symmetric(horizontal: 8.w),
-          //         decoration: ShapeDecoration(
-          //           color: isSelected ? const Color(0xFFFFECBB) : null,
-          //           gradient:
-          //               isSelected
-          //                   ? null
-          //                   : LinearGradient(
-          //                     begin: Alignment(0.77, -0.00),
-          //                     end: Alignment(0.77, 1.00),
-          //                     colors: [
-          //                       const Color(0xFFFF9416),
-          //                       const Color(0xFFFF7813),
-          //                     ],
-          //                   ),
-          //           shape: RoundedRectangleBorder(
-          //             borderRadius: BorderRadius.circular(
-          //               isSelected ? 17.r : 10.r,
-          //             ),
-          //           ),
-          //         ),
-          //         child: Text(
-          //           '¥${item.amountText}',
-          //           textAlign: TextAlign.center,
-          //           style:
-          //               isSelected
-          //                   ? Styles.getTextStyleFF7F14W500(12.sp)
-          //                   : Styles.getTextStyleWhiteW500(12.sp),
-          //         ),
-          //       ),
-          //     ],
-          //   ),
-          // ),
+            StringName.newDiscountMemberCardDesc,
+            style: TextStyle(
+              color: Colors.black.withValues(alpha: 87),
+              fontSize: 11.sp,
+              fontWeight: FontWeight.w400,
+            ),
+          ),
+          SizedBox(height: 8.w),
+          _buildMemberCardItem(),
         ],
       ),
     );
   }
+
+  // 卡片权益
+  _buildMemberCardItem() {
+    return SizedBox(
+      height: 80.w,
+      child: AutoScrollListView(
+        scrollDirection: Axis.horizontal,
+        itemBuilder: (context, index) {
+          final item = controller.memberCardList[index];
+          return Container(
+            margin: EdgeInsets.only(right: 8.w),
+            width: 140.w,
+            height: 65.w,
+            decoration: ShapeDecoration(
+              gradient: item.gradient,
+              shape: RoundedRectangleBorder(
+                side: BorderSide(width: 1.w, color: Colors.black.withAlpha(8)),
+                borderRadius: BorderRadius.circular(20.r),
+              ),
+            ),
+            child: Row(
+              mainAxisAlignment: MainAxisAlignment.center,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                item.imageUrl.image(width: 28.w, height: 27.62.w),
+                SizedBox(width: 8.w),
+                Column(
+                  crossAxisAlignment: CrossAxisAlignment.start,
+                  mainAxisAlignment: MainAxisAlignment.center,
+                  children: [
+                    Text(
+                      item.title,
+                      style: TextStyle(
+                        color: Colors.black.withAlpha(204),
+                        fontSize: 12.sp,
+                        fontWeight: FontWeight.w700,
+                      ),
+                    ),
+                    SizedBox(height: 6.w),
+                    Text(
+                      item.desc,
+                      style: TextStyle(
+                        color: Colors.black.withAlpha(128),
+                        fontSize: 10.sp,
+                        fontWeight: FontWeight.w400,
+                      ),
+                    ),
+                  ],
+                ),
+              ],
+            ),
+          );
+        },
+        itemCount: controller.memberCardList.length,
+      ),
+    );
+  }
+
+  Widget _buildPrivacyTextSpan() {
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Obx(() {
+          return GestureDetector(
+            behavior: HitTestBehavior.opaque,
+            onTap: () {
+              controller.isAgree.value = !controller.isAgree.value;
+            },
+            child:
+                controller.isAgree.value
+                    ? Assets.images.iconStoreAgreePrivacy.image(
+                      width: 16.w,
+                      height: 16.w,
+                    )
+                    : SizedBox(
+                      child: Container(
+                        padding: EdgeInsets.all(1.w),
+                        width: 16.w,
+                        height: 16.w,
+                        child: Container(
+                          decoration: BoxDecoration(
+                            shape: BoxShape.circle,
+                            border: Border.all(
+                              color: Colors.black.withAlpha(153),
+                              width: 1.w,
+                            ),
+                          ),
+                        ),
+                      ),
+                    ),
+          );
+        }),
+        Text.rich(
+          TextSpan(
+            children: [
+              TextSpan(
+                text: StringName.textSpanIHaveReadAndAgree,
+                style: TextStyle(
+                  color: Colors.black.withAlpha(153),
+                  fontSize: 10.sp,
+                  fontWeight: FontWeight.w400,
+                ),
+              ),
+              ClickTextSpan(
+                text: StringName.textSpanPrivacyPolicy,
+                url: WebUrl.privacyPolicy,
+              ),
+
+              TextSpan(
+                text: StringName.textSpanAnd,
+                style: TextStyle(
+                  color: Colors.black.withAlpha(153),
+                  fontSize: 10.sp,
+                  fontWeight: FontWeight.w400,
+                ),
+              ),
+
+              ClickTextSpan(
+                text: StringName.textSpanServiceTerms,
+                url: WebUrl.serviceAgreement,
+              ),
+            ],
+          ),
+        ),
+      ],
+    );
+  }
 }

+ 20 - 0
lib/module/store/store_controller.dart

@@ -12,10 +12,14 @@ import 'package:keyboard/data/repository/store_repository.dart';
 import 'package:keyboard/dialog/login/login_dialog.dart';
 import 'package:keyboard/dialog/payment_fail_dialog.dart';
 import 'package:keyboard/dialog/payment_success_dialog.dart';
+import 'package:keyboard/module/store/new_discount/new_discount_page.dart';
 import 'package:keyboard/module/store/store_banner_bean.dart';
 import 'package:keyboard/module/store/store_user_reviews_bean.dart';
+import 'package:keyboard/module/store/suprise/surprise_dialog.dart';
+import 'package:keyboard/module/store/ticket/discount_ticket_dialog.dart';
 import 'package:keyboard/utils/async_util.dart';
 import 'package:keyboard/utils/atmob_log.dart';
+import 'package:lottie/lottie.dart';
 
 import '../../data/api/response/user_info_response.dart';
 import '../../data/bean/member_info.dart';
@@ -447,12 +451,28 @@ class StoreController extends BaseController implements PaymentStatusCallback {
     super.onReady();
     refreshStoreData();
   }
+  @override
+  void onInit() async{
+    super.onInit();
+    await AssetLottie(Assets.anim.animSurpriseDialogData).load();
+
+  }
 
   @override
   void onClose() {
     super.onClose();
     _storeDataFuture?.cancel();
     paymentStatusManager.unregisterPaymentSuccessCallback(this);
+    DiscountTicketDialog.show(clickConfirm: () {
+      NewDiscountPage.start();
+    },clickCancel: () {
+      SurpriseDialog.show(
+          clickConfirm: () {
+            NewDiscountPage.start();
+          }
+      );
+    }
+    );
   }
 
   @override

+ 3 - 0
lib/module/store/store_page.dart

@@ -468,6 +468,7 @@ class StorePage extends BasePage<StoreController> {
           ),
         ],
       ),
+
       child: Obx(() {
         return Text(
           controller.selectedGoodsInfoItem?.selectDesc ?? "",
@@ -867,4 +868,6 @@ class StorePage extends BasePage<StoreController> {
       ),
     );
   }
+
+
 }

+ 6 - 1
lib/module/store/suprise/goods_surprise_controller.dart

@@ -21,6 +21,8 @@ class GoodsSurpriseController extends BaseController {
 
   CancelableFuture? _storeDataFuture;
 
+  RxList<GoodsInfo> get goodsInfoList => storeRepository.newDiscountGoodsInfoList;
+
   final Rxn<GoodsInfo> _firstAmount = Rxn<GoodsInfo>();
 
   GoodsInfo? get firstAmount => _firstAmount.value;
@@ -34,13 +36,16 @@ class GoodsSurpriseController extends BaseController {
   @override
   void onInit() {
     startCountdown();
+    _firstAmount.value = goodsInfoList.first;
+    _secondAmount.value = goodsInfoList.last;
+
     super.onInit();
   }
 
   @override
   void onReady() {
     super.onReady();
-    refreshStoreData();
+
   }
 
   void startCountdown() {

+ 4 - 1
lib/module/store/suprise/surprise_dialog.dart

@@ -15,12 +15,14 @@ import 'goods_surprise_controller.dart';
 class SurpriseDialog {
   static const String tag = 'SurpriseDialog';
 
-  static void show({VoidCallback? clickConfirm}) {
+  static void show({VoidCallback? clickConfirm,VoidCallback? clickCancel}) {
     SmartDialog.show(
       tag: tag,
       backType: SmartBackType.block,
       clickMaskDismiss: false,
       maskColor: ColorName.black70,
+      onDismiss: () => Get.delete<GoodsSurpriseController>(),
+      animationType: SmartAnimationType.centerScale_otherSlide,
       builder: (_) {
         final controller = Get.find<GoodsSurpriseController>();
         return Stack(
@@ -185,6 +187,7 @@ class SurpriseDialog {
                     child: GestureDetector(
                       onTap: () {
                         SmartDialog.dismiss(tag: tag);
+                        clickCancel?.call();
                       },
                       child: Assets.images.iconCharacterDialogClose.image(
                         width: 40.r,

+ 4 - 1
lib/module/store/ticket/discount_ticket_dialog.dart

@@ -12,12 +12,14 @@ import '../suprise/goods_surprise_controller.dart';
 class DiscountTicketDialog {
   static const String tag = 'DiscountTicketDialog';
 
-  static void show({VoidCallback? clickConfirm}) {
+  static void show({VoidCallback? clickConfirm,VoidCallback? clickCancel}) {
     SmartDialog.show(
       tag: tag,
       backType: SmartBackType.block,
       clickMaskDismiss: false,
       maskColor: ColorName.black70,
+      animationType: SmartAnimationType.centerScale_otherSlide,
+      onDismiss: () => Get.delete<GoodsSurpriseController>(),
       builder: (_) {
         final controller = Get.find<GoodsSurpriseController>();
         return Stack(
@@ -254,6 +256,7 @@ class DiscountTicketDialog {
                     child: GestureDetector(
                       onTap: () {
                         SmartDialog.dismiss(tag: tag);
+                        clickCancel?.call();
                       },
                       child: Assets.images.iconCharacterDialogClose.image(
                         width: 40.r,

+ 1 - 1
lib/module/user_info/user_info_page.dart

@@ -78,7 +78,7 @@ class UserInfoPage extends BasePage<UserInfoController> {
                       style: Styles.getTextStyleBlack204W400(14.sp),
                     ),
                     Text(
-                      controller.userInfo?.phone ?? "",
+                      controller.userInfo?.account ?? "",
                       style: TextStyle(
                         color: Colors.black.withAlpha(102),
                         fontSize: 14.sp,

+ 11 - 2
lib/module/user_profile/user_profile_controller.dart

@@ -7,10 +7,12 @@ import '../../data/api/response/user_info_response.dart';
 import '../../data/bean/default_avatar_info.dart';
 import '../../data/repository/config_repository.dart';
 import '../../resource/string.gen.dart';
+import '../../utils/age_zodiac_sign_util.dart';
 import '../../utils/atmob_log.dart';
 import '../change/birthday/change_birthday_page.dart';
 import '../change/gender/change_gender_page.dart';
 import '../change/nickname/change_nickname_page.dart';
+import 'package:intl/intl.dart';
 
 @injectable
 class UserProfileController extends BaseController {
@@ -54,6 +56,12 @@ class UserProfileController extends BaseController {
   @override
   void onInit() {
     super.onInit();
+    _currentNickname.value = userInfo?.name;
+    _currentBirthday.value = AgeZodiacSignUtil.formatBirthdayFromString(
+      userInfo?.birthday,
+    );
+    _currentGender.value = userInfo?.gender;
+    _userAvatarUrl.value = userInfo?.imageUrl ?? "";
     updateAvatarListsAndSelectFirst(configRepository.defaultAvatarInfo.value);
   }
 
@@ -64,6 +72,9 @@ class UserProfileController extends BaseController {
   void updateAvatarListsAndSelectFirst(DefaultAvatarInfo? info) {
     _boyAvatars.assignAll(info?.maleAvatars ?? []);
     _girlAvatars.assignAll(info?.femaleAvatars ?? []);
+    if (_userAvatarUrl.isNotEmpty) {
+      return;
+    }
     if (_currentGender.value == 1) {
       _userAvatarUrl.value = _boyAvatars.isNotEmpty ? _boyAvatars.first : "";
     } else {
@@ -111,8 +122,6 @@ class UserProfileController extends BaseController {
       _currentGender.value = result;
     }
 
-    // 有变化才改
-    if (result == _currentGender.value) return;
     if (result == 1 && _boyAvatars.isNotEmpty) {
       _userAvatarUrl.value = _boyAvatars.first;
     } else if (_girlAvatars.isNotEmpty) {

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

@@ -58,6 +58,14 @@ class $AssetsAnimGen {
 class $AssetsImagesGen {
   const $AssetsImagesGen();
 
+  /// File path: assets/images/bg_agreement_again_dialog.webp
+  AssetGenImage get bgAgreementAgainDialog =>
+      const AssetGenImage('assets/images/bg_agreement_again_dialog.webp');
+
+  /// File path: assets/images/bg_agreement_dialog.webp
+  AssetGenImage get bgAgreementDialog =>
+      const AssetGenImage('assets/images/bg_agreement_dialog.webp');
+
   /// File path: assets/images/bg_character_boy_banner.webp
   AssetGenImage get bgCharacterBoyBanner =>
       const AssetGenImage('assets/images/bg_character_boy_banner.webp');
@@ -114,6 +122,10 @@ class $AssetsImagesGen {
   AssetGenImage get bgGoApp =>
       const AssetGenImage('assets/images/bg_go_app.webp');
 
+  /// File path: assets/images/bg_heart_fill.png
+  AssetGenImage get bgHeartFill =>
+      const AssetGenImage('assets/images/bg_heart_fill.png');
+
   /// File path: assets/images/bg_intimacy_analyse.webp
   AssetGenImage get bgIntimacyAnalyse =>
       const AssetGenImage('assets/images/bg_intimacy_analyse.webp');
@@ -188,6 +200,14 @@ class $AssetsImagesGen {
   AssetGenImage get bgMineVipCard =>
       const AssetGenImage('assets/images/bg_mine_vip_card.webp');
 
+  /// File path: assets/images/bg_new_discount_item_select.webp
+  AssetGenImage get bgNewDiscountItemSelect =>
+      const AssetGenImage('assets/images/bg_new_discount_item_select.webp');
+
+  /// File path: assets/images/bg_new_discount_item_unselect.webp
+  AssetGenImage get bgNewDiscountItemUnselect =>
+      const AssetGenImage('assets/images/bg_new_discount_item_unselect.webp');
+
   /// File path: assets/images/bg_new_user_result.webp
   AssetGenImage get bgNewUserResult =>
       const AssetGenImage('assets/images/bg_new_user_result.webp');
@@ -208,6 +228,10 @@ class $AssetsImagesGen {
   AssetGenImage get bgProfileSelected =>
       const AssetGenImage('assets/images/bg_profile_selected.webp');
 
+  /// File path: assets/images/bg_splash.webp
+  AssetGenImage get bgSplash =>
+      const AssetGenImage('assets/images/bg_splash.webp');
+
   /// File path: assets/images/bg_store_selected_item.webp
   AssetGenImage get bgStoreSelectedItem =>
       const AssetGenImage('assets/images/bg_store_selected_item.webp');
@@ -824,6 +848,40 @@ class $AssetsImagesGen {
     'assets/images/icon_new_discount_character_title.webp',
   );
 
+  /// File path: assets/images/icon_new_discount_item_select.webp
+  AssetGenImage get iconNewDiscountItemSelect =>
+      const AssetGenImage('assets/images/icon_new_discount_item_select.webp');
+
+  /// File path: assets/images/icon_new_discount_membership_card_1.webp
+  AssetGenImage get iconNewDiscountMembershipCard1 => const AssetGenImage(
+    'assets/images/icon_new_discount_membership_card_1.webp',
+  );
+
+  /// File path: assets/images/icon_new_discount_membership_card_2.webp
+  AssetGenImage get iconNewDiscountMembershipCard2 => const AssetGenImage(
+    'assets/images/icon_new_discount_membership_card_2.webp',
+  );
+
+  /// File path: assets/images/icon_new_discount_membership_card_3.webp
+  AssetGenImage get iconNewDiscountMembershipCard3 => const AssetGenImage(
+    'assets/images/icon_new_discount_membership_card_3.webp',
+  );
+
+  /// File path: assets/images/icon_new_discount_membership_card_4.webp
+  AssetGenImage get iconNewDiscountMembershipCard4 => const AssetGenImage(
+    'assets/images/icon_new_discount_membership_card_4.webp',
+  );
+
+  /// File path: assets/images/icon_new_discount_membership_card_5.webp
+  AssetGenImage get iconNewDiscountMembershipCard5 => const AssetGenImage(
+    'assets/images/icon_new_discount_membership_card_5.webp',
+  );
+
+  /// File path: assets/images/icon_new_discount_membership_card_title.webp
+  AssetGenImage get iconNewDiscountMembershipCardTitle => const AssetGenImage(
+    'assets/images/icon_new_discount_membership_card_title.webp',
+  );
+
   /// File path: assets/images/icon_new_user_birthday_logo.webp
   AssetGenImage get iconNewUserBirthdayLogo =>
       const AssetGenImage('assets/images/icon_new_user_birthday_logo.webp');
@@ -980,6 +1038,10 @@ class $AssetsImagesGen {
   AssetGenImage get iconSurpriseDialogTitle =>
       const AssetGenImage('assets/images/icon_surprise_dialog_title.webp');
 
+  /// File path: assets/images/icon_system_keyboard.webp
+  AssetGenImage get iconSystemKeyboard =>
+      const AssetGenImage('assets/images/icon_system_keyboard.webp');
+
   /// File path: assets/images/icon_ta_avatar.webp
   AssetGenImage get iconTaAvatar =>
       const AssetGenImage('assets/images/icon_ta_avatar.webp');
@@ -1071,6 +1133,8 @@ class $AssetsImagesGen {
 
   /// List of all assets
   List<AssetGenImage> get values => [
+    bgAgreementAgainDialog,
+    bgAgreementDialog,
     bgCharacterBoyBanner,
     bgCharacterCustomDetail,
     bgCharacterCustomHuman,
@@ -1085,6 +1149,7 @@ class $AssetsImagesGen {
     bgDiscountTagTop,
     bgDiscountTitle,
     bgGoApp,
+    bgHeartFill,
     bgIntimacyAnalyse,
     bgIntimacyAnalyseNormalCard,
     bgIntimacyAnalyseReportPreview,
@@ -1103,11 +1168,14 @@ class $AssetsImagesGen {
     bgLoginDialog,
     bgMine,
     bgMineVipCard,
+    bgNewDiscountItemSelect,
+    bgNewDiscountItemUnselect,
     bgNewUserResult,
     bgNewUserResultIntimacy,
     bgProfileEditIntimacy,
     bgProfileLove,
     bgProfileSelected,
+    bgSplash,
     bgStoreSelectedItem,
     bgStoreUserReviews,
     bgSurpriseDialog,
@@ -1253,6 +1321,13 @@ class $AssetsImagesGen {
     iconNewDiscountBanner2,
     iconNewDiscountBanner3,
     iconNewDiscountCharacterTitle,
+    iconNewDiscountItemSelect,
+    iconNewDiscountMembershipCard1,
+    iconNewDiscountMembershipCard2,
+    iconNewDiscountMembershipCard3,
+    iconNewDiscountMembershipCard4,
+    iconNewDiscountMembershipCard5,
+    iconNewDiscountMembershipCardTitle,
     iconNewUserBirthdayLogo,
     iconNewUserOpenNow,
     iconNewUserResultLoveLeft,
@@ -1292,6 +1367,7 @@ class $AssetsImagesGen {
     iconSurpriseDialogButton,
     iconSurpriseDialogOnly,
     iconSurpriseDialogTitle,
+    iconSystemKeyboard,
     iconTaAvatar,
     iconTabCharacterSelected,
     iconTabCharacterUnselect,

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

@@ -123,6 +123,7 @@ class StringName {
   static final String textSpanAnd = 'text_span_and'.tr; // 和
   static final String textSpanPrivacyPolicy = 'text_span_privacy_policy'.tr; // 《隐私政策》
   static final String textSpanServiceTerms = 'text_span_service_terms'.tr; // 《服务条款》
+  static final String textSpanUserAgreement = 'text_span_user_agreement'.tr; // 《用户协议》
   static final String memberContinuePay = 'member_continue_pay'.tr; // 继续支付
   static final String memberPleaseChoiceGoods = 'member_please_choice_goods'.tr; // 请选择支付商品
   static final String memberPleaseChoicePayment = 'member_please_choice_payment'.tr; // 请选择支付方式
@@ -287,6 +288,23 @@ class StringName {
   static final String selectBirthdayDialogConfirm = 'select_birthday_dialog_confirm'.tr; // 确定
   static final String newUserResultIntimacyTitle = 'new_user_result_intimacy_title'.tr; // 亲密度:
   static final String newUserResultIntimacyDesc = 'new_user_result_intimacy_desc'.tr; // 根据当前的亲密度,建议选择以下人设
+  static final String confirmAdd = 'confirm_add'.tr; // 确认添加
+  static final String newDiscountMemberCardDesc = 'new_discount_member_card_desc'.tr; // 开通可畅享多种会员权益
+  static final String newDiscountMemberCard1Title = 'new_discount_member_card1_title'.tr; // 亲密度分析
+  static final String newDiscountMemberCard1Desc = 'new_discount_member_card1_desc'.tr; // 探索人格/情感特质
+  static final String newDiscountMemberCard2Title = 'new_discount_member_card2_title'.tr; // 星座分析
+  static final String newDiscountMemberCard2Desc = 'new_discount_member_card2_desc'.tr; // 指引你的星座缘分
+  static final String newDiscountMemberCard3Title = 'new_discount_member_card3_title'.tr; // 追爱自动回复
+  static final String newDiscountMemberCard3Desc = 'new_discount_member_card3_desc'.tr; // 智能生成不踩雷
+  static final String newDiscountMemberCard4Title = 'new_discount_member_card4_title'.tr; // Crush心情解析
+  static final String newDiscountMemberCard4Desc = 'new_discount_member_card4_desc'.tr; // 分析真实想法
+  static final String newDiscountMemberCard5Title = 'new_discount_member_card5_title'.tr; // N种精品人设
+  static final String newDiscountMemberCard5Desc = 'new_discount_member_card5_desc'.tr; // 为你量身打造
+  static final String newDiscountUnlockNow = 'new_discount_unlock_now'.tr; // 立即解锁体验
+  static final String privacyTitle = 'privacy_title'.tr; // 隐私政策及权限说明
+  static final String privacyDisagree = 'privacy_disagree'.tr; // 不同意
+  static final String privacyDisagreeAndExit = 'privacy_disagree_and_exit'.tr; // 不同意并退出
+  static final String privacyAgree = 'privacy_agree'.tr; // 同意
 }
 class StringMultiSource {
   StringMultiSource._();
@@ -413,6 +431,7 @@ class StringMultiSource {
       'text_span_and': '和',
       'text_span_privacy_policy': '《隐私政策》',
       'text_span_service_terms': '《服务条款》',
+      'text_span_user_agreement': '《用户协议》',
       'member_continue_pay': '继续支付',
       'member_please_choice_goods': '请选择支付商品',
       'member_please_choice_payment': '请选择支付方式',
@@ -577,6 +596,23 @@ class StringMultiSource {
       'select_birthday_dialog_confirm': '确定',
       'new_user_result_intimacy_title': '亲密度:',
       'new_user_result_intimacy_desc': '根据当前的亲密度,建议选择以下人设',
+      'confirm_add': '确认添加',
+      'new_discount_member_card_desc': '开通可畅享多种会员权益',
+      'new_discount_member_card1_title': '亲密度分析',
+      'new_discount_member_card1_desc': '探索人格/情感特质',
+      'new_discount_member_card2_title': '星座分析',
+      'new_discount_member_card2_desc': '指引你的星座缘分',
+      'new_discount_member_card3_title': '追爱自动回复',
+      'new_discount_member_card3_desc': '智能生成不踩雷',
+      'new_discount_member_card4_title': 'Crush心情解析',
+      'new_discount_member_card4_desc': '分析真实想法',
+      'new_discount_member_card5_title': 'N种精品人设',
+      'new_discount_member_card5_desc': '为你量身打造',
+      'new_discount_unlock_now': '立即解锁体验',
+      'privacy_title': '隐私政策及权限说明',
+      'privacy_disagree': '不同意',
+      'privacy_disagree_and_exit': '不同意并退出',
+      'privacy_agree': '同意',
     },
   };
 }

+ 2 - 1
lib/router/app_pages.dart

@@ -62,6 +62,7 @@ import '../module/main/main_page.dart';
 import '../module/new_user/new_user_page.dart';
 import '../module/new_user/step/gender/step_gender_logic.dart';
 import '../module/profile/edit/profile_edit_page.dart';
+import '../module/splash/splash_page.dart';
 import '../module/store/discount/discount_controller.dart';
 import '../module/store/new_discount/new_discount_controller.dart';
 import '../module/store/suprise/goods_surprise_controller.dart';
@@ -205,6 +206,6 @@ final generalPages = [
   GetPage(name: RoutePath.newUser, page: () => NewUserPage()),
   GetPage(name: RoutePath.newUserResult, page: () => NewUserResultPage()),
   GetPage(name: RoutePath.userProfile, page: () => UserProfilePage()),
-
+  GetPage(name: RoutePath.splash, page: () => SplashPage()),
   GetPage(name: RoutePath.newDiscount, page: () => NewDiscountPage()),
 ];

+ 36 - 37
lib/utils/intimacy_util.dart

@@ -1,56 +1,55 @@
+import '../data/bean/intimacy_config_info.dart';
+
 class IntimacyUtil {
   IntimacyUtil._();
 
-  static final List<IntimacyLevel> intimacyLevels = [
-    IntimacyLevel(max: 20, min: 0, name: "初相识", median: 10),
-    IntimacyLevel(max: 40, min: 21, name: "追爱期", median: 30),
-    IntimacyLevel(max: 60, min: 41, name: "暧昧期", median: 50),
-    IntimacyLevel(max: 80, min: 61, name: "恋人", median: 70),
-    IntimacyLevel(max: 90, min: 81, name: "伴侣", median: 85),
-    IntimacyLevel(max: 100, min: 91, name: "老夫老妻", median: 95),
-  ];
+  static IntimacyConfigInfo? _configInfo;
+
+  static List<IntimacyBean>? intimacyList() {
+    return _configInfo?.intimacy;
+  }
+
+  /// 设置亲密度配置
+  static void setConfig(IntimacyConfigInfo? config) {
+    _configInfo = config;
+  }
 
-  /// 获取亲密程度名称
+  /// 获取亲密度名称
   static String getIntimacyName(int intimacy) {
-    for (final level in intimacyLevels) {
-      if (intimacy >= level.min && intimacy <= level.max) {
-        return level.name;
+    final levels = _configInfo?.intimacy;
+    if (levels == null || levels.isEmpty) return "未知";
+
+    for (final level in levels) {
+      if (intimacy >= (level.min ?? 0) && intimacy <= (level.max ?? 0)) {
+        return level.name ?? "未知";
       }
     }
     return "未知";
   }
 
-  /// 获取对应的亲密程度对象
-  static IntimacyLevel? getIntimacyLevel(int intimacy) {
-    for (final level in intimacyLevels) {
-      if (intimacy >= level.min && intimacy <= level.max) {
+
+
+  /// 获取当前对应的 IntimacyBean
+  static IntimacyBean? getIntimacyLevel(int intimacy) {
+    final levels = _configInfo?.intimacy;
+    if (levels == null || levels.isEmpty) return null;
+
+    for (final level in levels) {
+      if (intimacy >= (level.min ?? 0) && intimacy <= (level.max ?? 0)) {
         return level;
       }
     }
     return null;
   }
 
+  /// 根据 index 获取中值
   static int getMedianByIndex(int index) {
-    if (index >= 0 && index < intimacyLevels.length) {
-      return intimacyLevels[index].median;
-    }
-    return 0;
+    final levels = _configInfo?.intimacy;
+    if (levels == null || index < 0 || index >= levels.length) return 0;
+
+    final level = levels[index];
+    final min = level.min ?? 0;
+    final max = level.max ?? 0;
+    return ((min + max) / 2).round();
   }
 }
-
-class IntimacyLevel {
-  final int max;
-  final int min;
-  final String name;
-  final int median;
-
-  const IntimacyLevel({
-    required this.max,
-    required this.min,
-    required this.name,
-    required this.median,
-  });
-
-  @override
-  String toString() => 'IntimacyLevel($name: $min-$max)';
-}

+ 1 - 1
lib/utils/privacy_compliance.dart

@@ -5,7 +5,7 @@ class PrivacyCompliance {
 
   static const String isPolicyGranted = 'isPolicyGranted';
   static final List<EnsurePolicyGrant> _pendingTasks = [];
-  static bool _isPolicyGranted = true;
+  static bool _isPolicyGranted = false;
 
   static Future<void> ensurePolicyGranted(EnsurePolicyGrant ensure) async {
     if (isAgreePrivacyPolicy()) {