diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..da872b9 Binary files /dev/null and b/.DS_Store differ diff --git a/assets/images/login_bg_white.png b/assets/images/login_bg_white.png new file mode 100644 index 0000000..869cc21 Binary files /dev/null and b/assets/images/login_bg_white.png differ diff --git a/assets/images/real_login_bg.png b/assets/images/real_login_bg.png new file mode 100644 index 0000000..e097ded Binary files /dev/null and b/assets/images/real_login_bg.png differ diff --git a/assets/images/real_logo.png b/assets/images/real_logo.png new file mode 100644 index 0000000..753f879 Binary files /dev/null and b/assets/images/real_logo.png differ diff --git a/assets/images/square_nol.png b/assets/images/square_nol.png new file mode 100644 index 0000000..82c8709 Binary files /dev/null and b/assets/images/square_nol.png differ diff --git a/assets/images/square_pre.png b/assets/images/square_pre.png new file mode 100644 index 0000000..f4a89e8 Binary files /dev/null and b/assets/images/square_pre.png differ diff --git a/assets/images/star.png b/assets/images/star.png new file mode 100644 index 0000000..5863e33 Binary files /dev/null and b/assets/images/star.png differ diff --git a/assets/images/star_sky_bg.png b/assets/images/star_sky_bg.png new file mode 100644 index 0000000..7991346 Binary files /dev/null and b/assets/images/star_sky_bg.png differ diff --git a/assets/images/test1.png b/assets/images/test1.png new file mode 100644 index 0000000..c926830 Binary files /dev/null and b/assets/images/test1.png differ diff --git a/assets/images/test2.png b/assets/images/test2.png new file mode 100644 index 0000000..23dd5c4 Binary files /dev/null and b/assets/images/test2.png differ diff --git a/assets/images/test_bg.png b/assets/images/test_bg.png new file mode 100644 index 0000000..3694977 Binary files /dev/null and b/assets/images/test_bg.png differ diff --git a/ios/Podfile b/ios/Podfile index a896be8..6d26356 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -30,6 +30,7 @@ flutter_ios_podfile_setup target 'Runner' do use_frameworks! + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do inherit! :search_paths diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 62d2247..a37f9ab 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,55 +1,55 @@ PODS: - - agora_rtc_engine (6.5.3): - - AgoraIrisRTC_iOS (= 4.5.2-build.1) - - AgoraRtcEngine_iOS (= 4.5.2) + - agora_rtc_engine (6.5.1): + - AgoraIrisRTC_iOS (= 4.5.1-build.1) + - AgoraRtcEngine_iOS (= 4.5.1) - Flutter - agora_rtm (2.2.5): - AgoraIrisRTM_iOS (= 2.2.5-build.2) - AgoraRtm (= 2.2.5) - Flutter - - AgoraInfra_iOS (1.2.13.1) - - AgoraIrisRTC_iOS (4.5.2-build.1) + - AgoraInfra_iOS (1.2.13) + - AgoraIrisRTC_iOS (4.5.1-build.1) - AgoraIrisRTM_iOS (2.2.5-build.2) - - AgoraRtcEngine_iOS (4.5.2): - - AgoraRtcEngine_iOS/AIAEC (= 4.5.2) - - AgoraRtcEngine_iOS/AIAECLL (= 4.5.2) - - AgoraRtcEngine_iOS/AINS (= 4.5.2) - - AgoraRtcEngine_iOS/AINSLL (= 4.5.2) - - AgoraRtcEngine_iOS/AudioBeauty (= 4.5.2) - - AgoraRtcEngine_iOS/ClearVision (= 4.5.2) - - AgoraRtcEngine_iOS/ContentInspect (= 4.5.2) - - AgoraRtcEngine_iOS/FaceCapture (= 4.5.2) - - AgoraRtcEngine_iOS/FaceDetection (= 4.5.2) - - AgoraRtcEngine_iOS/LipSync (= 4.5.2) - - AgoraRtcEngine_iOS/ReplayKit (= 4.5.2) - - AgoraRtcEngine_iOS/RtcBasic (= 4.5.2) - - AgoraRtcEngine_iOS/SpatialAudio (= 4.5.2) - - AgoraRtcEngine_iOS/VideoAv1CodecDec (= 4.5.2) - - AgoraRtcEngine_iOS/VideoAv1CodecEnc (= 4.5.2) - - AgoraRtcEngine_iOS/VideoCodecDec (= 4.5.2) - - AgoraRtcEngine_iOS/VideoCodecEnc (= 4.5.2) - - AgoraRtcEngine_iOS/VirtualBackground (= 4.5.2) - - AgoraRtcEngine_iOS/VQA (= 4.5.2) - - AgoraRtcEngine_iOS/AIAEC (4.5.2) - - AgoraRtcEngine_iOS/AIAECLL (4.5.2) - - AgoraRtcEngine_iOS/AINS (4.5.2) - - AgoraRtcEngine_iOS/AINSLL (4.5.2) - - AgoraRtcEngine_iOS/AudioBeauty (4.5.2) - - AgoraRtcEngine_iOS/ClearVision (4.5.2) - - AgoraRtcEngine_iOS/ContentInspect (4.5.2) - - AgoraRtcEngine_iOS/FaceCapture (4.5.2) - - AgoraRtcEngine_iOS/FaceDetection (4.5.2) - - AgoraRtcEngine_iOS/LipSync (4.5.2) - - AgoraRtcEngine_iOS/ReplayKit (4.5.2) - - AgoraRtcEngine_iOS/RtcBasic (4.5.2): - - AgoraInfra_iOS (= 1.2.13.1) - - AgoraRtcEngine_iOS/SpatialAudio (4.5.2) - - AgoraRtcEngine_iOS/VideoAv1CodecDec (4.5.2) - - AgoraRtcEngine_iOS/VideoAv1CodecEnc (4.5.2) - - AgoraRtcEngine_iOS/VideoCodecDec (4.5.2) - - AgoraRtcEngine_iOS/VideoCodecEnc (4.5.2) - - AgoraRtcEngine_iOS/VirtualBackground (4.5.2) - - AgoraRtcEngine_iOS/VQA (4.5.2) + - AgoraRtcEngine_iOS (4.5.1): + - AgoraRtcEngine_iOS/AIAEC (= 4.5.1) + - AgoraRtcEngine_iOS/AIAECLL (= 4.5.1) + - AgoraRtcEngine_iOS/AINS (= 4.5.1) + - AgoraRtcEngine_iOS/AINSLL (= 4.5.1) + - AgoraRtcEngine_iOS/AudioBeauty (= 4.5.1) + - AgoraRtcEngine_iOS/ClearVision (= 4.5.1) + - AgoraRtcEngine_iOS/ContentInspect (= 4.5.1) + - AgoraRtcEngine_iOS/FaceCapture (= 4.5.1) + - AgoraRtcEngine_iOS/FaceDetection (= 4.5.1) + - AgoraRtcEngine_iOS/LipSync (= 4.5.1) + - AgoraRtcEngine_iOS/ReplayKit (= 4.5.1) + - AgoraRtcEngine_iOS/RtcBasic (= 4.5.1) + - AgoraRtcEngine_iOS/SpatialAudio (= 4.5.1) + - AgoraRtcEngine_iOS/VideoAv1CodecDec (= 4.5.1) + - AgoraRtcEngine_iOS/VideoAv1CodecEnc (= 4.5.1) + - AgoraRtcEngine_iOS/VideoCodecDec (= 4.5.1) + - AgoraRtcEngine_iOS/VideoCodecEnc (= 4.5.1) + - AgoraRtcEngine_iOS/VirtualBackground (= 4.5.1) + - AgoraRtcEngine_iOS/VQA (= 4.5.1) + - AgoraRtcEngine_iOS/AIAEC (4.5.1) + - AgoraRtcEngine_iOS/AIAECLL (4.5.1) + - AgoraRtcEngine_iOS/AINS (4.5.1) + - AgoraRtcEngine_iOS/AINSLL (4.5.1) + - AgoraRtcEngine_iOS/AudioBeauty (4.5.1) + - AgoraRtcEngine_iOS/ClearVision (4.5.1) + - AgoraRtcEngine_iOS/ContentInspect (4.5.1) + - AgoraRtcEngine_iOS/FaceCapture (4.5.1) + - AgoraRtcEngine_iOS/FaceDetection (4.5.1) + - AgoraRtcEngine_iOS/LipSync (4.5.1) + - AgoraRtcEngine_iOS/ReplayKit (4.5.1) + - AgoraRtcEngine_iOS/RtcBasic (4.5.1): + - AgoraInfra_iOS (= 1.2.13) + - AgoraRtcEngine_iOS/SpatialAudio (4.5.1) + - AgoraRtcEngine_iOS/VideoAv1CodecDec (4.5.1) + - AgoraRtcEngine_iOS/VideoAv1CodecEnc (4.5.1) + - AgoraRtcEngine_iOS/VideoCodecDec (4.5.1) + - AgoraRtcEngine_iOS/VideoCodecEnc (4.5.1) + - AgoraRtcEngine_iOS/VirtualBackground (4.5.1) + - AgoraRtcEngine_iOS/VQA (4.5.1) - AgoraRtm (2.2.5): - AgoraRtm/RtmBasic (= 2.2.5) - AgoraRtm/RtmKit (= 2.2.5) @@ -73,11 +73,11 @@ PODS: - fluwx/pay (0.0.1): - Flutter - WechatOpenSDK-XCFramework (~> 2.0.5) - - HyphenateChat (4.15.0): - - AgoraInfra_iOS (~> 1.2.13) + - HyphenateChat (4.15.1): + - AgoraInfra_iOS (= 1.2.13) - im_flutter_sdk_ios (4.15.2): - Flutter - - HyphenateChat (= 4.15.0) + - HyphenateChat (= 4.15.1) - image_picker_ios (0.0.1): - Flutter - iris_method_channel (0.0.1): @@ -225,41 +225,41 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin" SPEC CHECKSUMS: - agora_rtc_engine: da45ea14c402317c9e22fdb9ffe504d9a1acbe68 - agora_rtm: 171fb2ddc9da71ca2c30780118a5bc6d005aed49 - AgoraInfra_iOS: 3691b2b277a1712a35ae96de25af319de0d73d08 - AgoraIrisRTC_iOS: eab58c126439adf5ec99632828a558ea216860da + agora_rtc_engine: 7434787c0b5284d803c31c726562b8399b8c1744 + agora_rtm: 7b085b01b7c7ed083483e5d1947d48c960e6a62d + AgoraInfra_iOS: 65e11a2183ab7836258768868d06058c22701b13 + AgoraIrisRTC_iOS: dd3d957c25be6bd2b2a5d03fe706ebe8a46909f0 AgoraIrisRTM_iOS: 8db20697f717de6e1db5dd4c842432889f284220 - AgoraRtcEngine_iOS: 97e2398a2addda9057815a2a583a658e36796ff6 + AgoraRtcEngine_iOS: 5092a058c7b2842db39d8ca614d451af6f84969a AgoraRtm: d92cdfca825f3e6817c315d7dd6403742494f7ca - app_settings: 58017cd26b604ae98c3e65acbdd8ba173703cc82 - audioplayers_darwin: 4027b33a8f471d996c13f71cb77f0b1583b5d923 - camera_avfoundation: 281867ff09f1da66f031a184ecfbc6f2e625c9f5 - emoji_picker_flutter: 8e50ec5caac456a23a78637e02c6293ea0ac8771 + app_settings: 5127ae0678de1dcc19f2293271c51d37c89428b2 + audioplayers_darwin: 4f9ca89d92d3d21cec7ec580e78ca888e5fb68bd + camera_avfoundation: 5675ca25298b6f81fa0a325188e7df62cc217741 + emoji_picker_flutter: ece213fc274bdddefb77d502d33080dc54e616cc Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 - flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29 - fluwx: 95a2274c23418c1098940bd00dcfe7c975bb0550 - HyphenateChat: 4523c7fb2075771c49a2c492b31544d6cc82ff50 - im_flutter_sdk_ios: 6570b291875ab7b3016e8d21fc0ef58ab347cd38 - image_picker_ios: 4f2f91b01abdb52842a8e277617df877e40f905b - iris_method_channel: 4e3fe7fe6b2db1b84feae956e98ce1479402627a + flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf + fluwx: 2ef787502fccb3f3596b380509001a8ea71cbbff + HyphenateChat: ec813941100d602d24e06b04b867474d634cb39d + im_flutter_sdk_ios: fafe8d1fc7fb81592d81a88ddcc907042117cf6c + image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326 + iris_method_channel: 7d661cf3259b3009ae423508470dbeb9374446ee libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 - location_plugin: 0b3c55050267925da87176add5bf67c67c8be7ec - package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba - permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 - photo_manager: 647b6f5c5057632e2d00e2921c6ce3437ded57a9 - record_ios: 840d21cce013c5a3b2168b74a54ebdb4136359e2 - sensors_plus: 7229095999f30740798f0eeef5cd120357a8f4f2 - shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6 - sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d - url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa - video_player_avfoundation: 7993f492ae0bd77edaea24d9dc051d8bb2cd7c86 - video_thumbnail: c4e2a3c539e247d4de13cd545344fd2d26ffafd1 - wakelock_plus: 76957ab028e12bfa4e66813c99e46637f367fc7e - webview_flutter_wkwebview: 29eb20d43355b48fe7d07113835b9128f84e3af4 + location_plugin: 298d64961a9c4c878cb4661a8c077023a20f585f + package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 + path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880 + permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d + photo_manager: fe4cbb0808b96f8be4af7ce6ae18dcd9c9b983c6 + record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374 + sensors_plus: 6a11ed0c2e1d0bd0b20b4029d3bad27d96e0c65b + shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb + sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 + url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b + video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a + video_thumbnail: b637e0ad5f588ca9945f6e2c927f73a69a661140 + wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556 + webview_flutter_wkwebview: 8ebf4fded22593026f7dbff1fbff31ea98573c8d WechatOpenSDK-XCFramework: ff342ae616bb86df3d236aca38059dfd4bc4a949 -PODFILE CHECKSUM: 9f921d5f3a6aff46b310102d923e8942abc7114d +PODFILE CHECKSUM: 41486ec64c29f62dbac3d6ff9ca3fe04ec701a07 COCOAPODS: 1.16.2 diff --git a/lib/components/sphere_cloud.dart b/lib/components/sphere_cloud.dart new file mode 100644 index 0000000..2b0472c --- /dev/null +++ b/lib/components/sphere_cloud.dart @@ -0,0 +1,166 @@ +import 'dart:math' as math; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class SphereCloud extends StatefulWidget { + SphereCloud({ + super.key, + required this.items, + this.radius = 140, + required this.itemSize, + this.cameraZ = 360, // 相机离球心距离,越大透视越弱 + this.focal = 320, // 焦距,影响投影与缩放 + this.minScale = 0.45, + this.maxScale = 1.25, + }); + + final List items; + final double radius; + final double itemSize; + final double cameraZ; + final double focal; + final double minScale; + final double maxScale; + + @override + State createState() => _SphereCloudState(); +} + +class _SphereCloudState extends State { + late final List<_Point3> _points; + + // 当前旋转角(弧度) + double _rotX = 0.0; + double _rotY = 0.0; + + @override + void initState() { + super.initState(); + _points = _genFibonacciSphere(widget.items.length, widget.radius); + } + + @override + void didUpdateWidget(covariant SphereCloud oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.items.length != widget.items.length || + oldWidget.radius != widget.radius) { + _points + ..clear() + ..addAll(_genFibonacciSphere(widget.items.length, widget.radius)); + } + } + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (_, c) { + final cx = c.maxWidth / 2; + final cy = c.maxHeight / 2; + + // 计算每个点投影后的 2D 信息 + final projected = <_ProjectedItem>[]; + for (int i = 0; i < _points.length; i++) { + final p = _rotate(_points[i], _rotX, _rotY); + + // 透视:避免 cameraZ - z 过小导致爆炸 + final denom = (widget.cameraZ - p.z).clamp(40.0, 1e9); + final perspective = widget.focal / denom; + + final x2 = cx + p.x * perspective; + final y2 = cy + p.y * perspective; + + final scale = perspective.clamp(widget.minScale, widget.maxScale); + + projected.add(_ProjectedItem( + index: i, + x: x2, + y: y2, + z: p.z, + scale: scale, + )); + } + + // 按 z 排序:远->近 + projected.sort((a, b) => a.z.compareTo(b.z)); + + return GestureDetector( + behavior: HitTestBehavior.opaque, + onPanUpdate: (d) { + // 你可以按手感调整系数 + setState(() { + _rotY += d.delta.dx * 0.01; + _rotX -= d.delta.dy * 0.01; + }); + }, + child: Stack( + clipBehavior: Clip.none, + children: [ + for (final it in projected) + Positioned( + left: it.x - widget.itemSize / 2, + top: it.y - widget.itemSize / 2, + child: Transform.scale( + scale: it.scale, + child: SizedBox( + width: widget.itemSize, + height: widget.itemSize, + child: widget.items[it.index], + ), + ), + ), + ], + ), + ); + }); + } + + // Fibonacci sphere:简单、分布均匀(比随机更像“均匀铺满球面”) + List<_Point3> _genFibonacciSphere(int n, double r) { + if (n <= 0) return []; + final pts = <_Point3>[]; + final offset = 2.0 / n; + final increment = math.pi * (3.0 - math.sqrt(5.0)); // golden angle + for (int i = 0; i < n; i++) { + final y = ((i * offset) - 1) + (offset / 2); + final rr = math.sqrt(1 - y * y); + final phi = i * increment; + final x = math.cos(phi) * rr; + final z = math.sin(phi) * rr; + pts.add(_Point3(x * r, y * r, z * r)); + } + return pts; + } + + // 绕 X/Y 旋转(右手系) + _Point3 _rotate(_Point3 p, double rx, double ry) { + // rotate around X + final cosX = math.cos(rx), sinX = math.sin(rx); + var y1 = p.y * cosX - p.z * sinX; + var z1 = p.y * sinX + p.z * cosX; + + // rotate around Y + final cosY = math.cos(ry), sinY = math.sin(ry); + var x2 = p.x * cosY + z1 * sinY; + var z2 = -p.x * sinY + z1 * cosY; + + return _Point3(x2, y1, z2); + } +} + +class _Point3 { + _Point3(this.x, this.y, this.z); + final double x, y, z; +} + +class _ProjectedItem { + _ProjectedItem({ + required this.index, + required this.x, + required this.y, + required this.z, + required this.scale, + }); + + final int index; + final double x, y, z; + final double scale; +} diff --git a/lib/controller/home/real_home_controller.dart b/lib/controller/home/real_home_controller.dart new file mode 100644 index 0000000..5bea0b8 --- /dev/null +++ b/lib/controller/home/real_home_controller.dart @@ -0,0 +1,45 @@ +import 'package:dating_touchme_app/model/home/marriage_data.dart'; +import 'package:dating_touchme_app/network/home_api.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class RealHomeController extends GetxController { + + late final HomeApi _homeApi; + // 推荐列表数据 + final recommendFeed = [].obs; + + @override + void onInit() { + super.onInit(); + // 从全局依赖中获取HomeApi + _homeApi = Get.find(); + getListData(); + } + + getListData() async { + try { + var response = await _homeApi.getMarriageList( + pageNum: 1, + pageSize: 100, + type: 0, + ); + if (response.data.isSuccess) { + final allRecords = response.data.data!.records + .map((item) => MarriageData.fromJson(item as Map)) + .toList(); + + // 过滤掉直播类型的项 + final records = allRecords!.where((item) => !item.isLive).toList(); + recommendFeed.addAll(records); + update(); + } else { + // 响应失败,抛出异常 + throw Exception(response.data.message); + } + } catch(e) { + // 向上抛出异常,让调用方处理 + rethrow; + } + } +} \ No newline at end of file diff --git a/lib/controller/mine/edit_info_controller.dart b/lib/controller/mine/edit_info_controller.dart index 80dea06..8bfda57 100644 --- a/lib/controller/mine/edit_info_controller.dart +++ b/lib/controller/mine/edit_info_controller.dart @@ -342,14 +342,14 @@ class EditInfoController extends GetxController { Future handleCameraCapture(int type) async { try { // 请求相机权限 - final ok = await _ensurePermission( - Permission.camera, - denyToast: '相机权限被拒绝,请在设置中允许访问相机', - ); - if (!ok) return; - - // 请求麦克风权限(部分设备拍照/录像会一并请求建议预授权) - await _ensurePermission(Permission.microphone, denyToast: '麦克风权限被拒绝'); + // final ok = await _ensurePermission( + // Permission.camera, + // denyToast: '相机权限被拒绝,请在设置中允许访问相机', + // ); + // if (!ok) return; + // + // // 请求麦克风权限(部分设备拍照/录像会一并请求建议预授权) + // await _ensurePermission(Permission.microphone, denyToast: '麦克风权限被拒绝'); // 权限通过后拍照 final ImagePicker picker = ImagePicker(); diff --git a/lib/controller/mine/login_controller.dart b/lib/controller/mine/login_controller.dart index 2d25f90..e646912 100644 --- a/lib/controller/mine/login_controller.dart +++ b/lib/controller/mine/login_controller.dart @@ -18,6 +18,7 @@ class LoginController extends GetxController with WidgetsBindingObserver { final countdownSeconds = 0.obs; // 是否正在登录中 final isLoggingIn = false.obs; + final passwordController = TextEditingController().obs; DateTime? startTime; @@ -51,6 +52,8 @@ class LoginController extends GetxController with WidgetsBindingObserver { } } + final isSend = false.obs; + // 获取验证码 Future getVerificationCode() async { // 验证手机号格式 @@ -74,6 +77,7 @@ class LoginController extends GetxController with WidgetsBindingObserver { // 处理响应 if (response.data.isSuccess) { + isSend.value = true; // 生产环境移除打印,可考虑使用正式的日志框架 // print('验证码发送成功'); // 开始倒计时 diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index 038821d..7e8a5b2 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -137,6 +137,7 @@ class Assets { static const String imagesLiveIcon = 'assets/images/live_icon.png'; static const String imagesLocationIcon = 'assets/images/location_icon.png'; static const String imagesLoginBg = 'assets/images/login_bg.png'; + static const String imagesLoginBgWhite = 'assets/images/login_bg_white.png'; static const String imagesLoginLogo = 'assets/images/login_logo.png'; static const String imagesMail = 'assets/images/mail.png'; static const String imagesMale = 'assets/images/male.png'; @@ -173,6 +174,8 @@ class Assets { static const String imagesPublish = 'assets/images/publish.png'; static const String imagesQuestionIcon = 'assets/images/question_icon.png'; static const String imagesRealChecked = 'assets/images/real_checked.png'; + static const String imagesRealLoginBg = 'assets/images/real_login_bg.png'; + static const String imagesRealLogo = 'assets/images/real_logo.png'; static const String imagesRealName = 'assets/images/real_name.png'; static const String imagesRealUncheck = 'assets/images/real_uncheck.png'; static const String imagesRealnameHelp = 'assets/images/realname_help.png'; @@ -196,12 +199,19 @@ class Assets { static const String imagesSettingIcon = 'assets/images/setting_icon.png'; static const String imagesShop = 'assets/images/shop.png'; static const String imagesSplash = 'assets/images/splash.png'; + static const String imagesSquareNol = 'assets/images/square_nol.png'; + static const String imagesSquarePre = 'assets/images/square_pre.png'; + static const String imagesStar = 'assets/images/star.png'; + static const String imagesStarSkyBg = 'assets/images/star_sky_bg.png'; static const String imagesSubscript = 'assets/images/subscript.png'; static const String imagesSuccessIcon = 'assets/images/success_icon.png'; static const String imagesTabChangeIcon = 'assets/images/tab_change_icon.png'; static const String imagesTalkIcon = 'assets/images/talk_icon.png'; static const String imagesTeenagerBg = 'assets/images/teenager_bg.png'; static const String imagesTeenagerList = 'assets/images/teenager_list.png'; + static const String imagesTest1 = 'assets/images/test1.png'; + static const String imagesTest2 = 'assets/images/test2.png'; + static const String imagesTestBg = 'assets/images/test_bg.png'; static const String imagesUnreadIcon = 'assets/images/unread_icon.png'; static const String imagesUpdataBg = 'assets/images/updata_bg.png'; static const String imagesUpdataFont = 'assets/images/updata_font.png'; diff --git a/lib/im/im_manager.dart b/lib/im/im_manager.dart index a9ac66c..ef3a120 100644 --- a/lib/im/im_manager.dart +++ b/lib/im/im_manager.dart @@ -13,6 +13,7 @@ import '../controller/message/chat_controller.dart'; import '../controller/global.dart'; import '../pages/mine/login_page.dart'; import '../network/user_api.dart'; +import '../pages/mine/real_login_page.dart'; // 完整的IM管理器实现,使用实际的SDK类型和方法 class IMManager { @@ -582,7 +583,7 @@ class IMManager { await Future.delayed(Duration(milliseconds: 500)); // 跳转到登录页 - Get.offAll(() => LoginPage()); + Get.offAll(() => RealLoginPage()); if (Get.isLogEnable) { Get.log('✅ [IMManager] 用户被踢下线处理完成,已跳转到登录页'); diff --git a/lib/main.dart b/lib/main.dart index 22ccaae..c2e99ef 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:dating_touchme_app/im/im_manager.dart'; import 'package:dating_touchme_app/network/network_service.dart'; import 'package:dating_touchme_app/pages/main/main_page.dart'; import 'package:dating_touchme_app/pages/mine/login_page.dart'; +import 'package:dating_touchme_app/pages/mine/real_login_page.dart'; import 'package:dating_touchme_app/pages/setting/teenager_mode_page.dart'; import 'package:dating_touchme_app/rtc/rtc_manager.dart'; import 'package:dating_touchme_app/widget/live/draggable_overlay_widget.dart'; @@ -275,11 +276,11 @@ class _MyAppState extends State { GlobalData().userId = userId; homeWidget = MainPage(); } else { - homeWidget = LoginPage(); + homeWidget = RealLoginPage(); } // 如果需要显示协议弹框,则显示 - if (_showAgreementDialog) { + if (false) { return Stack( children: [ homeWidget, diff --git a/lib/network/network_config.dart b/lib/network/network_config.dart index a86d420..031c1a8 100644 --- a/lib/network/network_config.dart +++ b/lib/network/network_config.dart @@ -4,6 +4,7 @@ import 'package:dating_touchme_app/controller/home/home_controller.dart'; import 'package:dating_touchme_app/controller/message/conversation_controller.dart'; import 'package:dating_touchme_app/controller/mine/mine_controller.dart'; import 'package:dating_touchme_app/im/im_manager.dart'; +import 'package:dating_touchme_app/pages/mine/real_login_page.dart'; import 'package:dio/dio.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart' hide Response; @@ -176,6 +177,6 @@ class ResponseInterceptor extends Interceptor { // 清除全局数据 GlobalData().logout(); - Get.offAll(() => LoginPage()); + Get.offAll(() => RealLoginPage()); } } \ No newline at end of file diff --git a/lib/pages/home/real_home_page.dart b/lib/pages/home/real_home_page.dart new file mode 100644 index 0000000..d9ff8af --- /dev/null +++ b/lib/pages/home/real_home_page.dart @@ -0,0 +1,183 @@ +import 'package:dating_touchme_app/components/page_appbar.dart'; +import 'package:dating_touchme_app/components/sphere_cloud.dart'; +import 'package:dating_touchme_app/controller/home/real_home_controller.dart'; +import 'package:dating_touchme_app/extension/ex_widget.dart'; +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:dating_touchme_app/pages/home/real_home_timeline_item.dart'; +import 'package:dating_touchme_app/pages/home/test_page.dart'; +import 'package:dating_touchme_app/pages/home/user_information_page.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +class RealHomePage extends StatefulWidget { + const RealHomePage({super.key}); + + @override + State createState() => _RealHomePageState(); +} + +class _RealHomePageState extends State with AutomaticKeepAliveClientMixin { + + @override + Widget build(BuildContext context) { + super.build(context); + return GetBuilder( + init: RealHomeController(), + builder: (controller){ + return Stack( + children: [ + Image.asset( + Assets.imagesStarSkyBg, + width: 375.w, + fit: BoxFit.cover, + alignment: AlignmentGeometry.topCenter, + ), + Scaffold( + backgroundColor: Colors.transparent, + appBar: PageAppbar(title: "快乐星球", color: Colors.white, backgroundColor: Colors.transparent,), + body: Container( + width: 375.w, + padding: EdgeInsets.symmetric(horizontal: 15.w), + child: SingleChildScrollView( + child: Column( + children: [ + SizedBox( + width: 345.w, + height: 345.w, + child: SphereCloud( + itemSize: 36.w, + items: [ + ...controller.recommendFeed.map((e){ + return SizedBox( + width: 36.w, + child: Column( + children: [ + Text( + e.nickName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 12.w, + color: Colors.white, + fontWeight: FontWeight.w400 + ), + ), + Image.asset( + Assets.imagesStar, + width: 18.w, + height: 18.w, + fit: BoxFit.cover, + ) + ], + ), + ).onTap((){ + Get.to(() => UserInformationPage(miId: e.miId, userId: e.userId,)); + }); + }), + ] + ), + ), + Container( + width: 92.w, + height: 21.w, + margin: EdgeInsets.symmetric(vertical: 20.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(21.w)), + color: const Color.fromRGBO(255, 255, 255, .1) + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.autorenew, + size: 18.w, + color: Colors.white, + ), + SizedBox(width: 4.w,), + Text( + "换一批", + style: TextStyle( + fontSize: 12.w, + color: Colors.white + ), + ) + ], + ), + ), + Row( + children: [ + Text( + "趣味测试", + style: TextStyle( + fontSize: 16.w, + color: Colors.white + ), + ) + ], + ), + SizedBox(height: 7.w,), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Image.asset( + Assets.imagesTest1, + width: 170.w, + ).onTap(() { + Get.to(() => TestPage()); + }), + Image.asset( + Assets.imagesTest2, + width: 170.w, + ).onTap(() { + Get.to(() => TestPage()); + }), + ], + ), + SizedBox(height: 15.w,), + Row( + children: [ + Text( + "热门帖子", + style: TextStyle( + fontSize: 16.w, + color: Colors.white + ), + ) + ], + ), + SizedBox(height: 7.w,), + Wrap( + spacing: 5.w, + runSpacing: 5.w, + children: [ + RealHomeTimelineItem(), + RealHomeTimelineItem(), + RealHomeTimelineItem(), + RealHomeTimelineItem(), + RealHomeTimelineItem(), + RealHomeTimelineItem(), + RealHomeTimelineItem(), + RealHomeTimelineItem(), + RealHomeTimelineItem(), + RealHomeTimelineItem(), + RealHomeTimelineItem(), + RealHomeTimelineItem(), + ], + ) + ], + ), + ), + ), + ) + ], + ); + }, + ); + } + + + @override + bool get wantKeepAlive => true; +} + diff --git a/lib/pages/home/real_home_timeline_item.dart b/lib/pages/home/real_home_timeline_item.dart new file mode 100644 index 0000000..0a57626 --- /dev/null +++ b/lib/pages/home/real_home_timeline_item.dart @@ -0,0 +1,85 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class RealHomeTimelineItem extends StatefulWidget { + const RealHomeTimelineItem({super.key}); + + @override + State createState() => _RealHomeTimelineItemState(); +} + +class _RealHomeTimelineItemState extends State { + @override + Widget build(BuildContext context) { + return ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(8.w)), + child: Container( + width: 170.w, + height: 205.w, + color: Colors.white, + child: Column( + children: [ + Image.asset( + Assets.imagesUserAvatar, + width: 170.w, + height: 170.w, + ), + Container( + width: 170.w, + height: 35.w, + color: Colors.white, + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(23.w)), + child: Image.asset( + Assets.imagesUserAvatar, + width: 23.w, + height: 23.w, + ), + ), + SizedBox(width: 3.w,), + Text( + "大西瓜", + style: TextStyle( + fontSize: 12.w, + fontWeight: FontWeight.w400 + ), + ) + ], + ), + Row( + children: [ + Row( + children: [ + Image.asset( + (false) ? Assets.imagesLikeActive : Assets.imagesLikeIcon, + width: 14.w, + height: 12.w, + ), + SizedBox(width: 6.w,), + Text( + "${23}", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(144, 144, 144, .6) + ), + ) + ], + ) + ], + ) + ], + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/home/recommend_tab.dart b/lib/pages/home/recommend_tab.dart index 61d4c66..b8ca852 100644 --- a/lib/pages/home/recommend_tab.dart +++ b/lib/pages/home/recommend_tab.dart @@ -276,9 +276,7 @@ class _RecommendTabState extends State color: const Color.fromRGBO(144, 144, 144, 1), fontWeight: FontWeight.w500 ), - ).onTap((){ - Get.to(() => MatchmakerPage()); - }) + ) ], ), Wrap( @@ -292,7 +290,9 @@ class _RecommendTabState extends State ) ], ), - ), + ).onTap((){ + Get.to(() => MatchmakerPage()); + }), ], ), ), diff --git a/lib/pages/home/send_timeline.dart b/lib/pages/home/send_timeline.dart index c975525..a6001fd 100644 --- a/lib/pages/home/send_timeline.dart +++ b/lib/pages/home/send_timeline.dart @@ -245,7 +245,7 @@ class _SendTimelineState extends State { imgList.addAll(list); print(imgList); SmartDialog.dismiss(); - SmartDialog.showToast('上传相册成功'); + SmartDialog.showToast('上传照片成功'); setState(() { diff --git a/lib/pages/home/test_page.dart b/lib/pages/home/test_page.dart new file mode 100644 index 0000000..b86cafe --- /dev/null +++ b/lib/pages/home/test_page.dart @@ -0,0 +1,53 @@ +import 'package:dating_touchme_app/components/page_appbar.dart'; +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class TestPage extends StatelessWidget { + const TestPage({super.key}); + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Image.asset( + Assets.imagesTestBg, + width: 375.w, + fit: BoxFit.cover, + ), + Scaffold( + backgroundColor: Colors.transparent, + appBar: PageAppbar(title: "人格类型测试", color: Colors.white, backgroundColor: Colors.transparent,), + body: Container( + width: 375.w, + padding: EdgeInsets.symmetric( + vertical: 40.w, + horizontal: 12.w + ), + child: Column( + children: [ + Container( + width: 350.w, + padding: EdgeInsets.all(30.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(16.w)), + color: const Color.fromRGBO(39, 48, 89, 1) + ), + child: Center( + child: Text( + "在陌生环境中,你通常会在陌生环境中,你通常会在陌生环境中,你通常会", + style: TextStyle( + fontSize: 16.w, + color: Colors.white + ), + ), + ), + ) + ], + ), + ), + ) + ], + ); + } +} diff --git a/lib/pages/home/timeline_info.dart b/lib/pages/home/timeline_info.dart index ce132c3..1abb359 100644 --- a/lib/pages/home/timeline_info.dart +++ b/lib/pages/home/timeline_info.dart @@ -202,7 +202,9 @@ class TimelineInfo extends StatelessWidget { height: 341.w, fit: BoxFit.cover, ), - ), + ).onTap((){ + TDImageViewer.showImageViewer(context: context, images: controller.imgList); + }), if(controller.imgList.length == 2) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -229,7 +231,9 @@ class TimelineInfo extends StatelessWidget { height: 165.w, fit: BoxFit.cover, ), - ); + ).onTap((){ + TDImageViewer.showImageViewer(context: context, images: controller.imgList); + }); }), ], ), @@ -259,7 +263,9 @@ class TimelineInfo extends StatelessWidget { height: 105.w, fit: BoxFit.cover, ), - ); + ).onTap((){ + TDImageViewer.showImageViewer(context: context, images: controller.imgList); + }); }), ], ), diff --git a/lib/pages/home/timeline_item.dart b/lib/pages/home/timeline_item.dart index cb58515..1b52183 100644 --- a/lib/pages/home/timeline_item.dart +++ b/lib/pages/home/timeline_item.dart @@ -11,6 +11,7 @@ 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:tdesign_flutter/tdesign_flutter.dart'; class TimelineItem extends StatefulWidget { final Records item; @@ -239,7 +240,9 @@ class _TimelineItemState extends State { height: 341.w, fit: BoxFit.cover, ), - ), + ).onTap((){ + TDImageViewer.showImageViewer(context: context, images: imgList); + }), if(imgList.length == 2) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -265,7 +268,9 @@ class _TimelineItemState extends State { height: 165.w, fit: BoxFit.cover, ), - ); + ).onTap((){ + TDImageViewer.showImageViewer(context: context, images: imgList); + }); }), ], ), @@ -295,7 +300,9 @@ class _TimelineItemState extends State { height: 105.w, fit: BoxFit.cover, ), - ); + ).onTap((){ + TDImageViewer.showImageViewer(context: context, images: imgList); + }); }), ], ), diff --git a/lib/pages/home/timeline_page.dart b/lib/pages/home/timeline_page.dart index 53b9a56..0ef9741 100644 --- a/lib/pages/home/timeline_page.dart +++ b/lib/pages/home/timeline_page.dart @@ -28,6 +28,10 @@ class _TimelinePageState extends State if (!Get.isRegistered()) { Get.put(TimelineController()); } + // 确保 HomeController 已注册 + if (!Get.isRegistered()) { + Get.put(HomeController()); + } } @override diff --git a/lib/pages/home/user_information_page.dart b/lib/pages/home/user_information_page.dart index 3efcf7c..a86cde4 100644 --- a/lib/pages/home/user_information_page.dart +++ b/lib/pages/home/user_information_page.dart @@ -226,7 +226,7 @@ class UserInformationPage extends StatelessWidget { ), ), SizedBox(width: 13.w,), - if(controller.myUserData.value?.genderCode == 0) Container( + if(controller.userData.value?.genderCode == 1) Container( width: 33.w, height: 13.w, decoration: BoxDecoration( @@ -304,7 +304,7 @@ class UserInformationPage extends StatelessWidget { ), ), SizedBox(width: 4.w,), - if(controller.myUserData.value?.genderCode == 1) Container( + if(controller.userData.value?.genderCode == 0) Container( width: 33.w, height: 13.w, decoration: BoxDecoration( diff --git a/lib/pages/main/main_page.dart b/lib/pages/main/main_page.dart index a383aa2..211a52b 100644 --- a/lib/pages/main/main_page.dart +++ b/lib/pages/main/main_page.dart @@ -1,5 +1,6 @@ import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:dating_touchme_app/pages/home/real_home_page.dart'; import 'package:dating_touchme_app/pages/home/send_timeline.dart'; import 'package:dating_touchme_app/pages/home/timeline_page.dart'; import 'package:dating_touchme_app/pages/home/timeline_window.dart'; @@ -34,7 +35,7 @@ class _MainPageState extends State { int currentIndex = 0; // 使用普通int替代RxInt // 将页面实例存储为成员变量,避免每次build都重新创建 - late HomePage homePage; + late RealHomePage homePage; late DiscoverPage discoverPage; late TimelinePage timelinePage; late MessagePage messagePage; @@ -45,7 +46,7 @@ class _MainPageState extends State { super.initState(); // 初始化页面实例 - homePage = HomePage(); + homePage = RealHomePage(); // discoverPage = DiscoverPage(); timelinePage = TimelinePage(); messagePage = MessagePage(); @@ -103,7 +104,7 @@ class _MainPageState extends State { barHeight: 61, navigationTabs: [ tabItem('首页', Assets.imagesHomePre, Assets.imagesHomeNol, 0), - tabItem('广场', Assets.imagesDiscoverPre, Assets.imagesDiscoverNol, 1), + tabItem('广场', Assets.imagesSquarePre, Assets.imagesSquareNol, 1), tabItem('消息', Assets.imagesMessagePre, Assets.imagesMessageNol, 2), tabItem('我的', Assets.imagesMinePre, Assets.imagesMineNol, 3), ] diff --git a/lib/pages/mine/mine_page.dart b/lib/pages/mine/mine_page.dart index 05890a7..70236b4 100644 --- a/lib/pages/mine/mine_page.dart +++ b/lib/pages/mine/mine_page.dart @@ -15,6 +15,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import '../discover/visitor_list_page.dart'; +import 'open_webview.dart'; class MinePage extends StatefulWidget { const MinePage({super.key}); @@ -278,6 +279,65 @@ class _MinePageState extends State with AutomaticKeepAliveClientMixin{ ), ), SizedBox(height: 12.w,), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + color: Colors.white + ), + child: Column( + children: [ + Container( + height: 48.w, + padding: EdgeInsets.symmetric(horizontal: 16.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "用户协议", + style: TextStyle( + fontSize: 14.w, + fontWeight: FontWeight.w500, + color: Colors.black + ), + ), + Image.asset( + Assets.imagesArrow, + width: 4.w, + height: 8.w, + ) + ], + ), + ).onTap((){ + Get.to(() => OpenWebView(url: "https://www.quzhaoqin.com/privacy.html")); + }), + Container( + height: 48.w, + padding: EdgeInsets.symmetric(horizontal: 16.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "隐私政策", + style: TextStyle( + fontSize: 14.w, + fontWeight: FontWeight.w500, + color: Colors.black + ), + ), + Image.asset( + Assets.imagesArrow, + width: 4.w, + height: 8.w, + ) + ], + ), + ).onTap((){ + Get.to(() => OpenWebView(url: "https://www.quzhaoqin.com/information.html")); + }), + ], + ), + ), + SizedBox(height: 12.w,), ClipRRect( borderRadius: BorderRadius.all(Radius.circular(9.w)), child: Column( diff --git a/lib/pages/mine/phone_login_page.dart b/lib/pages/mine/phone_login_page.dart new file mode 100644 index 0000000..74fe76e --- /dev/null +++ b/lib/pages/mine/phone_login_page.dart @@ -0,0 +1,169 @@ +import 'package:dating_touchme_app/controller/mine/login_controller.dart'; +import 'package:dating_touchme_app/extension/ex_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:pinput/pinput.dart'; + +class PhoneLoginPage extends StatelessWidget { + const PhoneLoginPage({super.key}); + + @override + Widget build(BuildContext context) { + return GetX( + init: LoginController(), + builder: (controller){ + return Scaffold( + backgroundColor: Colors.white, + body: !(controller.isSend.value) ? Container( + width: 375.w, + padding: EdgeInsets.only( + top: 310.w, + left: 25.w, + right: 25.w + ), + child: Column( + children: [ + Container( + height: 52.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + border: Border.all(width: 1.w, color: const Color.fromRGBO(230, 230, 230, 1)) + ), + child: Center( + child: TextField( + decoration: const InputDecoration( + hintText: '请输入你的手机号', + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + horizontal: 15, + vertical: 0, + ), + counterText: '', + ), + keyboardType: TextInputType.phone, + inputFormatters: [ + // 只允许 0-9 + FilteringTextInputFormatter.digitsOnly, + ], + maxLength: 11, + onChanged: (value) { + controller.phoneNumber.value = value; + }, + style: const TextStyle(fontSize: 16), + ), + ), + ), + SizedBox(height: 10.w,), + Text( + "未注册的手机号将在登录后自动注册", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(189, 189, 189, 1) + ), + ), + SizedBox(height: 30.w,), + Container( + width: 325.w, + height: 52.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(52.w)), + gradient: controller.phoneNumber.value.isNotEmpty ? LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color.fromRGBO(131, 89, 255, 1), + Color.fromRGBO(61, 138, 224, 1), + ], + ) : null, + color: const Color.fromRGBO(217, 217, 217, 1) + ), + child: Center( + child: Text( + "获取验证码", + style: TextStyle( + fontSize: 18.w, + color: Colors.white + ), + ), + ), + ).onTap(() { + controller.isSendingCode.value || + controller.countdownSeconds.value > 0 + ? null + : controller.getVerificationCode(); + }), + ], + ), + ) : Container( + width: 375.w, + padding: EdgeInsets.only( + top: 271.w, + left: 25.w, + right: 25.w + ), + child: Column( + children: [ + Text( + "已发送到${controller.phoneNumber.value}", + style: TextStyle( + fontSize: 14.w + ), + ), + SizedBox(height: 20.w,), + + Pinput( + length: 6, + controller: controller.passwordController.value, + inputFormatters: [ + // 只允许 0-9 + FilteringTextInputFormatter.digitsOnly, + ], + onCompleted: (pin) { + controller.verificationCode.value = pin; + controller.isLoggingIn.value + ? null + : controller.login(); + }, + ), + SizedBox(height: 40.w,), + Container( + width: 325.w, + height: 52.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(52.w)), + gradient: controller.countdownSeconds.value <= 0 ? LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color.fromRGBO(131, 89, 255, 1), + Color.fromRGBO(61, 138, 224, 1), + ], + ) : null, + color: const Color.fromRGBO(217, 217, 217, 1) + ), + child: Center( + child: Text( + controller.countdownSeconds.value > 0 ? "获取验证码 ${controller.countdownSeconds.value}s" : "获取验证码", + style: TextStyle( + fontSize: 18.w, + color: Colors.white + ), + ), + ), + ).onTap(() { + controller.isSendingCode.value || + controller.countdownSeconds.value > 0 + ? null + : controller.getVerificationCode(); + }), + ], + ), + ), + ); + }, + ); + } +} + diff --git a/lib/pages/mine/real_login_page.dart b/lib/pages/mine/real_login_page.dart new file mode 100644 index 0000000..8ee1f84 --- /dev/null +++ b/lib/pages/mine/real_login_page.dart @@ -0,0 +1,104 @@ +import 'package:dating_touchme_app/extension/ex_widget.dart'; +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:dating_touchme_app/pages/mine/phone_login_page.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; + +class RealLoginPage extends StatefulWidget { + const RealLoginPage({super.key}); + + @override + State createState() => _RealLoginPageState(); +} + +class _RealLoginPageState extends State { + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Container( + width: 375.w, + height: 812.h, + color: Colors.white, + ), + Image.asset( + Assets.imagesRealLoginBg, + width: 375.w, + fit: BoxFit.cover, + alignment: AlignmentGeometry.topCenter, + ), + Image.asset( + Assets.imagesLoginBgWhite, + width: 375.w, + fit: BoxFit.cover, + alignment: AlignmentGeometry.topCenter, + ), + Scaffold( + backgroundColor: Colors.transparent, + body: Container( + width: 375.w, + padding: EdgeInsets.only( + top: 126.w, + left: 20.w, + right: 20.w + ), + child: Column( + children: [ + Image.asset( + Assets.imagesRealLogo, + width: 55.w, + height: 55.w, + ), + SizedBox(height: 12.w,), + Text( + "快乐星球", + style: TextStyle( + fontSize: 24.w + ), + ), + SizedBox(height: 261.w,), + Container( + width: 335.w, + height: 52.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(52.w)), + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color.fromRGBO(131, 89, 255, 1), + Color.fromRGBO(61, 138, 224, 1), + ], + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.phone_iphone, + size: 28.w, + color: Colors.white, + ), + SizedBox(width: 12.w,), + Text( + "手机登录注册", + style: TextStyle( + fontSize: 18.w, + color: Colors.white + ), + ) + ], + ), + ).onTap(() { + Get.to(() => PhoneLoginPage()); + }), + + ], + ), + ), + ) + ], + ); + } +} diff --git a/lib/pages/setting/deactivate_page.dart b/lib/pages/setting/deactivate_page.dart index b0801cb..4f9c720 100644 --- a/lib/pages/setting/deactivate_page.dart +++ b/lib/pages/setting/deactivate_page.dart @@ -3,6 +3,7 @@ import 'package:dating_touchme_app/controller/mine/deactivate_controller.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/login_page.dart'; +import 'package:dating_touchme_app/pages/mine/real_login_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; @@ -164,7 +165,7 @@ class DeactivatePage extends StatelessWidget { ), onTap: () { controller.logout(); - Get.offAll(() => LoginPage()); + Get.offAll(() => RealLoginPage()); }, ), ], diff --git a/lib/pages/setting/setting_page.dart b/lib/pages/setting/setting_page.dart index 3043ca7..f13933a 100644 --- a/lib/pages/setting/setting_page.dart +++ b/lib/pages/setting/setting_page.dart @@ -15,6 +15,7 @@ import 'package:tdesign_flutter/tdesign_flutter.dart'; import '../../components/page_appbar.dart'; import '../../controller/setting/setting_controller.dart'; +import '../mine/real_login_page.dart'; import 'blacklist_page.dart'; import 'notice_page.dart'; @@ -183,7 +184,7 @@ class SettingPage extends StatelessWidget { ), onTap: () { controller.logout(); - Get.offAll(() => LoginPage()); + Get.offAll(() => RealLoginPage()); }, ), ], diff --git a/lib/widget/message/voice_input_view.dart b/lib/widget/message/voice_input_view.dart index f7931a6..5a36fd1 100644 --- a/lib/widget/message/voice_input_view.dart +++ b/lib/widget/message/voice_input_view.dart @@ -56,10 +56,11 @@ class _VoiceInputViewState extends State { // 开始录音 Future _startRecording() async { // 请求麦克风权限 - final status = await Permission.microphone.request(); - if (!status.isGranted) { - return; - } + // final status = await Permission.microphone.request(); + // print(status); + // if (!status.isGranted) { + // return; + // } try { if (await _audioRecorder.hasPermission()) { @@ -139,6 +140,7 @@ class _VoiceInputViewState extends State { // 处理长按开始 void _onLongPressStart(LongPressStartDetails details) { + print(11111); _panStartPosition = details.globalPosition; _startRecording(); } @@ -334,6 +336,7 @@ class _VoiceInputViewState extends State { // 麦克风按钮 Listener( onPointerDown: (details) { + print(123123); // 记录初始位置,用于后续拖拽检测 _panStartPosition = details.position; }, diff --git a/pubspec.yaml b/pubspec.yaml index a47de6e..c4eb228 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -66,7 +66,7 @@ dependencies: video_thumbnail: ^0.5.3 # 视频缩略图生成 fluwx: ^5.7.5 # # tobias: ^5.3.1 - agora_rtc_engine: ^6.5.3 + agora_rtc_engine: 6.5.1 agora_rtm: ^2.2.5 agora_token_generator: ^1.0.0 location_plugin: