import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../../../data/models/goods.dart'; import '../../../data/models/user_Info.dart'; import '../controllers/goodsmeet_controller.dart'; import '../utils/goods_i18n.dart'; import 'widgets/goods_footer_section.dart'; class GoodsmeetView extends GetView { const GoodsmeetView({super.key}); @override Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; return Scaffold( backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], appBar: AppBar( backgroundColor: isDarkMode ? Colors.black : Colors.white, elevation: 0.5, leading: IconButton( icon: Icon( Icons.arrow_back_ios, size: 20.sp, color: isDarkMode ? Colors.white : Colors.black87, ), onPressed: () => Get.back(), ), title: Text( 'meetingAssistantRecharge'.tr, style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w600, color: isDarkMode ? Colors.white : Colors.black, ), ), centerTitle: true, ), body: SafeArea( top: false, child: Obx(() { // 访问刷新信号以建立依赖关系:用户信息变化时触发重建 final _ = User.refreshTick.value; if (controller.loading.value) { return const Center(child: CircularProgressIndicator()); } if (controller.error.isNotEmpty) { return Center(child: Text(controller.error.value)); } return ListView.separated( padding: EdgeInsets.all(16.w), itemCount: controller.items.length + 4, separatorBuilder: (_, __) => SizedBox(height: 12.h), itemBuilder: (_, index) { if (index == 0) { return _buildHeader(isDarkMode); } if (index == 1) { return _buildUsageCard(isDarkMode); } final itemIndex = index - 2; if (itemIndex < controller.items.length) { final item = controller.items[itemIndex]; return _buildCard(item, isDarkMode); } if (index == controller.items.length + 2) { return _buildFeaturesSection(isDarkMode); } return GoodsFooterSection(isDarkMode: isDarkMode); }, ); }), ), ); } Widget _buildHeader(bool isDarkMode) { return Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( color: isDarkMode ? Colors.grey[900] : Colors.white, borderRadius: BorderRadius.circular(12.r), boxShadow: [ BoxShadow( color: isDarkMode ? Colors.black.withOpacity(0.2) : Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 44.w, height: 44.w, decoration: BoxDecoration( color: isDarkMode ? Colors.pink[900]!.withOpacity(0.3) : Colors.pink[100]!, borderRadius: BorderRadius.circular(22.r), ), child: Icon(Icons.people_alt, color: isDarkMode ? Colors.pink[300]! : Colors.pink[600]!), ), SizedBox(width: 12.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'conferenceAssistant'.tr, style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.w700, color: isDarkMode ? Colors.white : Colors.black, ), ), SizedBox(height: 6.h), Text( 'meetingHeaderDesc1'.tr, style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.white70 : Colors.grey[700], ), ), SizedBox(height: 4.h), Text( 'meetingHeaderDesc2'.tr, style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.white70 : Colors.grey[700], ), ), ], ), ), ], ), ); } Widget _buildUsageCard(bool isDarkMode) { int totalAi = 0; int remainAi = 0; if (User.isLoggedIn()) { final u = User.instance; totalAi = u.meettotalintegral; remainAi = u.meetintegral; } final progress = (totalAi > 0) ? (remainAi / totalAi).clamp(0.0, 1.0) : 0.0; return Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( color: isDarkMode ? Colors.grey[900] : Colors.white, borderRadius: BorderRadius.circular(12.r), boxShadow: [ BoxShadow( color: isDarkMode ? Colors.black.withOpacity(0.2) : Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Icon(Icons.timeline, color: isDarkMode ? Colors.blue[300]! : Colors.blue[600]!), SizedBox(width: 8.w), Text( 'remainingQuota'.tr, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, color: isDarkMode ? Colors.white : Colors.black, ), ), ], ), SizedBox(height: 12.h), LinearProgressIndicator( value: progress, minHeight: 8.h, backgroundColor: isDarkMode ? Colors.grey[800] : Colors.grey[300], valueColor: AlwaysStoppedAnimation( isDarkMode ? Colors.blue[300]! : Colors.blue[600]!), ), SizedBox(height: 8.h), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${'totalQuota'.tr}:$totalAi', style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.white70 : Colors.grey[700], ), ), Text( '${'remaining'.tr}:$remainAi', style: TextStyle( fontSize: 12.sp, color: isDarkMode ? Colors.white70 : Colors.grey[700], ), ), ], ), ], ), ); } Widget _buildCard(DBGoods item, bool isDarkMode) { return Container( padding: EdgeInsets.all(16.w), decoration: BoxDecoration( color: isDarkMode ? Colors.grey[900] : Colors.white, borderRadius: BorderRadius.circular(12.r), boxShadow: [ BoxShadow( color: isDarkMode ? Colors.black.withOpacity(0.2) : Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Row( children: [ Container( width: 42.w, height: 42.w, decoration: BoxDecoration( color: isDarkMode ? Colors.pink[900]!.withOpacity(0.3) : Colors.pink[100]!, borderRadius: BorderRadius.circular(21.r), ), child: Icon(Icons.people_alt, color: isDarkMode ? Colors.pink[300]! : Colors.pink[600]!), ), SizedBox(width: 12.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(localizedGoodsName(item), style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, color: isDarkMode ? Colors.white : Colors.black, )), // SizedBox(height: 4.h), // Text(localizedGoodsDesc(item), // style: TextStyle( // fontSize: 12.sp, // color: isDarkMode ? Colors.white70 : Colors.grey[600], // )), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text(goodsDisplayPrice(item), style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, color: isDarkMode ? Colors.white : Colors.black, )), SizedBox(height: 8.h), GestureDetector( onTap: () => controller.purchase(item), child: Container( padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h), decoration: BoxDecoration( color: Colors.blue[600], borderRadius: BorderRadius.circular(20.r), ), child: Text( 'purchase'.tr, style: TextStyle(fontSize: 12.sp, color: Colors.white), ), ), ), ], ), ], ), ); } Widget _buildFeaturesSection(bool isDarkMode) { final textColor = isDarkMode ? Colors.white : Colors.black; final subColor = isDarkMode ? Colors.white70 : Colors.grey[700]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'featureDescription'.tr, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w600, color: textColor, ), ), SizedBox(height: 10.h), Wrap( spacing: 12.w, runSpacing: 12.h, alignment: WrapAlignment.start, crossAxisAlignment: WrapCrossAlignment.start, children: [ _buildFeatureCard( isDarkMode, icon: Icons.mic, title: 'meetingRecording'.tr, lines: ['meetingAutoRecording'.tr, 'meetingSpeakerTagging'.tr], colorSeed: Colors.pink, ), _buildFeatureCard( isDarkMode, icon: Icons.summarize, title: 'transcriptionAndSummary'.tr, lines: [ 'meetingLongAudioTranscription'.tr, 'meetingKeyPointSummary'.tr ], colorSeed: Colors.blue, ), _buildFeatureCard( isDarkMode, icon: Icons.search, title: 'keywordSearch'.tr, lines: ['meetingTopicNameSearch'.tr, 'meetingTimelineJump'.tr], colorSeed: Colors.indigo, ), _buildFeatureCard( isDarkMode, icon: Icons.share, title: 'collaborationSharing'.tr, lines: [ 'meetingExportSummary'.tr, 'meetingMultiPlatformShare'.tr ], colorSeed: Colors.teal, ), ], ), SizedBox(height: 12.h), Text( 'meetingDisclaimer'.tr, style: TextStyle(fontSize: 12.sp, color: subColor), ), ], ); } Widget _buildFeatureCard( bool isDarkMode, { required IconData icon, required String title, required List lines, required MaterialColor colorSeed, }) { final bgColor = isDarkMode ? Colors.grey[900] : Colors.white; final mainColor = isDarkMode ? colorSeed[300]! : colorSeed[600]!; final subColor = isDarkMode ? Colors.white70 : Colors.grey[700]; final width = (Get.width - 16.w * 2 - 12.w) / 2; return Container( width: width, padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: bgColor, borderRadius: BorderRadius.circular(12.r), boxShadow: [ BoxShadow( color: isDarkMode ? Colors.black.withOpacity(0.2) : Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 36.w, height: 36.w, decoration: BoxDecoration( color: isDarkMode ? mainColor.withOpacity(0.25) : mainColor.withOpacity(0.15), borderRadius: BorderRadius.circular(18.r), ), child: Icon(icon, color: mainColor), ), SizedBox(width: 8.w), Expanded( child: Text( title, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: isDarkMode ? Colors.white : Colors.black, ), ), ), ], ), SizedBox(height: 8.h), ...lines.map((l) => Padding( padding: EdgeInsets.only(bottom: 4.h), child: Text(l, style: TextStyle(fontSize: 12.sp, color: subColor)), )), ], ), ); } }