import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../controllers/splash_controller.dart'; class SplashView extends GetView { const SplashView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; return Scaffold( backgroundColor: isDarkMode ? Colors.black : const Color(0xFFF5F5F7), body: Stack( children: [ // 主内容 Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Logo动画 _buildAnimatedLogo(isDarkMode), // 应用名称 _buildAppTitle(isDarkMode), // 标语 _buildSlogan(isDarkMode), // 加载进度条 SizedBox(height: 40.h), _buildLoadingBar(isDarkMode), // 额外信息 SizedBox(height: 16.h), _buildExtraInfo(isDarkMode), ], ), ), // 隐私政策组件 - 添加在底部 if (!controller.hasAcceptedPrivacy.value) Positioned( bottom: 90.h, left: 0, right: 0, child: _buildTermsAndPrivacy(isDarkMode), ), // 版本号 //_buildVersionInfo(isDarkMode), ], ), ); } // 动画Logo Widget _buildAnimatedLogo(bool isDarkMode) { return TweenAnimationBuilder( tween: Tween(begin: 0.8, end: 1.1), duration: const Duration(seconds: 2), curve: Curves.easeInOut, builder: (context, value, child) { // 确保opacity值不超过1.0 final opacity = value <= 1.0 ? value : 1.0; return Transform.scale( scale: value, child: AnimatedOpacity( opacity: opacity, duration: const Duration(milliseconds: 500), child: child, ), ); }, // 启动页 logo:直接用 App 自己的图标,不再用「蓝紫渐变 + 耳机 glyph」。 // assets/images/app_icon.png 是 iOS AppIcon 1024 缩到 512 的副本; // 它是**不带圆角的正方形**(RGB 无 alpha),圆角靠外面这层 ClipRRect 切, // 所以半径改这里就行。换 App 图标时记得同步替换这个 asset。 child: Container( width: 96.w, height: 96.w, decoration: BoxDecoration( borderRadius: BorderRadius.circular(24.r), boxShadow: [ BoxShadow( color: Colors.blue.withOpacity(0.3), blurRadius: 15, offset: const Offset(0, 8), spreadRadius: 3, ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(24.r), child: Image.asset( 'assets/images/app_icon.png', width: 96.w, height: 96.w, fit: BoxFit.cover, ), ), ), ); } // 应用标题 Widget _buildAppTitle(bool isDarkMode) { return TweenAnimationBuilder( tween: Tween(begin: 0.0, end: 1.0), duration: const Duration(milliseconds: 1500), curve: Curves.easeOut, builder: (context, value, child) { return Opacity( opacity: value, child: Padding( padding: EdgeInsets.only(top: 24.h), child: Text( 'Eaimar', style: TextStyle( fontSize: 28.sp, fontWeight: FontWeight.bold, color: isDarkMode ? Colors.white : Colors.grey[800], ), ), ), ); }, ); } // 标语 Widget _buildSlogan(bool isDarkMode) { return TweenAnimationBuilder( tween: Tween(begin: 0.0, end: 1.0), duration: const Duration(milliseconds: 1500), curve: Curves.easeOut, builder: (context, value, child) { return Opacity( opacity: value, child: Padding( padding: EdgeInsets.only(top: 8.h), child: Text( 'slogan'.tr, // 连接世界,岂止声音 style: TextStyle( fontSize: 14.sp, color: isDarkMode ? Colors.grey[400] : Colors.grey[600], ), ), ), ); }, ); } // 加载进度条 Widget _buildLoadingBar(bool isDarkMode) { return Padding( padding: EdgeInsets.symmetric(horizontal: 80.w), child: Stack( children: [ // 背景条 Container( height: 4.h, decoration: BoxDecoration( color: isDarkMode ? Colors.grey[800] : Colors.grey[200], borderRadius: BorderRadius.circular(2.r), ), ), // 进度条 Obx(() { final progress = controller.loadingProgress; return AnimatedContainer( duration: const Duration(milliseconds: 200), height: 4.h, width: 240.w * progress, // 使用固定宽度乘以进度 decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.centerLeft, end: Alignment.centerRight, colors: [Colors.blue, Colors.purple], ), borderRadius: BorderRadius.circular(2.r), boxShadow: [ BoxShadow( color: Colors.blue.withOpacity(0.3), blurRadius: 5, offset: const Offset(0, 1), ), ], ), ); }), ], ), ); } // 额外信息 Widget _buildExtraInfo(bool isDarkMode) { return TweenAnimationBuilder( tween: Tween(begin: 0.0, end: 1.0), duration: const Duration(milliseconds: 1500), curve: Curves.easeOut, builder: (context, value, child) { return Opacity( opacity: value, child: Text( 'sloganInfo'.tr, // AI语音专家 · 随时随地 style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.grey[500] : Colors.grey[400], ), ), ); }, ); } // 用户协议和隐私政策 Widget _buildTermsAndPrivacy(bool isDarkMode) { return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ // 将勾选框和文本包装在 GestureDetector 中 GestureDetector( //onTap: () => controller.togglePrivacyAcceptance(), behavior: HitTestBehavior.opaque, // 确保透明区域也能响应点击 child: Row( children: [ SizedBox( width: 12.w, height: 16.w, child: Transform.scale( scale: 0.7, child: Obx(() => Checkbox( value: controller.hasAcceptedPrivacy.value, onChanged: (value) => controller .hasAcceptedPrivacy.value = value ?? false, activeColor: const Color(0xFF3B82F6), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, visualDensity: VisualDensity.compact, side: BorderSide( width: 1.6, color: Colors.grey[600]!, ), )), ), ), SizedBox(width: 4.w), Text( 'expressConsent'.tr, // 登录/注册即表示你同意 style: TextStyle( fontSize: 13.sp, color: isDarkMode ? Colors.grey[400] : Colors.grey[700], ), ), ], ), ), ], ), //SizedBox(height: 4.h), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( // 注:此处 onTap 早已注释失效(旧实现指向上一代服务器的静态页)。 // 活的入口在 login_view / profile_view,走 doc_url_helper 的 userAgreementUrl()。 child: Text( 'userAgreement'.tr, // 《用户协议》 style: TextStyle( fontSize: 12.sp, color: const Color(0xFF3B82F6), ), ), ), Text( 'and'.tr, // 和 style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.grey[500] : Colors.grey[600], ), ), GestureDetector( // 注:同上,onTap 已失效;活的入口走 doc_url_helper 的 privacyPolicyUrl()。 child: Text( 'privacyPolicy'.tr, // 《隐私政策》 style: TextStyle( fontSize: 12.sp, color: const Color(0xFF3B82F6), ), ), ), ], ), ], ); } // 版本信息 // 暂时不需要版本号显示,保留代码以备将来使用 // Widget _buildVersionInfo(bool isDarkMode) { // return Positioned( // bottom: 32.h, // left: 0, // right: 0, // child: Center( // child: Text( // controller.version, // style: TextStyle( // fontSize: 12.sp, // color: isDarkMode ? Colors.grey[500] : Colors.grey[400], // ), // ), // ), // ); // } }