diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a2ad459..4a34cf8 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ + educationCodeMap = { + '大专以下': '0', + '大专': '1', + '本科': '2', + '硕士及以上': '3', + }; // UserApi实例 late UserApi _userApi; @@ -221,12 +228,7 @@ class UserInfoController extends GetxController { } // 学历代码映射 - Map educationCodeMap = { - '大专以下': '0', - '大专': '1', - '本科': '2', - '硕士及以上': '3', - }; + return { 'birthYear': birthYear, @@ -243,18 +245,13 @@ class UserInfoController extends GetxController { if (!_validateForm()) { return; } - isSubmitting.value = true; - try { - - // 构建请求参数 final params = _buildSubmitParams(); if (avatarUrl.value.isNotEmpty) { params['avatarUrl'] = avatarUrl.value; } - // 打印提交的信息 print('提交用户信息参数: $params'); @@ -264,40 +261,17 @@ class UserInfoController extends GetxController { // 处理响应 if (response.data.isSuccess) { // 获取 miId(资料id) - String miId = ''; - final regData = response.data.data; - if (regData != null) { - miId = regData; - await storage.write('miId', miId); - } else { - // 尝试从本地存储获取 - final stored = storage.read('miId'); - if (stored is String && stored.isNotEmpty) { - miId = stored; - } else { - SmartDialog.showToast('获取资料ID失败,请重试'); - return; - } - } - + String miId = response.data.data; // 先调用认证审核保存接口(保存头像,authenticationCode=8) try { - final payload = { - 'miId': miId, - 'authenticationCode': '8', - 'value': '0', - 'imgUrl': avatarUrl.value.isNotEmpty ? [avatarUrl.value] : ['0'], - }; - - final auditResp = await _userApi.saveCertificationAudit(payload); - if (auditResp.data.isSuccess) { - - } - else{ - - SmartDialog.showToast(auditResp.data.message); - - return; + if(avatarUrl.value.isNotEmpty){ + final payload = { + 'miId': miId, + 'authenticationCode': '8', + 'value': '0', + 'imgUrl': avatarUrl.value.isNotEmpty ? [avatarUrl.value] : ['0'], + }; + await _userApi.saveCertificationAudit(payload); } } catch (e) { print('保存认证审核失败: $e'); @@ -306,23 +280,21 @@ class UserInfoController extends GetxController { } // 更新本地存储的用户信息 - final currentUserInfo = storage.read('userInfo') ?? {}; - if (currentUserInfo is Map) { - currentUserInfo.addAll({ - 'gender': gender.value, - 'nickname': nickname.value, - 'birthday': birthday.value, - 'education': education.value, - 'avatarUrl': avatarUrl.value, - }); - await storage.write('userInfo', currentUserInfo); - } - + GlobalData().userData!.id = miId; + + final genderCode = gender.value == 'male' ? 0 : 1;// 1:男, 2:女 + GlobalData().userData!.genderCode = genderCode; + GlobalData().userData!.nickName = nickname.value; + GlobalData().userData!.profilePhoto = avatarUrl.value; + GlobalData().userData!.education = education.value; + final code = educationCodeMap[education.value] ?? '0'; + GlobalData().userData!.educationCode = int.parse(code); // 显示成功提示 - SmartDialog.showToast('信息提交成功!'); - + SmartDialog.showToast('信息提交成功'); // 延迟后跳转 - Future.delayed(const Duration(milliseconds: 1500), () { + // await storage.write('token', GlobalData().qnToken); + await storage.write('userId', GlobalData().userId); + Future.delayed(const Duration(milliseconds: 100), () { // 跳转到主页面(根据登录流程,应该跳转到MainPage) Get.offAll(() => MainPage()); }); diff --git a/lib/controller/setting/notification_controller.dart b/lib/controller/setting/notification_controller.dart new file mode 100644 index 0000000..057111c --- /dev/null +++ b/lib/controller/setting/notification_controller.dart @@ -0,0 +1,103 @@ +// controllers/notification_controller.dart +import 'package:get/get.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:app_settings/app_settings.dart'; + +class NotificationController extends GetxController { + // 权限状态 + final Rx notificationStatus = PermissionStatus.denied.obs; + final RxBool checking = false.obs; + + // 初始化时检查权限 + @override + void onInit() { + super.onInit(); + // 延迟检查,确保服务已初始化 + checkPermission(); + } + + // 检查通知权限状态 + Future checkPermission() async { + checking.value = true; + try { + // 检查通知权限 + final status = await Permission.notification.status; + notificationStatus.value = status; + + print('通知权限状态: $status'); + return status; + } catch (e) { + print('检查通知权限失败: $e'); + return PermissionStatus.denied; + } finally { + checking.value = false; + } + } + + // 请求通知权限 + Future requestNotificationPermission() async { + try { + final status = await Permission.notification.request(); + notificationStatus.value = status; + + print('请求通知权限结果: $status'); + return status; + } catch (e) { + print('请求通知权限失败: $e'); + return PermissionStatus.denied; + } + } + + // 打开应用设置页面(让用户手动开启权限) + Future openSettings() async { + try { + AppSettings.openAppSettings( + type: AppSettingsType.notification, + ); + } catch (e) { + print('打开设置页面失败: $e'); + } + } + + // 检查是否有通知权限的便捷方法 + // Future hasNotificationPermission() async { + // final status = await checkNotificationPermission(); + // return status.isGranted || status.isLimited; + // } + + // 获取权限状态描述 + String getPermissionStatusText() { + switch (notificationStatus.value) { + case PermissionStatus.granted: + return '已开启'; + case PermissionStatus.denied: + return '已拒绝'; + case PermissionStatus.restricted: + return '受限制'; + case PermissionStatus.limited: + return '部分授权'; + case PermissionStatus.permanentlyDenied: + return '永久拒绝'; + case PermissionStatus.provisional: + return '临时授权'; + } + } + + // 获取权限状态颜色 + String getPermissionStatusColor() { + switch (notificationStatus.value) { + case PermissionStatus.granted: + return '绿色'; + case PermissionStatus.denied: + return '橙色'; + case PermissionStatus.restricted: + return '红色'; + case PermissionStatus.limited: + return '蓝色'; + case PermissionStatus.permanentlyDenied: + return '红色'; + case PermissionStatus.provisional: + return '黄色'; + } + } +} \ No newline at end of file diff --git a/lib/controller/setting/setting_controller.dart b/lib/controller/setting/setting_controller.dart new file mode 100644 index 0000000..6e2dd9b --- /dev/null +++ b/lib/controller/setting/setting_controller.dart @@ -0,0 +1,230 @@ +import 'dart:async'; +import 'package:dating_touchme_app/controller/global.dart'; +import 'package:dating_touchme_app/extension/ex_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; +import '../../generated/assets.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +class SettingController extends GetxController { + + final storage = GetStorage(); + final appName = ''.obs; + final packageName = ''.obs; + final version = ''.obs; + final buildNumber = ''.obs; + + @override + Future onInit() async { + super.onInit(); + // 从全局依赖中获取UserApi + await getAppInfo(); + } + // 获取验证码 + Future getAppInfo() async { + try { + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + appName.value = packageInfo.appName; + packageName.value = packageInfo.packageName; + version.value = packageInfo.version; + buildNumber.value = packageInfo.buildNumber; + } catch (e) { + print('获取应用信息失败: $e'); + } + } + + Future checkVersion() async { + try { + _showUpdateDialog(); + } catch (e) { + print('检测版本跟新失败: $e'); + } + } + + void logout(){ + storage.erase(); + GlobalData().logout(); + } + + // 弹出版本升级的dialog + void _showUpdateDialog(){ + Navigator.of(Get.context!).push(TDSlidePopupRoute( + modalBarrierColor: TDTheme.of(Get.context!).fontGyColor2, + slideTransitionFrom: SlideTransitionFrom.center, + builder: (context) { + return Material( + color: Colors.transparent, + child: Container( + color: Colors.transparent, + width: 299.w, + padding: EdgeInsets.only(top: 56.w), + child: Stack( + clipBehavior: Clip.none, + children: [ + Container( + width: 299.w, + padding: EdgeInsets.only( + top: 147.w, + left: 30.w, + right: 30.w, + bottom: 25.w + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(18.w)), + color: Colors.white + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "体验全新升级v1.2.0", + style: TextStyle( + fontSize: 16.w, + fontWeight: FontWeight.w500 + ), + ), + SizedBox(height: 14.w,), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 2.w, + height: 5.w, + margin: EdgeInsets.only( + right: 10.w, + top: 6.w + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(2.w)), + color: const Color.fromRGBO(51, 51, 51, 1) + ), + ), + SizedBox( + width: 204.w, + child: Text( + "首页风格改版,更全面的内容,恍然一新的视觉用户体验。", + style: TextStyle( + fontSize: 12.w, + ), + ), + ) + ], + ), + SizedBox(height: 8.w,), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 2.w, + height: 5.w, + margin: EdgeInsets.only( + right: 10.w, + top: 6.w + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(2.w)), + color: const Color.fromRGBO(51, 51, 51, 1) + ), + ), + SizedBox( + width: 204.w, + child: Text( + "优化了动画细节,让产品更流畅。", + style: TextStyle( + fontSize: 12.w, + ), + ), + ) + ], + ), + SizedBox(height: 32.w,), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 113.w, + height: 40.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + color: const Color.fromRGBO(245, 245, 245, 1) + ), + child: Center( + child: Text( + "暂不更新", + style: TextStyle( + fontSize: 15.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ), + ), + ).onTap((){ + Navigator.of(context).pop(); + }), + Container( + width: 113.w, + height: 40.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + color: const Color.fromRGBO(245, 245, 245, 1), + gradient: const LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, // 对应 CSS 90deg + colors: [ + Color.fromRGBO(131, 89, 255, 1), // rgba(131, 89, 255, 1) + Color.fromRGBO(61, 138, 224, 1), // rgba(61, 138, 224, 1) + ], + ), + ), + child: Center( + child: Text( + "立即升级", + style: TextStyle( + fontSize: 15.w, + fontWeight: FontWeight.w500, + color: Colors.white + ), + ), + ), + ), + ], + ) + ], + ), + ), + Positioned( + left: 0, + top: -56.w, + child: Image.asset( + Assets.imagesUpdataBg, + width: 299.w, + ), + ), + Positioned( + left: 11.w, + top: -14.w, + child: Image.asset( + Assets.imagesUpdataIcon, + width: 36.w, + ), + ), + Positioned( + left: 43.w, + top: 29.w, + child: Image.asset( + Assets.imagesUpdataFont, + width: 76.w, + ), + ) + ], + ), + ), + ); + })); + } + +} + diff --git a/lib/main.dart b/lib/main.dart index 265b61e..ef1113c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -84,10 +84,10 @@ class MyApp extends StatelessWidget { // 判断token是否为空 final storage = GetStorage(); - final token = storage.read('token'); + final userId = storage.read('userId'); // 如果token不为空,显示主页;如果token为空,显示登录页面 - if (token != null && token.isNotEmpty) { + if (userId != null && userId.isNotEmpty) { return MainPage(); } else { return LoginPage(); diff --git a/lib/model/mine/user_data.dart b/lib/model/mine/user_data.dart index 65b50f3..d0cdd1c 100644 --- a/lib/model/mine/user_data.dart +++ b/lib/model/mine/user_data.dart @@ -1,11 +1,11 @@ // 用户详细信息实体类 class UserData { - final String? id; - final String? nickName; + String? id; + String? nickName; final String? name; - final String? profilePhoto; + String? profilePhoto; String? identityCard; - final int? genderCode; + int? genderCode; final String? genderValue; final String? homeCountryCode; final String? homeCountry; @@ -23,8 +23,8 @@ class UserData { final String? chineseZodiac; final int? height; final int? weight; - final int? educationCode; - final String? education; + int? educationCode; + String? education; final int? maritalStatusCode; final String? maritalStatusName; final int? minimumIncome; diff --git a/lib/network/network_config.dart b/lib/network/network_config.dart index 58f0e53..c892bf5 100644 --- a/lib/network/network_config.dart +++ b/lib/network/network_config.dart @@ -83,7 +83,6 @@ class ResponseInterceptor extends Interceptor { ) { // 统一处理响应数据 final data = response.data; - // 检查响应状态码 if (response.statusCode == 200) { // 假设后端返回的数据格式为 {"code": 0, "message": "success", "data": {...}} diff --git a/lib/pages/home/report_page.dart b/lib/pages/home/report_page.dart index 6a19b8a..9403d74 100644 --- a/lib/pages/home/report_page.dart +++ b/lib/pages/home/report_page.dart @@ -23,7 +23,7 @@ class _ReportPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: PageAppbar(title: "举报中心",), + appBar: PageAppbar(title: "举报中心"), body: SingleChildScrollView( child: Container( padding: EdgeInsets.only( diff --git a/lib/pages/mine/auth_center_page.dart b/lib/pages/mine/auth_center_page.dart index 188a73b..7b59cb0 100644 --- a/lib/pages/mine/auth_center_page.dart +++ b/lib/pages/mine/auth_center_page.dart @@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import '../../components/page_appbar.dart'; import '../../controller/mine/auth_controller.dart'; import '../../extension/router_service.dart'; import '../../generated/assets.dart'; @@ -18,10 +19,7 @@ class AuthCenterPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xffF5F5F5), - appBar: AppBar( - title: Text('认证中心', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - centerTitle: true, - ), + appBar: PageAppbar(title: "认证中心"), body: Obx(() { if (controller.isLoading.value) { return const Center(child: CupertinoActivityIndicator(radius: 12,)); diff --git a/lib/pages/mine/login_controller.dart b/lib/pages/mine/login_controller.dart deleted file mode 100644 index ba34f49..0000000 --- a/lib/pages/mine/login_controller.dart +++ /dev/null @@ -1,174 +0,0 @@ -// import 'dart:async'; -// import 'package:dating_touchme_app/pages/main/main_page.dart'; -// import 'package:get/get.dart'; -// import 'package:get_storage/get_storage.dart'; -// import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; -// import 'package:dating_touchme_app/network/user_api.dart'; -// import 'package:dating_touchme_app/pages/mine/user_info_page.dart'; -// -// -// class LoginController extends GetxController { -// // 手机号输入 -// final phoneNumber = ''.obs; -// // 验证码输入 -// final verificationCode = ''.obs; -// // 是否正在发送验证码 -// final isSendingCode = false.obs; -// // 倒计时秒数 -// final countdownSeconds = 0.obs; -// // 是否正在登录中 -// final isLoggingIn = false.obs; -// -// // 从GetX依赖注入中获取UserApi实例 -// late UserApi _userApi; -// // GetStorage实例,用于存储token等信息 -// final storage = GetStorage(); -// -// @override -// void onInit() { -// super.onInit(); -// // 从全局依赖中获取UserApi -// _userApi = Get.find(); -// } -// -// // 获取验证码 -// Future getVerificationCode() async { -// // 验证手机号格式 -// if (phoneNumber.value.isEmpty || phoneNumber.value.length != 11) { -// SmartDialog.showToast('请输入正确的手机号'); -// return; -// } -// -// isSendingCode.value = true; -// -// try { -// // 构建请求参数 -// final params = { -// 'purpose': 1, // 认证 -// 'verifiableAccount': phoneNumber.value, -// 'verifiableAccountType': 1, // 手机 -// }; -// -// // 调用UserApi中的验证码接口 -// final response = await _userApi.getVerificationCode(params); -// -// // 处理响应 -// if (response.data.isSuccess) { -// // 生产环境移除打印,可考虑使用正式的日志框架 -// // print('验证码发送成功'); -// // 开始倒计时 -// startCountdown(); -// } else { -// SmartDialog.showToast(response.data.message); -// } -// } catch (e) { -// SmartDialog.showToast('网络请求失败,请重试'); -// } finally { -// isSendingCode.value = false; -// } -// } -// -// // 开始倒计时 -// void startCountdown() { -// countdownSeconds.value = 60; -// Timer.periodic(const Duration(seconds: 1), (timer) { -// countdownSeconds.value--; -// if (countdownSeconds.value <= 0) { -// timer.cancel(); -// } -// }); -// } -// -// // 清除错误信息 - 由于使用SmartDialog,此方法不再需要 -// // void clearErrorMessage() {} -// -// -// // 登录方法 -// Future login() async { -// // 验证输入 -// if (phoneNumber.value.isEmpty || phoneNumber.value.length != 11) { -// SmartDialog.showToast('请输入正确的手机号'); -// return; -// } -// -// if (verificationCode.value.isEmpty) { -// SmartDialog.showToast('请输入验证码'); -// return; -// } -// -// isLoggingIn.value = true; -// -// try { -// // 构建登录请求参数 -// final params = { -// 'account': phoneNumber.value, -// 'accountType': 2, // 手机号类型 -// 'captcha': verificationCode.value, -// }; -// -// // 调用登录接口 -// final response = await _userApi.login(params); -// -// // 处理响应 -// if (response.data.isSuccess) { -// // 保存token和用户信息 -// if (response.data.data != null) { -// final loginData = response.data.data!; -// await storage.write('token', loginData.token); -// await storage.write('userId', loginData.userId); -// // 保存用户信息 -// await storage.write('userInfo', loginData.toJson()); -// -// // 登录成功后获取用户基础信息 -// await _getBaseUserInfo(loginData.userId); -// } -// } else { -// SmartDialog.showToast(response.data.message); -// } -// } catch (e) { -// SmartDialog.showToast('网络请求失败,请检查网络连接'); -// } finally { -// isLoggingIn.value = false; -// } -// } -// -// // 获取用户基础信息 -// Future _getBaseUserInfo(String userId) async { -// try { -// final response = await _userApi.getBaseUserInfo(userId); -// -// if (response.data.isSuccess && response.data.data != null) { -// // 成功获取基础信息后,调用获取婚姻信息详情接口 -// await _getMarriageInformationDetail(); -// } else { -// SmartDialog.showToast(response.data.message); -// } -// } catch (e) { -// // 获取用户信息失败不影响登录流程 -// SmartDialog.showToast('获取用户信息失败'); -// } -// } -// -// // 获取用户婚姻信息详情 -// Future _getMarriageInformationDetail() async { -// try { -// final response = await _userApi.getMarriageInformationDetail(); -// if (response.data.isSuccess) { -// // 检查data是否为null或者是空对象 -// if(response.data.data == null){ -// //跳转到完善信息 -// SmartDialog.showToast('转到完善信息'); -// // 导航到完善信息页面 -// Get.offAll(() => UserInfoPage()); -// }else{ -// Get.offAll(MainPage()); -// } -// } else { -// // 获取婚姻信息失败不影响登录流程 -// } -// } catch (e) { -// // 获取婚姻信息失败不影响登录流程 -// print('获取婚姻信息异常: $e'); -// } -// } -// } \ No newline at end of file diff --git a/lib/pages/mine/mine_page.dart b/lib/pages/mine/mine_page.dart index ab463bd..4c59793 100644 --- a/lib/pages/mine/mine_page.dart +++ b/lib/pages/mine/mine_page.dart @@ -1,3 +1,4 @@ +import 'package:cached_network_image/cached_network_image.dart'; import 'package:dating_touchme_app/controller/mine/mine_controller.dart'; import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:dating_touchme_app/pages/mine/edit_info_page.dart'; @@ -6,9 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:dating_touchme_app/generated/assets.dart'; import 'package:get/get.dart'; -import 'package:get_storage/get_storage.dart'; -import '../../extension/router_service.dart'; import '../discover/visitor_list_page.dart'; class MinePage extends StatefulWidget { @@ -80,7 +79,7 @@ class _MinePageState extends State with AutomaticKeepAliveClientMixin{ Assets.imagesUserAvatar, width: 60.w, height: 60.w, - ), + ) ), SizedBox(width: 14.w,), Column( diff --git a/lib/pages/mine/phone_page.dart b/lib/pages/mine/phone_page.dart index e602a6c..117c3fa 100644 --- a/lib/pages/mine/phone_page.dart +++ b/lib/pages/mine/phone_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; +import '../../components/page_appbar.dart'; import '../../controller/mine/phone_controller.dart'; class PhonePage extends StatelessWidget { @@ -13,10 +14,7 @@ class PhonePage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xffFFFFFF), - appBar: AppBar( - title: Text('手机认证', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - centerTitle: true, - ), + appBar: PageAppbar(title: "手机认证", bottom: true), body: Obx(() { return IndexedStack( index: controller.tabIndex.value, diff --git a/lib/pages/mine/real_name_page.dart b/lib/pages/mine/real_name_page.dart index a45e396..9aa3bd2 100644 --- a/lib/pages/mine/real_name_page.dart +++ b/lib/pages/mine/real_name_page.dart @@ -4,6 +4,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; +import '../../components/page_appbar.dart'; import '../../controller/mine/auth_controller.dart'; class RealNamePage extends StatelessWidget { @@ -14,10 +15,7 @@ class RealNamePage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xffFFFFFF), - appBar: AppBar( - title: Text('实名认证', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - centerTitle: true, - ), + appBar: PageAppbar(title: "实名认证"), body: Column( children: [ Container( diff --git a/lib/pages/mine/setting_page.dart b/lib/pages/mine/setting_page.dart deleted file mode 100644 index fb22e17..0000000 --- a/lib/pages/mine/setting_page.dart +++ /dev/null @@ -1,410 +0,0 @@ -import 'package:dating_touchme_app/components/page_appbar.dart'; -import 'package:dating_touchme_app/extension/ex_widget.dart'; -import 'package:dating_touchme_app/generated/assets.dart'; -import 'package:dating_touchme_app/pages/mine/blacklist_page.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:get/get.dart'; -import 'package:get/get_core/src/get_main.dart'; -import 'package:tdesign_flutter/tdesign_flutter.dart'; - -class SettingPage extends StatefulWidget { - const SettingPage({super.key}); - - @override - State createState() => _SettingPageState(); -} - -class _SettingPageState extends State { - - - bool blockUser = false; - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: const Color.fromRGBO(250, 250, 250, 1), - appBar: PageAppbar(title: "设置"), - body: SingleChildScrollView( - child: Container( - padding: EdgeInsets.symmetric( - vertical: 15.w, - horizontal: 10.w - ), - child: Column( - children: [ - BlockItem( - children: [ - Item( - label: "后台播放", - child: TDSwitch( - isOn: blockUser, - trackOnColor: const Color.fromRGBO(117, 98, 249, 1), - onChanged: (bool e){ - print(e); - blockUser = e; - setState(() { - - }); - return e; - }, - ), - ), - LineItem(), - Item( - label: "语音/视频通话提示音", - child: TDSwitch( - isOn: blockUser, - trackOnColor: const Color.fromRGBO(117, 98, 249, 1), - onChanged: (bool e){ - print(e); - blockUser = e; - setState(() { - - }); - return e; - }, - ), - ), - ], - ), - BlockItem( - children: [ - Item( - label: "安全中心", - child: Icon( - Icons.keyboard_arrow_right, - size: 10.w, - color: const Color.fromRGBO(191, 191, 191, 1), - ), - ), - LineItem(), - Item( - label: "黑名单", - child: Icon( - Icons.keyboard_arrow_right, - size: 10.w, - color: const Color.fromRGBO(191, 191, 191, 1), - ), - ).onTap((){ - Get.to(() => BlacklistPage()); - }), - ], - ), - BlockItem( - children: [ - Item( - label: "隐私设置", - child: Icon( - Icons.keyboard_arrow_right, - size: 10.w, - color: const Color.fromRGBO(191, 191, 191, 1), - ), - ), - LineItem(), - Item( - label: "青少年模式", - child: Icon( - Icons.keyboard_arrow_right, - size: 10.w, - color: const Color.fromRGBO(191, 191, 191, 1), - ), - ), - ], - ), - BlockItem( - children: [ - Item( - label: "系统权限管理", - child: Icon( - Icons.keyboard_arrow_right, - size: 10.w, - color: const Color.fromRGBO(191, 191, 191, 1), - ), - ), - LineItem(), - Item( - label: "消息通知", - child: Icon( - Icons.keyboard_arrow_right, - size: 10.w, - color: const Color.fromRGBO(191, 191, 191, 1), - ), - ), - LineItem(), - Item( - label: "检查更新", - child: Row( - children: [ - Text( - "版本号 1.0.000", - style: TextStyle( - fontSize: 13.w, - color: const Color.fromRGBO(117, 98, 249, 1) - ), - ), - SizedBox(width: 10.w,), - Icon( - Icons.keyboard_arrow_right, - size: 10.w, - color: const Color.fromRGBO(191, 191, 191, 1), - ) - ], - ), - ).onTap((){ - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.center, - builder: (context) { - return Material( - color: Colors.transparent, - child: Container( - color: Colors.transparent, - width: 299.w, - padding: EdgeInsets.only( - top: 56.w - ), - child: Stack( - clipBehavior: Clip.none, - children: [ - Container( - width: 299.w, - padding: EdgeInsets.only( - top: 147.w, - left: 30.w, - right: 30.w, - bottom: 25.w - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(18.w)), - color: Colors.white - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - "体验全新升级v1.2.0", - style: TextStyle( - fontSize: 16.w, - fontWeight: FontWeight.w500 - ), - ), - SizedBox(height: 14.w,), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 2.w, - height: 5.w, - margin: EdgeInsets.only( - right: 10.w, - top: 6.w - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(2.w)), - color: const Color.fromRGBO(51, 51, 51, 1) - ), - ), - SizedBox( - width: 204.w, - child: Text( - "首页风格改版,更全面的内容,恍然一新的视觉用户体验。", - style: TextStyle( - fontSize: 12.w, - ), - ), - ) - ], - ), - SizedBox(height: 8.w,), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 2.w, - height: 5.w, - margin: EdgeInsets.only( - right: 10.w, - top: 6.w - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(2.w)), - color: const Color.fromRGBO(51, 51, 51, 1) - ), - ), - SizedBox( - width: 204.w, - child: Text( - "优化了动画细节,让产品更流畅。", - style: TextStyle( - fontSize: 12.w, - ), - ), - ) - ], - ), - SizedBox(height: 32.w,), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - width: 113.w, - height: 40.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(9.w)), - color: const Color.fromRGBO(245, 245, 245, 1) - ), - child: Center( - child: Text( - "暂不更新", - style: TextStyle( - fontSize: 15.w, - color: const Color.fromRGBO(144, 144, 144, 1) - ), - ), - ), - ), - Container( - width: 113.w, - height: 40.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(9.w)), - color: const Color.fromRGBO(245, 245, 245, 1), - gradient: const LinearGradient( - begin: Alignment.centerLeft, - end: Alignment.centerRight, // 对应 CSS 90deg - colors: [ - Color.fromRGBO(131, 89, 255, 1), // rgba(131, 89, 255, 1) - Color.fromRGBO(61, 138, 224, 1), // rgba(61, 138, 224, 1) - ], - ), - ), - child: Center( - child: Text( - "立即升级", - style: TextStyle( - fontSize: 15.w, - fontWeight: FontWeight.w500, - color: Colors.white - ), - ), - ), - ), - ], - ) - ], - ), - ), - Positioned( - left: 0, - top: -56.w, - child: Image.asset( - Assets.imagesUpdataBg, - width: 299.w, - ), - ), - Positioned( - left: 11.w, - top: -14.w, - child: Image.asset( - Assets.imagesUpdataIcon, - width: 36.w, - ), - ), - Positioned( - left: 43.w, - top: 29.w, - child: Image.asset( - Assets.imagesUpdataFont, - width: 76.w, - ), - ) - ], - ), - ), - ); - })); - }), - ], - ), - ], - ), - ), - ), - ); - } -} - -class BlockItem extends StatefulWidget { - final List children; - const BlockItem({super.key, required this.children}); - - @override - State createState() => _BlockItemState(); -} - -class _BlockItemState extends State { - @override - Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.symmetric( - horizontal: 14.w - ), - margin: EdgeInsets.only( - bottom: 10.w - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(9.w)), - color: Colors.white - ), - child: Column( - children: widget.children, - ), - ); - } -} - -class Item extends StatefulWidget { - final String label; - final Widget child; - const Item({super.key, required this.label, required this.child}); - - @override - State createState() => _ItemState(); -} - -class _ItemState extends State { - @override - Widget build(BuildContext context) { - return SizedBox( - height: 54.w, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - widget.label, - style: TextStyle( - fontSize: 13.w, - fontWeight: FontWeight.w500 - ), - ), - widget.child - ], - ), - ); - } -} - -class LineItem extends StatelessWidget { - const LineItem({super.key}); - - @override - Widget build(BuildContext context) { - return Container( - width: 320.w, - height: 2.w, - color: const Color.fromRGBO(245, 245, 245, 1), - ); - } -} diff --git a/lib/pages/mine/user_info_page.dart b/lib/pages/mine/user_info_page.dart index 50ed079..cbb7903 100644 --- a/lib/pages/mine/user_info_page.dart +++ b/lib/pages/mine/user_info_page.dart @@ -1,42 +1,74 @@ +import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:dating_touchme_app/controller/mine/user_info_controller.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; class UserInfoPage extends StatelessWidget { - const UserInfoPage({Key? key}) : super(key: key); - + UserInfoPage({super.key}); // 显示头像选择选项 - void _showAvatarOptions(UserInfoController controller) { - showCupertinoModalPopup( - context: Get.context!, - builder: (context) => CupertinoActionSheet( - title: const Text('选择头像'), - actions: [ - CupertinoActionSheetAction( - child: const Text('拍照'), - onPressed: () async { - Navigator.pop(context); - await controller.handleCameraCapture(); - }, - ), - CupertinoActionSheetAction( - child: const Text('从相册选择'), - onPressed: () async { - Navigator.pop(context); - await controller.handleGallerySelection(); - }, - ), - ], - cancelButton: CupertinoActionSheetAction( - child: const Text('取消'), - isDestructiveAction: true, - onPressed: () { - Navigator.pop(context); - }, - ), - ), + void _showAvatarPopup(UserInfoController controller){ + Navigator.of(Get.context!).push( + TDSlidePopupRoute( + slideTransitionFrom: SlideTransitionFrom.bottom, + builder: (context) { + return Container( + // color: TDTheme.of(context).bgColorContainer, + height: 490, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(12.0), + topRight: Radius.circular(12.0), + ), + ), + child: Column( + children: [ + const SizedBox(height: 4), + CachedNetworkImage(imageUrl: 'https://dating-agency-prod.oss-cn-shenzhen.aliyuncs.com/1A437A945667.jpg', width: 375, height: 314), + const TDDivider(), + TDCell( + arrow: false, + titleWidget: Center( + child: Text('拍照', style: TextStyle(fontSize: 16.w, color: const Color.fromRGBO(51, 51, 51, 1))), + ), + onClick: (cell) async{ + Navigator.pop(context); + await controller.handleCameraCapture(); + }, + ), + const TDDivider(), + TDCell( + arrow: false, + titleWidget: Center( + child: Text('从相册选择'), + ), + onClick: (cell) async{ + Navigator.pop(context); + await controller.handleGallerySelection(); + }, + ), + Expanded( + child: Container( + color: Color(0xFFF3F3F3), + ), + ), + TDCell( + arrow: false, + titleWidget: Center( + child: Text('取消'), + ), + onClick: (cell){ + Navigator.pop(context); + }, + ), + ], + ), + ); + }), ); } @@ -228,7 +260,7 @@ class UserInfoPage extends StatelessWidget { title: const Text( '完善信息', style: TextStyle( - fontSize: 20, + fontSize: 16, fontWeight: FontWeight.bold, color: Color.fromRGBO(51, 51, 51, 1), ), @@ -255,10 +287,9 @@ class UserInfoPage extends StatelessWidget { child: Column( children: [ const SizedBox(height: 25), - // 头像 GestureDetector( - onTap: () => _showAvatarOptions(controller), + onTap: () => _showAvatarPopup(controller), child: Stack( children: [ Container( @@ -369,7 +400,7 @@ class UserInfoPage extends StatelessWidget { ), ], ), - const SizedBox(height: 25), + const SizedBox(height: 20), // 昵称 const Align( @@ -408,7 +439,7 @@ class UserInfoPage extends StatelessWidget { ], ), ), - const SizedBox(height: 25), + const SizedBox(height: 20), // 出生日期 const Align( @@ -452,7 +483,7 @@ class UserInfoPage extends StatelessWidget { ), ), ), - const SizedBox(height: 25), + const SizedBox(height: 20), // 学历 const Align( @@ -496,7 +527,7 @@ class UserInfoPage extends StatelessWidget { ), ), ), - const SizedBox(height: 25), + const SizedBox(height: 20), // 邀请码 const Align( @@ -528,7 +559,7 @@ class UserInfoPage extends StatelessWidget { ), ), ), - const SizedBox(height: 50), + const SizedBox(height: 24), // 开始交友按钮 SizedBox( @@ -562,7 +593,7 @@ class UserInfoPage extends StatelessWidget { ), ), ), - const SizedBox(height: 30), + const SizedBox(height: 20), ], ), ), diff --git a/lib/pages/mine/blacklist_page.dart b/lib/pages/setting/blacklist_page.dart similarity index 100% rename from lib/pages/mine/blacklist_page.dart rename to lib/pages/setting/blacklist_page.dart diff --git a/lib/pages/setting/notice_page.dart b/lib/pages/setting/notice_page.dart index 3378021..0e68bb6 100644 --- a/lib/pages/setting/notice_page.dart +++ b/lib/pages/setting/notice_page.dart @@ -1,79 +1,77 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; -class NoticePage extends StatefulWidget { - const NoticePage({super.key}); +import '../../components/page_appbar.dart'; +import '../../controller/setting/notification_controller.dart'; - @override - State createState() => _NoticePageState(); -} +class NoticePage extends StatelessWidget { + NoticePage({super.key}); -class _NoticePageState extends State with AutomaticKeepAliveClientMixin{ + final NotificationController controller = Get.put(NotificationController()); @override Widget build(BuildContext context) { - super.build(context); return Scaffold( backgroundColor: Color(0xffF5F5F5), - appBar: AppBar( - title: Text('消息通知', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - centerTitle: true, - backgroundColor: Colors.white, - ), + appBar: PageAppbar(title: "消息通知"), body: Expanded( child: SingleChildScrollView( padding: EdgeInsetsGeometry.symmetric(vertical: 16.w), - child: Column( - children: [ - TDCellGroup( - theme: TDCellGroupTheme.cardTheme, - cells: [ - TDCell( - arrow: true, - title: '接受推送通知', - description: '已开启', - ), - TDCell( - arrow: false, - title: '接受推送通知', - description: '一段很长很长的内容文字', - rightIconWidget: TDSwitch( - isOn: false, - trackOnColor: const Color.fromRGBO(117, 98, 249, 1), - onChanged: (bool e){ - return false; - }, - ) - ), - ], - ), - const SizedBox(height: 12), - TDCellGroup( - theme: TDCellGroupTheme.cardTheme, - cells: [ - TDCell( - arrow: false, - title: '后台播放', - description: '一段很长很长的内容文字', - rightIconWidget: TDSwitch( - isOn: true, - trackOnColor: const Color.fromRGBO(117, 98, 249, 1), - onChanged: (bool e){ - return false; - }, - ) - ), - ], - ), - ], - ), + child: Obx(() { + return Column( + children: [ + TDCellGroup( + theme: TDCellGroupTheme.cardTheme, + cells: [ + TDCell( + arrow: true, + title: '接受推送通知', + description: controller.getPermissionStatusText(), + onClick: (cell){ + controller.openSettings(); + }, + ), + TDCell( + arrow: false, + title: '接受推送通知', + description: '一段很长很长的内容文字', + rightIconWidget: TDSwitch( + isOn: false, + trackOnColor: const Color.fromRGBO(117, 98, 249, 1), + onChanged: (bool e){ + return false; + }, + ) + ), + ], + ), + const SizedBox(height: 12), + TDCellGroup( + theme: TDCellGroupTheme.cardTheme, + cells: [ + TDCell( + arrow: false, + title: '后台播放', + description: '一段很长很长的内容文字', + rightIconWidget: TDSwitch( + isOn: true, + trackOnColor: const Color.fromRGBO(117, 98, 249, 1), + onChanged: (bool e){ + return false; + }, + ) + ), + ], + ), + ], + ); + }), ), ), ); } - @override - bool get wantKeepAlive => true; } diff --git a/lib/pages/setting/setting_page.dart b/lib/pages/setting/setting_page.dart index ea67fd2..27c03e6 100644 --- a/lib/pages/setting/setting_page.dart +++ b/lib/pages/setting/setting_page.dart @@ -1,155 +1,153 @@ -import 'package:dating_touchme_app/components/home_appbar.dart'; -import 'package:dating_touchme_app/generated/assets.dart'; -import 'package:dating_touchme_app/pages/discover/live_room_page.dart'; +import 'package:dating_touchme_app/pages/mine/login_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; +import '../../components/page_appbar.dart'; +import '../../controller/setting/setting_controller.dart'; +import 'blacklist_page.dart'; import 'notice_page.dart'; -class SettingPage extends StatefulWidget { - const SettingPage({super.key}); +class SettingPage extends StatelessWidget { - @override - State createState() => _SettingPageState(); -} - -class _SettingPageState extends State with AutomaticKeepAliveClientMixin{ + SettingPage({super.key}); + final SettingController controller = Get.put(SettingController()); @override Widget build(BuildContext context) { - super.build(context); return Scaffold( backgroundColor: Color(0xffF5F5F5), - appBar: AppBar( - title: Text('设置', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), - centerTitle: true, - backgroundColor: Colors.white, - ), + appBar: PageAppbar(title: "设置"), body: Expanded( child: SingleChildScrollView( padding: EdgeInsetsGeometry.symmetric(vertical: 16.w), - child: Column( - children: [ - TDCellGroup( - theme: TDCellGroupTheme.cardTheme, - cells: [ - TDCell( - arrow: false, - title: '允许中间邀请弹窗', - rightIconWidget: TDSwitch( - isOn: false, - trackOnColor: const Color.fromRGBO(117, 98, 249, 1), - onChanged: (bool e){ - return false; + child: Obx(() { + return Column( + children: [ + TDCellGroup( + theme: TDCellGroupTheme.cardTheme, + cells: [ + TDCell( + arrow: false, + title: '允许中间邀请弹窗', + rightIconWidget: TDSwitch(isOn: false,trackOnColor: const Color.fromRGBO(117, 98, 249, 1),onChanged: (bool e) { + return false; + }) + ), + TDCell( + arrow: false, + title: '后台播放', + rightIconWidget: TDSwitch( + isOn: true, + trackOnColor: const Color.fromRGBO(117, 98, 249, 1), + onChanged: (bool e) { + return false; + }, + ) + ), + TDCell( + arrow: false, + title: '语音/视频通话提示音', + rightIconWidget: TDSwitch(isOn: false,trackOnColor: const Color.fromRGBO(117, 98, 249, 1),onChanged: (bool e) { + + return false; + }) + ), + ], + ), + const SizedBox(height: 12), + TDCellGroup( + theme: TDCellGroupTheme.cardTheme, + cells: [ + TDCell(arrow: true, title: '安全中心', onClick: (cell) { + print('安全中心'); + }), + TDCell(arrow: true, title: '黑名单', onClick: (cell) { + Get.to(() => BlacklistPage()); + }), + ], + ), + const SizedBox(height: 12), + TDCellGroup( + theme: TDCellGroupTheme.cardTheme, + cells: [ + TDCell(arrow: true, title: '系统权限管理'), + TDCell(arrow: true, title: '消息通知', onClick: (cell) { + Get.to(() => NoticePage()); + }), + TDCell(arrow: true, title: '检查更新', onClick: (cell) { + // _showUpdateDialog(); + controller.checkVersion(); }, + noteWidget: Text('当前版本:${controller.version.value}',style: TextStyle(fontSize: 13.w,color: const Color.fromRGBO(117, 98, 249, 1))), ) - ), - TDCell( - arrow: false, - title: '后台播放', - rightIconWidget: TDSwitch( - isOn: true, - trackOnColor: const Color.fromRGBO(117, 98, 249, 1), - onChanged: (bool e){ - return false; - }, - ) - ), - TDCell(arrow: false, title: '单行标题'), - ], - ), - const SizedBox(height: 12), - TDCellGroup( - theme: TDCellGroupTheme.cardTheme, - cells: [ - TDCell(arrow: true, title: '黑名单',onClick: (cell) { - print('单行标题'); - } - ), - ], - ), - const SizedBox(height: 12), - TDCellGroup( - theme: TDCellGroupTheme.cardTheme, - cells: [ - TDCell(arrow: true, title: '单行标题'), - TDCell(arrow: true, title: '单行标题'), - TDCell(arrow: true, title: '消息通知',onClick: (cell) { - Get.to(()=> NoticePage()); - } - ), - ], - ), - const SizedBox(height: 36), - TDButton( - text: '退出登录', - width: MediaQuery.of(context).size.width - 40, - size: TDButtonSize.large, - type: TDButtonType.fill, - shape: TDButtonShape.round, - theme: TDButtonTheme.danger, - onTap: (){ - // showGeneralDialog( - // context: context, - // pageBuilder: (BuildContext buildContext, Animation animation, - // Animation secondaryAnimation) { - // return TDConfirmDialog( - // title: '是否退出当前账号?', - // - // ); - // }, - // ); - showGeneralDialog( - context: context, - pageBuilder: (BuildContext buildContext, Animation animation, - Animation secondaryAnimation) { - return TDAlertDialog( - title: '是否退出当前账号?', - buttonWidget:Container( - padding: EdgeInsetsGeometry.only(top: 16.w, right: 30.w, left: 30.w, bottom: 32.w), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TDButton( - text: '取 消', - width: 120, - size: TDButtonSize.large, - type: TDButtonType.fill, - shape: TDButtonShape.round, - theme: TDButtonTheme.defaultTheme, - onTap: (){ - Navigator.of(context).pop(); - }, - ), - TDButton( - text: '确 定', - width: 120, - size: TDButtonSize.large, - type: TDButtonType.fill, - shape: TDButtonShape.round, - theme: TDButtonTheme.danger, - onTap: (){ - Navigator.of(context).pop(); - }, + ], + ), + const SizedBox(height: 64), + TDButton( + text: '退出登录', + width: MediaQuery.of(context).size.width - 40, + size: TDButtonSize.large, + type: TDButtonType.fill, + shape: TDButtonShape.round, + theme: TDButtonTheme.danger, + onTap: () { + showGeneralDialog( + context: context, + pageBuilder: (BuildContext buildContext, Animation< + double> animation, + Animation secondaryAnimation) { + return TDAlertDialog( + title: '是否退出当前账号?', + buttonWidget: Container( + padding: EdgeInsetsGeometry.only(top: 16.w, + right: 30.w, + left: 30.w, + bottom: 32.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TDButton( + text: '取 消', + width: 120, + size: TDButtonSize.large, + type: TDButtonType.fill, + shape: TDButtonShape.round, + theme: TDButtonTheme.defaultTheme, + onTap: () { + Navigator.of(context).pop(); + }, + ), + TDButton( + text: '确 定', + width: 120, + size: TDButtonSize.large, + type: TDButtonType.fill, + shape: TDButtonShape.round, + theme: TDButtonTheme.danger, + onTap: () { + controller.logout(); + Navigator.of(context).pop(); + Get.offAll(() => LoginPage()); + }, + ), + ], ), - ], - ), - ) - ); - }, - ); - }, - ), - ], - ), + ) + ); + }, + ); + }, + ), + const SizedBox(height: 24), + ], + ); + }), ), ), ); } - @override - bool get wantKeepAlive => true; } diff --git a/pubspec.yaml b/pubspec.yaml index 1a5d398..c20394b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,6 +58,8 @@ dependencies: wechat_assets_picker: ^9.8.0 wechat_camera_picker: ^4.4.0 tdesign_flutter: ^0.2.5 + app_settings: ^6.1.1 + package_info_plus: ^9.0.0 record: ^6.1.2 video_player: ^2.9.2 chewie: ^1.8.5 # 视频播放器UI