diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a2a967bc..341d6fae 100755 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -29,6 +29,9 @@ + + + diff --git a/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart b/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart index b908e07a..e13c01bd 100755 --- a/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart +++ b/lib/main/lockDetail/authorizedAdmin/authorizedAdmin/authorizedAdmin_page.dart @@ -257,15 +257,42 @@ class _AuthorizedAdminPageState extends State onTap: () async { final Contact? currentContact = await logic.state.contactPicker.selectContact(); - logic.state.contact = currentContact!; - if (currentContact.phoneNumbers!.isNotEmpty) { - logic.state.emailOrPhoneController.text = currentContact - .phoneNumbers![0] - .replaceAll(RegExp(r'\s+\b|\b\s'), ''); - } - if (currentContact.fullName!.isNotEmpty) { - logic.state.keyNameController.text = - currentContact.fullName!; + if (currentContact != null) { + setState(() { + logic.state.contact = currentContact; + + // 处理手机号 + if (currentContact.phoneNumbers != null && + currentContact.phoneNumbers!.isNotEmpty) { + // 获取第一个手机号并清理格式 + String phoneNumber = currentContact.phoneNumbers![0]; + // 移除所有空格、括号、连字符等特殊字符 + phoneNumber = + phoneNumber.replaceAll(RegExp(r'[\s\(\)\-]'), ''); + // 如果号码以+开头,保留+号 + if (phoneNumber.startsWith('+')) { + phoneNumber = '+' + + phoneNumber + .substring(1) + .replaceAll(RegExp(r'[^\d]'), ''); + } else { + phoneNumber = + phoneNumber.replaceAll(RegExp(r'[^\d]'), ''); + } + logic.state.emailOrPhoneController.text = phoneNumber; + } else { + logic.state.emailOrPhoneController.text = ''; + } + + // 处理姓名 + if (currentContact.fullName != null && + currentContact.fullName!.isNotEmpty) { + logic.state.keyNameController.text = + currentContact.fullName!; + } else { + logic.state.keyNameController.text = ''; + } + }); } }, ), @@ -602,17 +629,42 @@ class _AuthorizedAdminPageState extends State onTap: () async { final Contact? currentContact = await state.contactPicker.selectContact(); - setState(() { - state.contact = currentContact!; - if (currentContact.phoneNumbers!.isNotEmpty) { - state.emailOrPhoneController.text = currentContact - .phoneNumbers![0] - .replaceAll(RegExp(r'\s+\b|\b\s'), ''); - } - if (currentContact.fullName!.isNotEmpty) { - state.keyNameController.text = currentContact.fullName!; - } - }); + if (currentContact != null) { + setState(() { + state.contact = currentContact; + + // 处理手机号 + if (currentContact.phoneNumbers != null && + currentContact.phoneNumbers!.isNotEmpty) { + // 获取第一个手机号并清理格式 + String phoneNumber = currentContact.phoneNumbers![0]; + // 移除所有空格、括号、连字符等特殊字符 + phoneNumber = + phoneNumber.replaceAll(RegExp(r'[\s\(\)\-]'), ''); + // 如果号码以+开头,保留+号 + if (phoneNumber.startsWith('+')) { + phoneNumber = '+' + + phoneNumber + .substring(1) + .replaceAll(RegExp(r'[^\d]'), ''); + } else { + phoneNumber = + phoneNumber.replaceAll(RegExp(r'[^\d]'), ''); + } + state.emailOrPhoneController.text = phoneNumber; + } else { + state.emailOrPhoneController.text = ''; + } + + // 处理姓名 + if (currentContact.fullName != null && + currentContact.fullName!.isNotEmpty) { + state.keyNameController.text = currentContact.fullName!; + } else { + state.keyNameController.text = ''; + } + }); + } }, ), ) diff --git a/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_page.dart b/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_page.dart index da455907..c4e62f99 100755 --- a/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_page.dart +++ b/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_page.dart @@ -20,6 +20,7 @@ import 'package:star_lock/tools/pickers/time_picker/model/pduration.dart'; import 'package:star_lock/tools/regularExpression.dart'; import 'package:star_lock/tools/showTipView.dart'; import 'package:star_lock/tools/submitBtn.dart'; +import 'package:permission_handler/permission_handler.dart'; class SendElectronicKeyView extends StatefulWidget { SendElectronicKeyView({required this.type, Key? key}) : super(key: key); @@ -31,6 +32,14 @@ class SendElectronicKeyView extends StatefulWidget { class _SendElectronicKeyViewState extends State with AutomaticKeepAliveClientMixin { + late FlutterContactPicker _contactPicker; + + @override + void initState() { + super.initState(); + _contactPicker = FlutterContactPicker(); + } + @override Widget build(BuildContext context) { super.build(context); @@ -163,8 +172,8 @@ class _SendElectronicKeyViewState extends State color: Colors.white, border: Border( bottom: BorderSide( - color: AppColors.greyLineColor, // 设置边框颜色 - width: 2.0.h, // 设置边框宽度 + color: AppColors.greyLineColor, + width: 2.0.h, ), )), child: Row( @@ -174,17 +183,14 @@ class _SendElectronicKeyViewState extends State Expanded( child: TextField( controller: logic.getCurrentController(1), - //输入框一行 maxLines: 1, inputFormatters: [ FilteringTextInputFormatter.deny('\n'), LengthLimitingTextInputFormatter(30), ], - // controller: _controller, autofocus: false, textAlign: TextAlign.end, decoration: InputDecoration( - //输入里面输入文字内边距设置 hintText: rightTitle, hintStyle: TextStyle(fontSize: 22.sp), focusedBorder: const OutlineInputBorder( @@ -205,9 +211,7 @@ class _SendElectronicKeyViewState extends State fontSize: 22.sp, textBaseline: TextBaseline.alphabetic), ), ), - SizedBox( - width: 10.w, - ), + SizedBox(width: 10.w), Container( width: 32.w, height: 32.w, @@ -220,24 +224,88 @@ class _SendElectronicKeyViewState extends State alignment: Alignment.center, child: InkWell( onTap: () async { - final Contact? currentContact = - await logic.state.contactPicker.selectContact(); - logic.state.contact = currentContact!; - if (currentContact.phoneNumbers!.isNotEmpty) { - logic.state.emailOrPhoneController.text = currentContact - .phoneNumbers![0] - .replaceAll(RegExp(r'\s+\b|\b\s'), ''); - } - if (currentContact.fullName!.isNotEmpty) { - logic.state.keyNameController.text = - currentContact.fullName!; + try { + final PermissionStatus status = + await Permission.contacts.request(); + if (status.isGranted) { + // 保存当前路由 + final currentRoute = ModalRoute.of(context); + + final Contact? currentContact = + await _contactPicker.selectContact(); + + // 检查路由是否仍然存在且组件是否挂载 + if (currentRoute?.isCurrent == true && mounted) { + // 检查 GetX 控制器是否仍然存在 + if (Get.isRegistered( + tag: widget.type)) { + final logic = Get.find( + tag: widget.type); + + if (currentContact != null) { + // 处理手机号 + if (currentContact.phoneNumbers != null && + currentContact.phoneNumbers!.isNotEmpty) { + String phoneNumber = + currentContact.phoneNumbers![0]; + // 移除所有空格、括号、连字符等特殊字符 + phoneNumber = phoneNumber.replaceAll( + RegExp(r'[\s\(\)\-]'), ''); + // 如果号码以+开头,保留+号 + if (phoneNumber.startsWith('+')) { + phoneNumber = '+' + + phoneNumber + .substring(1) + .replaceAll(RegExp(r'[^\d]'), ''); + } else { + phoneNumber = phoneNumber.replaceAll( + RegExp(r'[^\d]'), ''); + } + logic.state.emailOrPhoneController.text = + phoneNumber; + logic.state.emailOrPhone.value = phoneNumber; + } + + // 处理姓名 + if (currentContact.fullName != null && + currentContact.fullName!.isNotEmpty) { + logic.state.keyNameController.text = + currentContact.fullName!; + } + + // 更新UI + logic.update(); + } + } + } + } else { + // 权限被拒绝,显示提示 + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('需要通讯录权限才能选择联系人'.tr), + duration: const Duration(seconds: 2), + ), + ); + } + } + } catch (e) { + print('Error selecting contact: $e'); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('获取通讯录失败,请检查权限设置'.tr), + duration: const Duration(seconds: 2), + ), + ); + } } }, ), ), Container( - color: AppColors.greyLineColor, // 设置边框颜色 - height: 2.0.h, // + color: AppColors.greyLineColor, + height: 2.0.h, ) ], ), @@ -616,17 +684,65 @@ class _SendElectronicKeyViewState extends State alignment: Alignment.center, child: InkWell( onTap: () async { - final Contact? currentContact = - await logic.state.contactPicker.selectContact(); - logic.state.contact = currentContact!; - if (currentContact.phoneNumbers!.isNotEmpty) { - logic.state.emailOrPhoneController.text = currentContact - .phoneNumbers![0] - .replaceAll(RegExp(r'\s+\b|\b\s'), ''); - } - if (currentContact.fullName!.isNotEmpty) { - logic.state.keyNameController.text = - currentContact.fullName!; + try { + final PermissionStatus status = + await Permission.contacts.request(); + if (status.isGranted) { + final Contact? currentContact = + await _contactPicker.selectContact(); + if (currentContact != null && mounted) { + // 处理手机号 + if (currentContact.phoneNumbers != null && + currentContact.phoneNumbers!.isNotEmpty) { + String phoneNumber = currentContact.phoneNumbers![0]; + // 移除所有空格、括号、连字符等特殊字符 + phoneNumber = + phoneNumber.replaceAll(RegExp(r'[\s\(\)\-]'), ''); + // 如果号码以+开头,保留+号 + if (phoneNumber.startsWith('+')) { + phoneNumber = '+' + + phoneNumber + .substring(1) + .replaceAll(RegExp(r'[^\d]'), ''); + } else { + phoneNumber = + phoneNumber.replaceAll(RegExp(r'[^\d]'), ''); + } + logic.state.emailOrPhoneController.text = phoneNumber; + logic.state.emailOrPhone.value = phoneNumber; + } + + // 处理姓名 + if (currentContact.fullName != null && + currentContact.fullName!.isNotEmpty) { + logic.state.keyNameController.text = + currentContact.fullName!; + } + + // 更新UI + logic.update(); + } + } else { + // 权限被拒绝,显示提示 + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('需要通讯录权限才能选择联系人'.tr), + duration: const Duration(seconds: 2), + ), + ); + } + } + } catch (e) { + print('Error selecting contact: $e'); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('获取通讯录失败,请检查权限设置'.tr), + duration: const Duration(seconds: 2), + ), + ); + } } }, ), @@ -736,7 +852,7 @@ class _SendElectronicKeyViewState extends State child: Text( '取消'.tr, style: TextStyle( - color: Colors.black, fontSize: ScreenUtil().setSp(24)), + color: Colors.black, fontSize: 24.sp), ), onPressed: () { Navigator.pop(context); @@ -779,7 +895,7 @@ class _SendElectronicKeyViewState extends State Text( titleStr, style: TextStyle( - fontSize: ScreenUtil().setSp(20), color: Colors.black), + fontSize: 20.sp, color: Colors.black), ), ], ), diff --git a/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_state.dart b/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_state.dart index 7ada2123..61121249 100755 --- a/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_state.dart +++ b/lib/main/lockDetail/electronicKey/sendElectronicKey/sendElectronicKey/view/sendElectronicKeyView_state.dart @@ -15,8 +15,8 @@ class SendElectronicKeyViewState { TextEditingController realNameController = TextEditingController(); //真实姓名输入框 TextEditingController idCardController = TextEditingController(); //身份证号输入框 - final FlutterContactPicker contactPicker = FlutterContactPicker(); - late Contact contact; + // final FlutterContactPicker contactPicker = FlutterContactPicker(); + // late Contact contact; RxBool isRemoteUnlock = false.obs; //是否允许远程开锁 RxBool isAuthentication = false.obs; //是否可以实名认证 diff --git a/lib/talk/starChart/status/star_chart_talk_status.dart b/lib/talk/starChart/status/star_chart_talk_status.dart index 54ee1751..939c130b 100644 --- a/lib/talk/starChart/status/star_chart_talk_status.dart +++ b/lib/talk/starChart/status/star_chart_talk_status.dart @@ -4,7 +4,7 @@ import 'package:star_lock/talk/starChart/constant/talk_status.dart'; class StartChartTalkStatus { // 私有字段,用于存储当前状态 - TalkStatus _status = TalkStatus.uninitialized; + TalkStatus _status = TalkStatus.none; // 私有化默认构造函数,防止外部创建实例 StartChartTalkStatus._(); diff --git a/pubspec.yaml b/pubspec.yaml index 7819d6e8..0cdf858a 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -155,7 +155,7 @@ dependencies: # 选择日期时间 flutter_cupertino_datetime_picker: ^3.0.0 # 选择原生通讯录 - flutter_native_contact_picker: ^0.0.4 + flutter_native_contact_picker: 0.0.7 #底部弹出选择器 flutter_picker: ^2.1.0 #生成二维码