From ae8e307ccaedff6b74c80e65f2b28d2b3d9228b2 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Wed, 5 Nov 2025 10:21:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=94=AF=E4=BB=98vip?= =?UTF-8?q?=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/data/services/network/api.dart | 9 ++ .../goods/bindings/goodsai_binding.dart | 9 ++ .../goods/bindings/goodsmeet_binding.dart | 9 ++ .../goods/bindings/goodstrade_binding.dart | 9 ++ .../goods/bindings/goodsvip_binding.dart | 9 ++ .../goods/controllers/goodsai_controller.dart | 65 +++++++++ .../controllers/goodsmeet_controller.dart | 65 +++++++++ .../controllers/goodstrade_controller.dart | 65 +++++++++ .../controllers/goodsvip_controller.dart | 66 +++++++++ lib/modules/goods/views/goodsai_view.dart | 131 +++++++++++++++++ lib/modules/goods/views/goodsmeet_view.dart | 132 +++++++++++++++++ lib/modules/goods/views/goodstrade_view.dart | 132 +++++++++++++++++ lib/modules/goods/views/goodsvip_view.dart | 137 ++++++++++++++++++ lib/modules/settings/views/settings_view.dart | 117 +++++++++++++++ lib/routes/app_pages.dart | 37 ++++- lib/routes/app_routes.dart | 6 + 16 files changed, 997 insertions(+), 1 deletion(-) create mode 100644 lib/modules/goods/bindings/goodsai_binding.dart create mode 100644 lib/modules/goods/bindings/goodsmeet_binding.dart create mode 100644 lib/modules/goods/bindings/goodstrade_binding.dart create mode 100644 lib/modules/goods/bindings/goodsvip_binding.dart create mode 100644 lib/modules/goods/controllers/goodsai_controller.dart create mode 100644 lib/modules/goods/controllers/goodsmeet_controller.dart create mode 100644 lib/modules/goods/controllers/goodstrade_controller.dart create mode 100644 lib/modules/goods/controllers/goodsvip_controller.dart create mode 100644 lib/modules/goods/views/goodsai_view.dart create mode 100644 lib/modules/goods/views/goodsmeet_view.dart create mode 100644 lib/modules/goods/views/goodstrade_view.dart create mode 100644 lib/modules/goods/views/goodsvip_view.dart diff --git a/lib/data/services/network/api.dart b/lib/data/services/network/api.dart index ced2a2c6f..b5acf4c34 100644 --- a/lib/data/services/network/api.dart +++ b/lib/data/services/network/api.dart @@ -216,4 +216,13 @@ class Api { params: params, ); } + + //获取商品列表 + static getGoods([params]) { + return DioManager().request( + NWMethod.post, + '/api/home/pay_getgoods', + params: params, + ); + } } diff --git a/lib/modules/goods/bindings/goodsai_binding.dart b/lib/modules/goods/bindings/goodsai_binding.dart new file mode 100644 index 000000000..4c21e4920 --- /dev/null +++ b/lib/modules/goods/bindings/goodsai_binding.dart @@ -0,0 +1,9 @@ +import 'package:get/get.dart'; +import '../controllers/goodsai_controller.dart'; + +class GoodsaiBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => GoodsaiController()); + } +} \ No newline at end of file diff --git a/lib/modules/goods/bindings/goodsmeet_binding.dart b/lib/modules/goods/bindings/goodsmeet_binding.dart new file mode 100644 index 000000000..f8c1b3308 --- /dev/null +++ b/lib/modules/goods/bindings/goodsmeet_binding.dart @@ -0,0 +1,9 @@ +import 'package:get/get.dart'; +import '../controllers/goodsmeet_controller.dart'; + +class GoodsmeetBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => GoodsmeetController()); + } +} \ No newline at end of file diff --git a/lib/modules/goods/bindings/goodstrade_binding.dart b/lib/modules/goods/bindings/goodstrade_binding.dart new file mode 100644 index 000000000..70f119608 --- /dev/null +++ b/lib/modules/goods/bindings/goodstrade_binding.dart @@ -0,0 +1,9 @@ +import 'package:get/get.dart'; +import '../controllers/goodstrade_controller.dart'; + +class GoodstradeBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => GoodstradeController()); + } +} \ No newline at end of file diff --git a/lib/modules/goods/bindings/goodsvip_binding.dart b/lib/modules/goods/bindings/goodsvip_binding.dart new file mode 100644 index 000000000..50e957d57 --- /dev/null +++ b/lib/modules/goods/bindings/goodsvip_binding.dart @@ -0,0 +1,9 @@ +import 'package:get/get.dart'; +import '../controllers/goodsvip_controller.dart'; + +class GoodsvipBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => GoodsvipController()); + } +} \ No newline at end of file diff --git a/lib/modules/goods/controllers/goodsai_controller.dart b/lib/modules/goods/controllers/goodsai_controller.dart new file mode 100644 index 000000000..c51ba35d5 --- /dev/null +++ b/lib/modules/goods/controllers/goodsai_controller.dart @@ -0,0 +1,65 @@ +import 'package:get/get.dart'; +import '../../../routes/app_routes.dart'; + +class AIItem { + final String id; + final String title; + final String description; + final double price; + final String productId; + + AIItem({ + required this.id, + required this.title, + required this.description, + required this.price, + required this.productId, + }); +} + +class GoodsaiController extends GetxController { + final RxList items = [].obs; + final RxBool loading = false.obs; + final RxString error = ''.obs; + + @override + void onInit() { + super.onInit(); + _loadProducts(); + } + + Future _loadProducts() async { + loading.value = true; + error.value = ''; + try { + items.assignAll([ + AIItem( + id: 'ai_chat', + title: '通用AI聊天包', + description: '更长对话额度与工具调用', + price: 19.9, + productId: 'ai_chat_101', + ), + AIItem( + id: 'ai_tools', + title: 'AI工具扩展', + description: '额外工具能力与上下文长度', + price: 39.9, + productId: 'ai_tools_201', + ), + ]); + } catch (e) { + error.value = e.toString(); + } finally { + loading.value = false; + } + } + + void purchase(AIItem item) { + Get.toNamed(Routes.payment, arguments: { + 'productId': item.productId, + 'amount': item.price, + 'description': item.title, + }); + } +} \ No newline at end of file diff --git a/lib/modules/goods/controllers/goodsmeet_controller.dart b/lib/modules/goods/controllers/goodsmeet_controller.dart new file mode 100644 index 000000000..6b5c793a0 --- /dev/null +++ b/lib/modules/goods/controllers/goodsmeet_controller.dart @@ -0,0 +1,65 @@ +import 'package:get/get.dart'; +import '../../../routes/app_routes.dart'; + +class MeetItem { + final String id; + final String title; + final String description; + final double price; + final String productId; + + MeetItem({ + required this.id, + required this.title, + required this.description, + required this.price, + required this.productId, + }); +} + +class GoodsmeetController extends GetxController { + final RxList items = [].obs; + final RxBool loading = false.obs; + final RxString error = ''.obs; + + @override + void onInit() { + super.onInit(); + _loadProducts(); + } + + Future _loadProducts() async { + loading.value = true; + error.value = ''; + try { + items.assignAll([ + MeetItem( + id: 'meet_basic', + title: '会议助手基础版', + description: '会议纪要与基础翻译', + price: 29.9, + productId: 'meet_101', + ), + MeetItem( + id: 'meet_pro', + title: '会议助手高级版', + description: '纪要、翻译与AI总结增强', + price: 59.9, + productId: 'meet_201', + ), + ]); + } catch (e) { + error.value = e.toString(); + } finally { + loading.value = false; + } + } + + void purchase(MeetItem item) { + Get.toNamed(Routes.payment, arguments: { + 'productId': item.productId, + 'amount': item.price, + 'description': item.title, + }); + } +} \ No newline at end of file diff --git a/lib/modules/goods/controllers/goodstrade_controller.dart b/lib/modules/goods/controllers/goodstrade_controller.dart new file mode 100644 index 000000000..12cf8af16 --- /dev/null +++ b/lib/modules/goods/controllers/goodstrade_controller.dart @@ -0,0 +1,65 @@ +import 'package:get/get.dart'; +import '../../../routes/app_routes.dart'; + +class TradeItem { + final String id; + final String title; + final String description; + final double price; + final String productId; + + TradeItem({ + required this.id, + required this.title, + required this.description, + required this.price, + required this.productId, + }); +} + +class GoodstradeController extends GetxController { + final RxList items = [].obs; + final RxBool loading = false.obs; + final RxString error = ''.obs; + + @override + void onInit() { + super.onInit(); + _loadProducts(); + } + + Future _loadProducts() async { + loading.value = true; + error.value = ''; + try { + items.assignAll([ + TradeItem( + id: 'trans_100', + title: '翻译包 100 分钟', + description: '实时翻译服务时长包', + price: 19.9, + productId: 'trans_100', + ), + TradeItem( + id: 'trans_500', + title: '翻译包 500 分钟', + description: '更划算的翻译时长包', + price: 79.9, + productId: 'trans_500', + ), + ]); + } catch (e) { + error.value = e.toString(); + } finally { + loading.value = false; + } + } + + void purchase(TradeItem item) { + Get.toNamed(Routes.payment, arguments: { + 'productId': item.productId, + 'amount': item.price, + 'description': item.title, + }); + } +} \ No newline at end of file diff --git a/lib/modules/goods/controllers/goodsvip_controller.dart b/lib/modules/goods/controllers/goodsvip_controller.dart new file mode 100644 index 000000000..34d9dc98f --- /dev/null +++ b/lib/modules/goods/controllers/goodsvip_controller.dart @@ -0,0 +1,66 @@ +import 'package:get/get.dart'; +import '../../../routes/app_routes.dart'; + +class GoodsItem { + final String id; + final String title; + final String description; + final double price; + final String productId; + + GoodsItem({ + required this.id, + required this.title, + required this.description, + required this.price, + required this.productId, + }); +} + +class GoodsvipController extends GetxController { + final RxList items = [].obs; + final RxBool loading = false.obs; + final RxString error = ''.obs; + + @override + void onInit() { + super.onInit(); + _loadProducts(); + } + + Future _loadProducts() async { + loading.value = true; + error.value = ''; + try { + // 示例数据,可接后端商品接口替换 + items.assignAll([ + GoodsItem( + id: 'vip_month', + title: '月度会员', + description: '解锁高级功能,按月订阅', + price: 9.9, + productId: 'vip_101', + ), + GoodsItem( + id: 'vip_year', + title: '年度会员', + description: '解锁高级功能,按年订阅', + price: 99.0, + productId: 'vip_201', + ), + ]); + } catch (e) { + error.value = e.toString(); + } finally { + loading.value = false; + } + } + + void purchase(GoodsItem item) { + Get.toNamed(Routes.payment, arguments: { + 'productId': item.productId, + 'amount': item.price, + 'description': item.title, + }); + } +} \ No newline at end of file diff --git a/lib/modules/goods/views/goodsai_view.dart b/lib/modules/goods/views/goodsai_view.dart new file mode 100644 index 000000000..d362fedd3 --- /dev/null +++ b/lib/modules/goods/views/goodsai_view.dart @@ -0,0 +1,131 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import '../controllers/goodsai_controller.dart'; + +class GoodsaiView extends GetView { + const GoodsaiView({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, + title: Text( + 'aiFunction'.tr, + style: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + ), + ), + centerTitle: true, + ), + body: Obx(() { + 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, + separatorBuilder: (_, __) => SizedBox(height: 12.h), + itemBuilder: (_, index) { + final item = controller.items[index]; + return _buildCard(item, isDarkMode); + }, + ); + }), + ); + } + + Widget _buildCard(AIItem 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.teal[900]!.withOpacity(0.3) + : Colors.teal[100]!, + borderRadius: BorderRadius.circular(21.r), + ), + child: Icon(Icons.auto_awesome, + color: + isDarkMode ? Colors.teal[300]! : Colors.teal[600]!), + ), + SizedBox(width: 12.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(item.title, + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + )), + SizedBox(height: 4.h), + Text(item.description, + style: TextStyle( + fontSize: 12.sp, + color: + isDarkMode ? Colors.white70 : Colors.grey[600], + )), + ], + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('¥${item.price.toStringAsFixed(2)}', + 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( + '购买', + style: TextStyle(fontSize: 12.sp, color: Colors.white), + ), + ), + ), + ], + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/modules/goods/views/goodsmeet_view.dart b/lib/modules/goods/views/goodsmeet_view.dart new file mode 100644 index 000000000..6eb214d58 --- /dev/null +++ b/lib/modules/goods/views/goodsmeet_view.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import '../controllers/goodsmeet_controller.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, + title: Text( + 'conferenceAssistant'.tr, + style: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + ), + ), + centerTitle: true, + ), + body: Obx(() { + 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, + separatorBuilder: (_, __) => SizedBox(height: 12.h), + itemBuilder: (_, index) { + final item = controller.items[index]; + return _buildCard(item, isDarkMode); + }, + ); + }), + ); + } + + Widget _buildCard(MeetItem 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(item.title, + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + )), + SizedBox(height: 4.h), + Text(item.description, + style: TextStyle( + fontSize: 12.sp, + color: + isDarkMode ? Colors.white70 : Colors.grey[600], + )), + ], + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('¥${item.price.toStringAsFixed(2)}', + 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( + '购买', + style: TextStyle(fontSize: 12.sp, color: Colors.white), + ), + ), + ), + ], + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/modules/goods/views/goodstrade_view.dart b/lib/modules/goods/views/goodstrade_view.dart new file mode 100644 index 000000000..b410c03b6 --- /dev/null +++ b/lib/modules/goods/views/goodstrade_view.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import '../controllers/goodstrade_controller.dart'; + +class GoodstradeView extends GetView { + const GoodstradeView({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, + title: Text( + 'simultaneousTranslation'.tr, + style: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + ), + ), + centerTitle: true, + ), + body: Obx(() { + 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, + separatorBuilder: (_, __) => SizedBox(height: 12.h), + itemBuilder: (_, index) { + final item = controller.items[index]; + return _buildCard(item, isDarkMode); + }, + ); + }), + ); + } + + Widget _buildCard(TradeItem 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.indigo[900]!.withOpacity(0.3) + : Colors.indigo[100]!, + borderRadius: BorderRadius.circular(21.r), + ), + child: Icon(Icons.translate, + color: isDarkMode + ? Colors.indigo[300]! + : Colors.indigo[600]!), + ), + SizedBox(width: 12.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(item.title, + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + )), + SizedBox(height: 4.h), + Text(item.description, + style: TextStyle( + fontSize: 12.sp, + color: + isDarkMode ? Colors.white70 : Colors.grey[600], + )), + ], + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('¥${item.price.toStringAsFixed(2)}', + 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( + '购买', + style: TextStyle(fontSize: 12.sp, color: Colors.white), + ), + ), + ), + ], + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/modules/goods/views/goodsvip_view.dart b/lib/modules/goods/views/goodsvip_view.dart new file mode 100644 index 000000000..dc3067191 --- /dev/null +++ b/lib/modules/goods/views/goodsvip_view.dart @@ -0,0 +1,137 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import '../controllers/goodsvip_controller.dart'; + +class GoodsvipView extends GetView { + const GoodsvipView({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, + title: Text( + 'premiumMember'.tr, // 高级会员 + style: TextStyle( + fontSize: 18.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + ), + ), + centerTitle: true, + ), + body: Obx(() { + 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, + separatorBuilder: (_, __) => + SizedBox(height: 12.h), + itemBuilder: (_, index) { + final item = controller.items[index]; + return _buildGoodsCard(item, isDarkMode); + }, + ); + }), + ); + } + + Widget _buildGoodsCard(GoodsItem 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.amber[900]!.withOpacity(0.3) + : Colors.amber[100]!, + borderRadius: BorderRadius.circular(21.r), + ), + child: Icon(Icons.workspace_premium, + color: isDarkMode + ? Colors.amber[300]! + : Colors.amber[600]!), + ), + SizedBox(width: 12.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(item.title, + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w600, + color: isDarkMode ? Colors.white : Colors.black, + )), + SizedBox(height: 4.h), + Text(item.description, + style: TextStyle( + fontSize: 12.sp, + color: + isDarkMode ? Colors.white70 : Colors.grey[600], + )), + ], + ), + ), + SizedBox(width: 12.w), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('¥${item.price.toStringAsFixed(2)}', + 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( + '购买', + style: TextStyle( + fontSize: 12.sp, + color: Colors.white, + ), + ), + ), + ), + ], + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/modules/settings/views/settings_view.dart b/lib/modules/settings/views/settings_view.dart index 81a017434..a94493ef4 100644 --- a/lib/modules/settings/views/settings_view.dart +++ b/lib/modules/settings/views/settings_view.dart @@ -40,6 +40,8 @@ class SettingsView extends GetView { padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), children: [ _buildUserInfoCard(isDarkMode), + SizedBox(height: 20.h), + _buildVipPurchaseCard(isDarkMode), // SizedBox(height: 20.h), // _buildAISettingsSection(isDarkMode), SizedBox(height: 20.h), @@ -215,6 +217,121 @@ class SettingsView extends GetView { ); } + // 构建Vip购买卡片 + Widget _buildVipPurchaseCard(bool isDarkMode) { + return Container( + padding: EdgeInsets.all(16.w), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: isDarkMode + ? [ + const Color(0xFF4A148C).withOpacity(0.7), + const Color(0xFFAD1457).withOpacity(0.7) + ] + : [const Color(0xFFF8BBD0), const Color(0xFFE1BEE7)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + borderRadius: BorderRadius.circular(16.r), + boxShadow: [ + BoxShadow( + color: isDarkMode + ? Colors.black.withOpacity(0.2) + : Colors.black.withOpacity(0.05), + blurRadius: 10, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _buildCategoryItem( + icon: Icons.workspace_premium, + label: 'Vip', + iconBg: isDarkMode + ? Colors.amber[900]!.withOpacity(0.3) + : Colors.amber[100]!, + iconColor: isDarkMode ? Colors.amber[300]! : Colors.amber[600]!, + onTap: () => Get.toNamed(Routes.goodsvip), + ), + _buildCategoryItem( + icon: Icons.translate, + label: 'Translation', + iconBg: isDarkMode + ? Colors.indigo[900]!.withOpacity(0.3) + : Colors.indigo[100]!, + iconColor: isDarkMode ? Colors.indigo[300]! : Colors.indigo[600]!, + onTap: () => Get.toNamed(Routes.goodstrade), + ), + _buildCategoryItem( + icon: Icons.people_alt, + label: "Meet", + iconBg: isDarkMode + ? Colors.pink[900]!.withOpacity(0.3) + : Colors.pink[100]!, + iconColor: isDarkMode ? Colors.pink[300]! : Colors.pink[600]!, + onTap: () => Get.toNamed(Routes.goodsmeet), + ), + _buildCategoryItem( + icon: Icons.auto_awesome, + label: "AI", + iconBg: isDarkMode + ? Colors.teal[900]!.withOpacity(0.3) + : Colors.teal[100]!, + iconColor: isDarkMode ? Colors.teal[300]! : Colors.teal[600]!, + onTap: () => Get.toNamed(Routes.goodsai), + ), + ], + ), + ); + } + + Widget _buildCategoryItem({ + required IconData icon, + required String label, + required Color iconBg, + required Color iconColor, + required VoidCallback onTap, + }) { + return InkWell( + onTap: onTap, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 42.w, + height: 42.w, + decoration: BoxDecoration( + color: iconBg, + borderRadius: BorderRadius.circular(21.r), + ), + child: Icon( + icon, + size: 20.w, + color: iconColor, + ), + ), + SizedBox(height: 8.h), + SizedBox( + width: 72.w, + child: Text( + label, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12.sp, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ); + } + // AI设置 Widget _buildAISettingsSection(bool isDarkMode) { return Column( diff --git a/lib/routes/app_pages.dart b/lib/routes/app_pages.dart index f16b5c0a3..1738a207f 100644 --- a/lib/routes/app_pages.dart +++ b/lib/routes/app_pages.dart @@ -1,5 +1,4 @@ import 'package:get/get.dart'; -import 'package:qq_music/qq_music.dart'; import 'package:voitrans/modules/qqmusic/bindings/qqmusic_playlist_binding.dart'; import 'package:voitrans/modules/qqmusic/views/qqmusic_playlist_view.dart'; @@ -71,6 +70,14 @@ import '../modules/text_translation/bindings/text_translation_binding.dart'; import '../modules/text_translation/views/text_translation_view.dart'; import '../modules/picture_translation/views/picture_translation_view.dart'; import '../modules/picture_translation/bindings/picture_translation_binding.dart'; +import '../modules/goods/bindings/goodsvip_binding.dart'; +import '../modules/goods/views/goodsvip_view.dart'; +import '../modules/goods/bindings/goodstrade_binding.dart'; +import '../modules/goods/views/goodstrade_view.dart'; +import '../modules/goods/bindings/goodsmeet_binding.dart'; +import '../modules/goods/views/goodsmeet_view.dart'; +import '../modules/goods/bindings/goodsai_binding.dart'; +import '../modules/goods/views/goodsai_view.dart'; abstract class AppPages { static final pages = [ @@ -324,5 +331,33 @@ abstract class AppPages { transition: Transition.rightToLeft, transitionDuration: Duration(milliseconds: 250), ), + GetPage( + name: Routes.goodsvip, + page: () => const GoodsvipView(), + binding: GoodsvipBinding(), + transition: Transition.rightToLeft, + transitionDuration: Duration(milliseconds: 250), + ), + GetPage( + name: Routes.goodstrade, + page: () => const GoodstradeView(), + binding: GoodstradeBinding(), + transition: Transition.rightToLeft, + transitionDuration: Duration(milliseconds: 250), + ), + GetPage( + name: Routes.goodsmeet, + page: () => const GoodsmeetView(), + binding: GoodsmeetBinding(), + transition: Transition.rightToLeft, + transitionDuration: Duration(milliseconds: 250), + ), + GetPage( + name: Routes.goodsai, + page: () => const GoodsaiView(), + binding: GoodsaiBinding(), + transition: Transition.rightToLeft, + transitionDuration: Duration(milliseconds: 250), + ), ]; } diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index b513e0369..c964ffb57 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -69,4 +69,10 @@ abstract class Routes { // 支付相关 static const payment = '/payment'; // 支付测试页面 + + //商品购买页面 + static const goodsvip = '/goodsvip'; //vip商品页面 + static const goodstrade = '/goodstrade'; //翻译商品页面 + static const goodsmeet = '/goodsmeet'; //会议商品页面 + static const goodsai = '/goodsai'; //ai商品页面 }