Merge branch 'develop' into 'canary_release'
Develop See merge request StarlockTeam/app-starlock!27
This commit is contained in:
commit
e9c06cc66d
@ -328,7 +328,7 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
// implementation('com.amap.api:location:5.6.0')
|
// implementation('com.amap.api:location:5.6.0')
|
||||||
// implementation('com.amap.api:3dmap:8.1.0')
|
// implementation('com.amap.api:3dmap:8.1.0')
|
||||||
implementation('com.amap.api:3dmap-location-search:latest.integration')
|
// implementation('com.amap.api:3dmap-location-search:latest.integration')
|
||||||
|
|
||||||
implementation 'cn.jiguang.sdk:jpush:5.2.3'
|
implementation 'cn.jiguang.sdk:jpush:5.2.3'
|
||||||
// 接入华为厂商
|
// 接入华为厂商
|
||||||
|
|||||||
@ -156,9 +156,6 @@ import 'main/lockMian/demoMode/demoModeLockSet/demoModeLockSet_page.dart';
|
|||||||
import 'main/lockMian/lockMain/lockMain_page.dart';
|
import 'main/lockMian/lockMain/lockMain_page.dart';
|
||||||
import 'mine/about/about_page.dart';
|
import 'mine/about/about_page.dart';
|
||||||
import 'mine/addLock/addLock/addLock_page.dart';
|
import 'mine/addLock/addLock/addLock_page.dart';
|
||||||
import 'mine/addLock/addLockSelectCountry/addLockSelectCountry_page.dart';
|
|
||||||
import 'mine/addLock/lockAddress/gaode/lockAddressGaoDe_page.dart';
|
|
||||||
import 'mine/addLock/lockAddress/lockAddress/lockAddress_page.dart';
|
|
||||||
import 'mine/addLock/nearbyLock/nearbyLock_page.dart';
|
import 'mine/addLock/nearbyLock/nearbyLock_page.dart';
|
||||||
import 'mine/addLock/saveLock/saveLock_page.dart';
|
import 'mine/addLock/saveLock/saveLock_page.dart';
|
||||||
import 'mine/addLock/selectLockType/selectLockType_page.dart';
|
import 'mine/addLock/selectLockType/selectLockType_page.dart';
|
||||||
@ -715,10 +712,6 @@ abstract class AppRouters {
|
|||||||
name: Routers.nearbyDoorMagneticPage,
|
name: Routers.nearbyDoorMagneticPage,
|
||||||
page: () => const NearbyDoorMagneticPage(),
|
page: () => const NearbyDoorMagneticPage(),
|
||||||
),
|
),
|
||||||
GetPage<dynamic>(
|
|
||||||
name: Routers.lockAddressPage,
|
|
||||||
page: () => const LockAddressPage(),
|
|
||||||
),
|
|
||||||
GetPage<dynamic>(
|
GetPage<dynamic>(
|
||||||
name: Routers.remoteUnlockingPage,
|
name: Routers.remoteUnlockingPage,
|
||||||
page: () => const RemoteUnlockingPage(),
|
page: () => const RemoteUnlockingPage(),
|
||||||
@ -1007,9 +1000,6 @@ abstract class AppRouters {
|
|||||||
GetPage<dynamic>(
|
GetPage<dynamic>(
|
||||||
name: Routers.adminDetailChangeDatePage,
|
name: Routers.adminDetailChangeDatePage,
|
||||||
page: () => const AdminDetailChangeDatePage()),
|
page: () => const AdminDetailChangeDatePage()),
|
||||||
GetPage<dynamic>(
|
|
||||||
name: Routers.lockAddressGaoDePage,
|
|
||||||
page: () => const LockAddressGaoDePage()),
|
|
||||||
GetPage<dynamic>(
|
GetPage<dynamic>(
|
||||||
name: Routers.safeVerifyPage, page: () => const SafeVerifyPage()),
|
name: Routers.safeVerifyPage, page: () => const SafeVerifyPage()),
|
||||||
GetPage<dynamic>(
|
GetPage<dynamic>(
|
||||||
@ -1023,9 +1013,6 @@ abstract class AppRouters {
|
|||||||
GetPage<dynamic>(
|
GetPage<dynamic>(
|
||||||
name: Routers.demoModeLockDetailPage,
|
name: Routers.demoModeLockDetailPage,
|
||||||
page: () => const DemoModeLockDetailPage()),
|
page: () => const DemoModeLockDetailPage()),
|
||||||
GetPage<dynamic>(
|
|
||||||
name: Routers.addLockSelectCountryPage,
|
|
||||||
page: () => const AddLockSelectCountryPage()),
|
|
||||||
GetPage<dynamic>(
|
GetPage<dynamic>(
|
||||||
name: Routers.faceUnlockPage, page: () => const FaceUnlockPage()),
|
name: Routers.faceUnlockPage, page: () => const FaceUnlockPage()),
|
||||||
GetPage<dynamic>(
|
GetPage<dynamic>(
|
||||||
|
|||||||
@ -262,7 +262,7 @@ class BlueManage {
|
|||||||
for (final ScanResult scanResult in results) {
|
for (final ScanResult scanResult in results) {
|
||||||
if (scanResult.advertisementData.serviceUuids.isNotEmpty) {
|
if (scanResult.advertisementData.serviceUuids.isNotEmpty) {
|
||||||
// AppLog.log(
|
// AppLog.log(
|
||||||
// '扫描到的设备:${scanResult.advertisementData.serviceUuids[0].toString()}');
|
// '扫描到的设备:${scanResult.advertisementData.serviceUuids[0].toString()}====${scanResult.advertisementData.advName}');
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -315,20 +315,30 @@ class BlueManage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 判断是否包含指定的uuid
|
/// 判断是否包含指定的uuid
|
||||||
bool _isMatch(List<String> serviceUuids,
|
bool _isMatch(List<String> serviceUuids, {DeviceType deviceType = DeviceType.blue}) {
|
||||||
{DeviceType deviceType = DeviceType.blue}) {
|
final List<String> prefixes = getDeviceType(deviceType).map((e) => e.toLowerCase()).toList();
|
||||||
// 获取设备类型数组
|
for (String uuid in serviceUuids) {
|
||||||
List<String> deviceTypeList = getDeviceType(deviceType);
|
final String cleanUuid = uuid.replaceAll('-', '').toLowerCase();
|
||||||
|
if (cleanUuid.length == 8) {
|
||||||
// 检查 serviceUuids 是否包含 deviceTypeList 中的任意一个值
|
// 8位,判断前两位
|
||||||
if (serviceUuids != null && serviceUuids.isNotEmpty) {
|
for (final prefix in prefixes) {
|
||||||
return serviceUuids.any((uuid) {
|
if (cleanUuid.startsWith(prefix)) {
|
||||||
return deviceTypeList
|
return true;
|
||||||
.any((type) => uuid.toLowerCase().contains(type.toLowerCase()));
|
}
|
||||||
});
|
}
|
||||||
|
} else if (cleanUuid.length == 32) {
|
||||||
|
// 128位,判断前8位的第3、第4位
|
||||||
|
final String first8 = cleanUuid.substring(0, 8);
|
||||||
|
if (first8.length >= 4) {
|
||||||
|
final String thirdAndFourth = first8.substring(2, 4); // 索引2和3
|
||||||
|
for (final prefix in prefixes) {
|
||||||
|
if (thirdAndFourth == prefix) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果 serviceUuids 为空,则返回 false
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ List<String> getDeviceType(DeviceType deviceType) {
|
|||||||
List<String> t = ['758824'];
|
List<String> t = ['758824'];
|
||||||
switch (deviceType) {
|
switch (deviceType) {
|
||||||
case DeviceType.blue:
|
case DeviceType.blue:
|
||||||
t = ['758824', '75'];
|
t = ['758824', '75', '768824', '76'];
|
||||||
break;
|
break;
|
||||||
case DeviceType.gateway:
|
case DeviceType.gateway:
|
||||||
t = ['758825'];
|
t = ['758825'];
|
||||||
|
|||||||
@ -76,7 +76,6 @@ class _StarLockRegisterPageState extends State<StarLockRegisterPage> {
|
|||||||
Container(
|
Container(
|
||||||
width: 340.w,
|
width: 340.w,
|
||||||
height: 60.h,
|
height: 60.h,
|
||||||
// color: Colors.red,
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(30.h)),
|
borderRadius: BorderRadius.all(Radius.circular(30.h)),
|
||||||
border:
|
border:
|
||||||
@ -119,28 +118,22 @@ class _StarLockRegisterPageState extends State<StarLockRegisterPage> {
|
|||||||
child: Obx(
|
child: Obx(
|
||||||
() => Container(
|
() => Container(
|
||||||
height: 60.h,
|
height: 60.h,
|
||||||
// color: Colors.red,
|
decoration: !state.isIphoneType.value
|
||||||
decoration: state.isIphoneType.value
|
? BoxDecoration(
|
||||||
? null
|
|
||||||
: BoxDecoration(
|
|
||||||
color: AppColors.mainColor,
|
color: AppColors.mainColor,
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius:
|
||||||
Radius.circular(
|
BorderRadius.all(Radius.circular(30.h)),
|
||||||
30.h,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
width: 1.0,
|
width: 1.0,
|
||||||
color: AppColors.greyLineColor,
|
color: AppColors.greyLineColor))
|
||||||
),
|
: null,
|
||||||
),
|
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'邮箱'.tr,
|
'邮箱'.tr,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: state.isIphoneType.value
|
color: !state.isIphoneType.value
|
||||||
? Colors.black
|
? Colors.white
|
||||||
: Colors.white,
|
: Colors.black,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -3,8 +3,11 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
class StarLockRegisterState {
|
class StarLockRegisterState {
|
||||||
|
|
||||||
StarLockRegisterState() {
|
StarLockRegisterState() {
|
||||||
|
// 根据系统语言设置默认选中的tab
|
||||||
|
final Locale? systemLocale = Get.deviceLocale;
|
||||||
|
isIphoneType.value = systemLocale?.languageCode == 'zh';
|
||||||
|
|
||||||
resetResend();
|
resetResend();
|
||||||
}
|
}
|
||||||
final TextEditingController phoneOrEmailController = TextEditingController();
|
final TextEditingController phoneOrEmailController = TextEditingController();
|
||||||
@ -22,16 +25,21 @@ class StarLockRegisterState {
|
|||||||
RxString verificationCode = ''.obs;
|
RxString verificationCode = ''.obs;
|
||||||
RxString xWidth = ''.obs; // 滑动验证码滑动位置
|
RxString xWidth = ''.obs; // 滑动验证码滑动位置
|
||||||
RxBool isIphoneType = true.obs;
|
RxBool isIphoneType = true.obs;
|
||||||
RxBool canSub = false.obs;// 是否能提交
|
RxBool canSub = false.obs; // 是否能提交
|
||||||
RxBool agree = false.obs;
|
RxBool agree = false.obs;
|
||||||
RxBool canSendCode = false.obs;// 是否能发送验证码
|
RxBool canSendCode = false.obs; // 是否能发送验证码
|
||||||
|
|
||||||
// bool get isEmail => RegexUtil.isEmail(phoneOrEmailStr.value);
|
// bool get isEmail => RegexUtil.isEmail(phoneOrEmailStr.value);
|
||||||
// bool get isIphone => RegexUtil.isMobileSimple(phoneOrEmailStr.value);
|
// bool get isIphone => RegexUtil.isMobileSimple(phoneOrEmailStr.value);
|
||||||
bool get pwdIsOK => pwd.value.isNotEmpty && surePwd.value.isNotEmpty && pwd.value.length >= 8 && surePwd.value.length >= 8;
|
bool get pwdIsOK =>
|
||||||
bool get codeIsOK => verificationCode.value.isNotEmpty && verificationCode.value.length >= 6 ;
|
pwd.value.isNotEmpty &&
|
||||||
|
surePwd.value.isNotEmpty &&
|
||||||
|
pwd.value.length >= 8 &&
|
||||||
|
surePwd.value.length >= 8;
|
||||||
|
bool get codeIsOK =>
|
||||||
|
verificationCode.value.isNotEmpty && verificationCode.value.length >= 6;
|
||||||
|
|
||||||
RxBool canResend = false.obs;// 是否能重新发送,就是验证码倒计时之后的重新发送
|
RxBool canResend = false.obs; // 是否能重新发送,就是验证码倒计时之后的重新发送
|
||||||
RxString btnText = ''.obs;
|
RxString btnText = ''.obs;
|
||||||
int totalSeconds = 120;
|
int totalSeconds = 120;
|
||||||
int currentSecond = 120;
|
int currentSecond = 120;
|
||||||
@ -39,9 +47,8 @@ class StarLockRegisterState {
|
|||||||
|
|
||||||
void resetResend() {
|
void resetResend() {
|
||||||
canResend.value = totalSeconds == currentSecond;
|
canResend.value = totalSeconds == currentSecond;
|
||||||
btnText.value = !canResend.value
|
btnText.value =
|
||||||
? '$currentSecond s'
|
!canResend.value ? '$currentSecond s' : btnText.value = '获取验证码'.tr;
|
||||||
: btnText.value = '获取验证码'.tr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onClose() {
|
void onClose() {
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
@ -74,6 +73,7 @@ class _StarLockRegisterPageState extends State<StarLockRegisterXHJPage> {
|
|||||||
height: 80.h,
|
height: 80.h,
|
||||||
child: DefaultTabController(
|
child: DefaultTabController(
|
||||||
length: 2,
|
length: 2,
|
||||||
|
initialIndex: state.isIphoneType.value ? 0 : 1,
|
||||||
child: TabBar(
|
child: TabBar(
|
||||||
onTap: (int index) {
|
onTap: (int index) {
|
||||||
state.isIphoneType.value = index == 0;
|
state.isIphoneType.value = index == 0;
|
||||||
@ -84,10 +84,7 @@ class _StarLockRegisterPageState extends State<StarLockRegisterXHJPage> {
|
|||||||
}),
|
}),
|
||||||
dividerHeight: 0,
|
dividerHeight: 0,
|
||||||
indicatorSize: TabBarIndicatorSize.tab,
|
indicatorSize: TabBarIndicatorSize.tab,
|
||||||
tabs: <Widget>[
|
tabs: <Widget>[Text('手机'.tr), Text('邮箱'.tr)],
|
||||||
Text('手机'.tr),
|
|
||||||
Text('邮箱'.tr)
|
|
||||||
],
|
|
||||||
indicatorColor: AppColors.mainColor,
|
indicatorColor: AppColors.mainColor,
|
||||||
labelStyle:
|
labelStyle:
|
||||||
TextStyle(color: AppColors.mainColor, fontSize: 26.sp),
|
TextStyle(color: AppColors.mainColor, fontSize: 26.sp),
|
||||||
@ -144,7 +141,7 @@ class _StarLockRegisterPageState extends State<StarLockRegisterXHJPage> {
|
|||||||
logic.checkNext(state.phoneOrEmailController);
|
logic.checkNext(state.phoneOrEmailController);
|
||||||
},
|
},
|
||||||
leftWidget: SizedBox(),
|
leftWidget: SizedBox(),
|
||||||
label:state.isIphoneType.value ? '请输入手机号'.tr : '请输入邮箱'.tr,
|
label: state.isIphoneType.value ? '请输入手机号'.tr : '请输入邮箱'.tr,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
inputFormatters: <TextInputFormatter>[
|
inputFormatters: <TextInputFormatter>[
|
||||||
LengthLimitingTextInputFormatter(30),
|
LengthLimitingTextInputFormatter(30),
|
||||||
@ -163,7 +160,7 @@ class _StarLockRegisterPageState extends State<StarLockRegisterXHJPage> {
|
|||||||
Text(
|
Text(
|
||||||
'密码必须是8-20位,至少包括数字/字母/符号中的2种'.tr,
|
'密码必须是8-20位,至少包括数字/字母/符号中的2种'.tr,
|
||||||
style:
|
style:
|
||||||
TextStyle(color: AppColors.placeholderTextColor, fontSize: 20.sp),
|
TextStyle(color: AppColors.placeholderTextColor, fontSize: 20.sp),
|
||||||
),
|
),
|
||||||
LoginInput(
|
LoginInput(
|
||||||
controller: state.sureController,
|
controller: state.sureController,
|
||||||
@ -235,32 +232,31 @@ class _StarLockRegisterPageState extends State<StarLockRegisterXHJPage> {
|
|||||||
|
|
||||||
Widget _buildBottomAgreement() {
|
Widget _buildBottomAgreement() {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(bottom:20.w),
|
padding: EdgeInsets.only(bottom: 20.w),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Obx(() => GestureDetector(
|
Obx(() => GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
state.agree.value = !state.agree.value;
|
state.agree.value = !state.agree.value;
|
||||||
logic.changeAgreeState();
|
logic.changeAgreeState();
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 40.w,
|
width: 40.w,
|
||||||
height: 40.w,
|
height: 40.w,
|
||||||
// color: Colors.red,
|
// color: Colors.red,
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: 5.w,
|
left: 5.w,
|
||||||
right: 10.w,
|
right: 10.w,
|
||||||
),
|
),
|
||||||
child: Image.asset(
|
child: Image.asset(
|
||||||
state.agree.value
|
state.agree.value
|
||||||
? 'images/icon_round_select.png'
|
? 'images/icon_round_select.png'
|
||||||
: 'images/icon_round_unSelect.png',
|
: 'images/icon_round_unSelect.png',
|
||||||
width: 20.w,
|
width: 20.w,
|
||||||
height: 20.w,
|
height: 20.w,
|
||||||
),
|
),
|
||||||
)
|
))),
|
||||||
)),
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 10.w,
|
width: 10.w,
|
||||||
),
|
),
|
||||||
@ -268,14 +264,12 @@ class _StarLockRegisterPageState extends State<StarLockRegisterXHJPage> {
|
|||||||
child: RichText(
|
child: RichText(
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
text: '我已阅读并同意'.tr,
|
text: '我已阅读并同意'.tr,
|
||||||
style:
|
style: TextStyle(color: const Color(0xff333333), fontSize: 20.sp),
|
||||||
TextStyle(color: const Color(0xff333333), fontSize: 20.sp),
|
|
||||||
children: <InlineSpan>[
|
children: <InlineSpan>[
|
||||||
WidgetSpan(
|
WidgetSpan(
|
||||||
alignment: PlaceholderAlignment.middle,
|
alignment: PlaceholderAlignment.middle,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
child: Text(
|
child: Text('《${'用户协议'.tr}》',
|
||||||
'《${'用户协议'.tr}》',
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: AppColors.mainColor, fontSize: 20.sp)),
|
color: AppColors.mainColor, fontSize: 20.sp)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -289,8 +283,7 @@ class _StarLockRegisterPageState extends State<StarLockRegisterXHJPage> {
|
|||||||
WidgetSpan(
|
WidgetSpan(
|
||||||
alignment: PlaceholderAlignment.middle,
|
alignment: PlaceholderAlignment.middle,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
child: Text(
|
child: Text('《${'隐私政策'.tr}》',
|
||||||
'《${'隐私政策'.tr}》',
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: AppColors.mainColor, fontSize: 20.sp)),
|
color: AppColors.mainColor, fontSize: 20.sp)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
import '../../../tools/baseGetXController.dart';
|
|
||||||
import 'addLockSelectCountry_state.dart';
|
|
||||||
|
|
||||||
class AddLockSelectCountryLogic extends BaseGetXController {
|
|
||||||
AddLockSelectCountryState state = AddLockSelectCountryState();
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,187 +0,0 @@
|
|||||||
|
|
||||||
import 'package:azlistview/azlistview.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:star_lock/mine/addLock/addLockSelectCountry/addLockSelectCountry_state.dart';
|
|
||||||
import 'package:star_lock/tools/baseGetXController.dart';
|
|
||||||
|
|
||||||
import '../../../appRouters.dart';
|
|
||||||
import '../../../app_settings/app_colors.dart';
|
|
||||||
import '../../../login/selectCountryRegion/common/countryRegionEntity.dart';
|
|
||||||
import '../../../network/api_repository.dart';
|
|
||||||
import '../../../tools/commonItem.dart';
|
|
||||||
import '../../../tools/titleAppBar.dart';
|
|
||||||
import 'addLockSelectCountry_logic.dart';
|
|
||||||
|
|
||||||
class AddLockSelectCountryPage extends StatefulWidget {
|
|
||||||
const AddLockSelectCountryPage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<AddLockSelectCountryPage> createState() => _AddLockSelectCountryPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AddLockSelectCountryPageState extends State<AddLockSelectCountryPage> {
|
|
||||||
final AddLockSelectCountryLogic logic = Get.put(AddLockSelectCountryLogic());
|
|
||||||
final AddLockSelectCountryState state = Get.find<AddLockSelectCountryLogic>().state;
|
|
||||||
|
|
||||||
List<CountryRegionModel> countriesList = [];
|
|
||||||
int selectindex = 10000;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
SuspensionUtil.setShowSuspensionStatus(
|
|
||||||
countriesList.cast<ISuspensionBean>());
|
|
||||||
Future.delayed(const Duration(milliseconds: 20), getCountriesListRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
//请求国家/地区json文件
|
|
||||||
Future<void> getCountriesListRequest() async {
|
|
||||||
final CountryRegionEntity entity = await ApiRepository.to.getCountryRegion('1');
|
|
||||||
countriesList.clear();
|
|
||||||
if (entity.errorCode!.codeIsSuccessful) {
|
|
||||||
countriesList.addAll(entity.dataList!);
|
|
||||||
_handleList(countriesList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> loadJsonFromAssets(String assetsPath) async {
|
|
||||||
return await rootBundle.loadString(assetsPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _handleList(List<CountryRegionModel> list) {
|
|
||||||
if (list.isEmpty) return;
|
|
||||||
for (int i = 0, length = list.length; i < length; i++) {
|
|
||||||
final CountryRegionModel countryModel = list[i];
|
|
||||||
final String tag = countryModel.group!;
|
|
||||||
if (RegExp('[A-Z]').hasMatch(tag)) {
|
|
||||||
list[i].tagIndex = tag;
|
|
||||||
} else {
|
|
||||||
list[i].tagIndex = '#';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// A-Z sort.
|
|
||||||
SuspensionUtil.sortListBySuspensionTag(list);
|
|
||||||
// show sus tag.
|
|
||||||
SuspensionUtil.setShowSuspensionStatus(countriesList);
|
|
||||||
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
resizeToAvoidBottomInset: false,
|
|
||||||
backgroundColor: const Color(0xFFFFFFFF),
|
|
||||||
appBar: TitleAppBar(
|
|
||||||
barTitle: '请选择您的位置'.tr,
|
|
||||||
haveBack: true,
|
|
||||||
backgroundColor: AppColors.mainColor,
|
|
||||||
),
|
|
||||||
body: Column(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: ListView.builder(
|
|
||||||
itemCount: countriesList.length,
|
|
||||||
itemBuilder: (BuildContext c, int index) {
|
|
||||||
final CountryRegionModel model = countriesList[index];
|
|
||||||
return CommonItem(
|
|
||||||
leftTitel: model.name,
|
|
||||||
rightTitle: '',
|
|
||||||
allHeight: 60.h,
|
|
||||||
isHaveLine: true,
|
|
||||||
isHaveRightWidget: true,
|
|
||||||
action: (){
|
|
||||||
setState(() {
|
|
||||||
selectindex = index;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
rightWidget: Row(
|
|
||||||
children: [
|
|
||||||
Image.asset((selectindex == index) ? 'images/icon_round_select.png' : 'images/icon_round_unSelect.png', width: 30.w, height: 30.w,),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
margin: EdgeInsets.only(top: 30.h, bottom: 30.h),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
TextButton(
|
|
||||||
child: Text(
|
|
||||||
'跳过'.tr,
|
|
||||||
style: TextStyle(color: Colors.black, fontSize: 24.sp),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
Get.toNamed(Routers.saveLockPage, arguments: {
|
|
||||||
'addressInfo': {},
|
|
||||||
'pwdTimestamp': state.pwdTimestamp.value,
|
|
||||||
'lockInfo': state.lockInfo,
|
|
||||||
'featureValue': state.featureValue,
|
|
||||||
'featureSettingValue': state.featureSettingValue,
|
|
||||||
'featureSettingParams': state.featureSettingParams,
|
|
||||||
'isFromMap': 0,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
child: Text(
|
|
||||||
'下一步'.tr,
|
|
||||||
style: TextStyle(color: Colors.black, fontSize: 24.sp),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
if(selectindex == 10000){
|
|
||||||
logic.showToast('请选择国家'.tr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final CountryRegionModel model = countriesList[selectindex];
|
|
||||||
Get.toNamed(Routers.saveLockPage, arguments: {
|
|
||||||
'addressInfo': {'country':model.name},
|
|
||||||
'pwdTimestamp': state.pwdTimestamp.value,
|
|
||||||
'lockInfo': state.lockInfo,
|
|
||||||
'featureValue': state.featureValue,
|
|
||||||
'featureSettingValue': state.featureSettingValue,
|
|
||||||
'featureSettingParams': state.featureSettingParams,
|
|
||||||
'isFromMap': 0,
|
|
||||||
});
|
|
||||||
// Navigator.pushNamed(context, Routers.saveLockPage);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
// body: AzListView(
|
|
||||||
// data: countriesList,
|
|
||||||
// itemCount: countriesList.length,
|
|
||||||
// itemBuilder: (BuildContext context, int index) {
|
|
||||||
// CountryRegionModel model = countriesList[index];
|
|
||||||
// model.code = " ";
|
|
||||||
// return Utils.getListItem(context, model, () {
|
|
||||||
// Map<String, dynamic> resultMap = {};
|
|
||||||
// resultMap['code'] = model.code;
|
|
||||||
// resultMap['countryId'] = model.countryId.toString();
|
|
||||||
// resultMap['countryName'] = model.name;
|
|
||||||
// Navigator.pop(context, resultMap);
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// padding: EdgeInsets.zero,
|
|
||||||
// susItemBuilder: (BuildContext context, int index) {
|
|
||||||
// CountryRegionModel model = countriesList[index];
|
|
||||||
// String tag = model.getSuspensionTag();
|
|
||||||
// return Utils.getSusItem(context, tag);
|
|
||||||
// },
|
|
||||||
// // indexBarData: const ['★', ...kIndexBarData],
|
|
||||||
// ),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
|
|
||||||
class AddLockSelectCountryState{
|
|
||||||
|
|
||||||
var pwdTimestamp= 0.obs;
|
|
||||||
var lockInfo = {};
|
|
||||||
var featureValue = '';
|
|
||||||
var featureSettingValue = '';
|
|
||||||
var featureSettingParams = [];
|
|
||||||
AddLockSelectCountryState() {
|
|
||||||
Map map = Get.arguments;
|
|
||||||
pwdTimestamp.value = map["pwdTimestamp"];
|
|
||||||
lockInfo = map["lockInfo"];
|
|
||||||
featureValue = map["featureValue"];
|
|
||||||
featureSettingValue = map["featureSettingValue"];
|
|
||||||
featureSettingParams = map["featureSettingParams"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
import 'package:star_lock/tools/baseGetXController.dart';
|
|
||||||
|
|
||||||
import 'lockAddressGaoDe_state.dart';
|
|
||||||
|
|
||||||
class LockAddressGaoDeLogic extends BaseGetXController{
|
|
||||||
LockAddressGaoDeState state = LockAddressGaoDeState();
|
|
||||||
|
|
||||||
void pushAddAction(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onReady() {
|
|
||||||
super.onReady();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onInit() {
|
|
||||||
super.onInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onClose() {
|
|
||||||
super.onClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,386 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:amap_flutter_base/amap_flutter_base.dart';
|
|
||||||
import 'package:amap_flutter_location/amap_flutter_location.dart';
|
|
||||||
import 'package:amap_flutter_location/amap_location_option.dart';
|
|
||||||
import 'package:amap_flutter_map/amap_flutter_map.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
|
||||||
import 'package:star_lock/mine/addLock/lockAddress/gaode/lockAddressGaoDe_state.dart';
|
|
||||||
import 'package:star_lock/widget/permission/permission_dialog.dart';
|
|
||||||
|
|
||||||
import '../../../../appRouters.dart';
|
|
||||||
import '../../../../app_settings/app_colors.dart';
|
|
||||||
import '../../../../flavors.dart';
|
|
||||||
import '../../../../tools/titleAppBar.dart';
|
|
||||||
import 'lockAddressGaoDe_logic.dart';
|
|
||||||
|
|
||||||
class LockAddressGaoDePage extends StatefulWidget {
|
|
||||||
const LockAddressGaoDePage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<LockAddressGaoDePage> createState() => _LockAddressGaoDePageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LockAddressGaoDePageState extends State<LockAddressGaoDePage>
|
|
||||||
with RouteAware {
|
|
||||||
final LockAddressGaoDeLogic logic = Get.put(LockAddressGaoDeLogic());
|
|
||||||
final LockAddressGaoDeState state = Get.find<LockAddressGaoDeLogic>().state;
|
|
||||||
AMapController? mapController;
|
|
||||||
Map<String, Object>? _addressInfo;
|
|
||||||
|
|
||||||
late StreamSubscription<Map<String, Object>> _locationListener;
|
|
||||||
|
|
||||||
AMapFlutterLocation _amapLocationPlugin = AMapFlutterLocation();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
/// 设置是否已经包含高德隐私政策并弹窗展示显示用户查看,如果未包含或者没有弹窗展示,高德定位SDK将不会工作
|
|
||||||
///
|
|
||||||
/// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy
|
|
||||||
/// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b>
|
|
||||||
///
|
|
||||||
/// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy
|
|
||||||
///
|
|
||||||
/// [hasContains] 隐私声明中是否包含高德隐私政策说明
|
|
||||||
///
|
|
||||||
/// [hasShow] 隐私权政策是否弹窗展示告知用户
|
|
||||||
AMapFlutterLocation.updatePrivacyShow(true, true);
|
|
||||||
|
|
||||||
/// 设置是否已经取得用户同意,如果未取得用户同意,高德定位SDK将不会工作
|
|
||||||
///
|
|
||||||
/// 高德SDK合规使用方案请参考官网地址:https://lbs.amap.com/news/sdkhgsy
|
|
||||||
///
|
|
||||||
/// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b>
|
|
||||||
///
|
|
||||||
/// [hasAgree] 隐私权政策是否已经取得用户同意
|
|
||||||
AMapFlutterLocation.updatePrivacyAgree(true);
|
|
||||||
AMapFlutterLocation.setApiKey(F.aMapKey.androidKey, F.aMapKey.iosKey);
|
|
||||||
|
|
||||||
/// 动态申请定位权限
|
|
||||||
requestPermission();
|
|
||||||
|
|
||||||
///设置Android和iOS的apiKey<br>
|
|
||||||
///
|
|
||||||
/// 定位Flutter插件提供了单独的设置ApiKey的接口,
|
|
||||||
/// 使用接口的优先级高于通过Native配置ApiKey的优先级(通过Api接口配置后,通过Native配置文件设置的key将不生效),
|
|
||||||
/// 使用时可根据实际情况决定使用哪种方式
|
|
||||||
///
|
|
||||||
///key的申请请参考高德开放平台官网说明<br>
|
|
||||||
///
|
|
||||||
///Android: https://lbs.amap.com/api/android-location-sdk/guide/create-project/get-key
|
|
||||||
///
|
|
||||||
///iOS: https://lbs.amap.com/api/ios-location-sdk/guide/create-project/get-key
|
|
||||||
// AMapFlutterLocation.setApiKey(
|
|
||||||
// "anroid ApiKey", "ios ApiKey");
|
|
||||||
|
|
||||||
///iOS 获取native精度类型
|
|
||||||
if (Platform.isIOS) {
|
|
||||||
requestAccuracyAuthorization();
|
|
||||||
}
|
|
||||||
|
|
||||||
///注册定位结果监听
|
|
||||||
_locationListener = _amapLocationPlugin
|
|
||||||
.onLocationChanged()
|
|
||||||
.listen((Map<String, Object> result) {
|
|
||||||
setState(() {
|
|
||||||
_addressInfo = result;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
_startLocation();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
|
|
||||||
///移除定位监听
|
|
||||||
_locationListener.cancel();
|
|
||||||
|
|
||||||
///销毁定位
|
|
||||||
_amapLocationPlugin.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
///设置定位参数
|
|
||||||
void _setLocationOption() {
|
|
||||||
AMapLocationOption locationOption = new AMapLocationOption();
|
|
||||||
|
|
||||||
///是否单次定位
|
|
||||||
locationOption.onceLocation = false;
|
|
||||||
|
|
||||||
///是否需要返回逆地理信息
|
|
||||||
locationOption.needAddress = true;
|
|
||||||
|
|
||||||
///逆地理信息的语言类型
|
|
||||||
locationOption.geoLanguage = GeoLanguage.DEFAULT;
|
|
||||||
|
|
||||||
locationOption.desiredLocationAccuracyAuthorizationMode =
|
|
||||||
AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;
|
|
||||||
|
|
||||||
locationOption.fullAccuracyPurposeKey = "AMapLocationScene";
|
|
||||||
|
|
||||||
///设置Android端连续定位的定位间隔
|
|
||||||
locationOption.locationInterval = 2000;
|
|
||||||
|
|
||||||
///设置Android端的定位模式<br>
|
|
||||||
///可选值:<br>
|
|
||||||
///<li>[AMapLocationMode.Battery_Saving]</li>
|
|
||||||
///<li>[AMapLocationMode.Device_Sensors]</li>
|
|
||||||
///<li>[AMapLocationMode.Hight_Accuracy]</li>
|
|
||||||
locationOption.locationMode = AMapLocationMode.Hight_Accuracy;
|
|
||||||
|
|
||||||
///设置iOS端的定位最小更新距离<br>
|
|
||||||
locationOption.distanceFilter = -1;
|
|
||||||
|
|
||||||
///设置iOS端期望的定位精度
|
|
||||||
/// 可选值:<br>
|
|
||||||
/// <li>[DesiredAccuracy.Best] 最高精度</li>
|
|
||||||
/// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
|
|
||||||
/// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
|
|
||||||
/// <li>[DesiredAccuracy.Kilometer] 1000米</li>
|
|
||||||
/// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
|
|
||||||
locationOption.desiredAccuracy = DesiredAccuracy.Best;
|
|
||||||
|
|
||||||
///设置iOS端是否允许系统暂停定位
|
|
||||||
locationOption.pausesLocationUpdatesAutomatically = false;
|
|
||||||
|
|
||||||
///将定位参数设置给定位插件
|
|
||||||
_amapLocationPlugin.setLocationOption(locationOption);
|
|
||||||
}
|
|
||||||
|
|
||||||
///开始定位
|
|
||||||
void _startLocation() {
|
|
||||||
///开始定位之前设置定位参数
|
|
||||||
_setLocationOption();
|
|
||||||
_amapLocationPlugin.startLocation();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
appBar: TitleAppBar(
|
|
||||||
barTitle: '锁地址'.tr,
|
|
||||||
haveBack: true,
|
|
||||||
backgroundColor: AppColors.mainColor,
|
|
||||||
),
|
|
||||||
body: ListView(
|
|
||||||
children: <Widget>[
|
|
||||||
Container(
|
|
||||||
margin: EdgeInsets.only(
|
|
||||||
left: 25.w, right: 25.w, top: 40.h, bottom: 40.w),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
'地理位置'.tr,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(fontSize: 50.sp),
|
|
||||||
softWrap: true,
|
|
||||||
overflow: TextOverflow.visible,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
child: (_addressInfo != null &&
|
|
||||||
_addressInfo!.containsKey('latitude'))
|
|
||||||
? Column(
|
|
||||||
children: <Widget>[
|
|
||||||
SizedBox(
|
|
||||||
height: 1.sw / 5 * 4,
|
|
||||||
width: 1.sw,
|
|
||||||
child: AMapWidget(
|
|
||||||
apiKey: AMapApiKey(
|
|
||||||
iosKey: F.aMapKey.iosKey,
|
|
||||||
androidKey: F.aMapKey.androidKey),
|
|
||||||
// 初始化地图中心
|
|
||||||
initialCameraPosition: CameraPosition(
|
|
||||||
target: LatLng(
|
|
||||||
double.parse(
|
|
||||||
_addressInfo!['latitude'].toString()),
|
|
||||||
double.parse(
|
|
||||||
_addressInfo!['longitude'].toString())),
|
|
||||||
zoom: 10.0,
|
|
||||||
),
|
|
||||||
//定位小蓝点
|
|
||||||
myLocationStyleOptions: MyLocationStyleOptions(
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
// 普通地图normal,卫星地图satellite,夜间视图night,导航视图 navi,公交视图bus,
|
|
||||||
mapType: MapType.normal,
|
|
||||||
// 缩放级别范围
|
|
||||||
minMaxZoomPreference:
|
|
||||||
const MinMaxZoomPreference(3, 20),
|
|
||||||
// 隐私政策包含高德 必须填写
|
|
||||||
privacyStatement: const AMapPrivacyStatement(
|
|
||||||
hasAgree: true, hasContains: true, hasShow: true),
|
|
||||||
// 地图创建成功时返回AMapController
|
|
||||||
onMapCreated: (AMapController controller) {
|
|
||||||
mapController = controller;
|
|
||||||
},
|
|
||||||
onLocationChanged: (AMapLocation location) {
|
|
||||||
print("onLocationChanged ${location}");
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
// color: Colors.red,
|
|
||||||
margin:
|
|
||||||
EdgeInsets.only(left: 25.w, top: 20.h, right: 25.w),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
Flexible(
|
|
||||||
child: Text('检查以确保以下地址是正确的'.tr,
|
|
||||||
style: TextStyle(fontSize: 24.sp))),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// SizedBox(height: 20.h),
|
|
||||||
Container(
|
|
||||||
// color: Colors.red,
|
|
||||||
// height: 45.h,
|
|
||||||
margin: EdgeInsets.only(
|
|
||||||
left: 25.w, top: 20.h, right: 25.w),
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
_addressInfo!['address'].toString() ??
|
|
||||||
'',
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.grey,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
overflow: TextOverflow.clip))),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 5.h),
|
|
||||||
Container(
|
|
||||||
height: 1.h,
|
|
||||||
color: AppColors.mainColor,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: SizedBox(
|
|
||||||
height: 1.sw / 5 * 4 + 65.h * 2,
|
|
||||||
child: Center(child: Text('地图加载中,请稍候。。。'.tr))),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
constraints: BoxConstraints(maxHeight: 150.h),
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: <Widget>[
|
|
||||||
TextButton(
|
|
||||||
child: Text(
|
|
||||||
'跳过'.tr,
|
|
||||||
style: TextStyle(color: Colors.black, fontSize: 24.sp),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
Get.toNamed(Routers.addLockSelectCountryPage,
|
|
||||||
arguments: <String, Object>{
|
|
||||||
'addressInfo': {},
|
|
||||||
'pwdTimestamp': state.pwdTimestamp.value,
|
|
||||||
'lockInfo': state.lockInfo,
|
|
||||||
'featureValue': state.featureValue,
|
|
||||||
'featureSettingValue': state.featureSettingValue,
|
|
||||||
'featureSettingParams': state.featureSettingParams,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
child: Text(
|
|
||||||
'下一步'.tr,
|
|
||||||
style: TextStyle(color: Colors.black, fontSize: 24.sp),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
if (_addressInfo!.isEmpty) {
|
|
||||||
logic.showToast('还未获取到位置信息哦,请耐心等待一下!'.tr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Get.toNamed(Routers.saveLockPage,
|
|
||||||
arguments: <String, Object?>{
|
|
||||||
'addressInfo': _addressInfo,
|
|
||||||
'pwdTimestamp': state.pwdTimestamp.value,
|
|
||||||
'lockInfo': state.lockInfo,
|
|
||||||
'featureValue': state.featureValue,
|
|
||||||
'featureSettingValue': state.featureSettingValue,
|
|
||||||
'featureSettingParams': state.featureSettingParams,
|
|
||||||
'isFromMap': 1,
|
|
||||||
});
|
|
||||||
// Navigator.pushNamed(context, Routers.saveLockPage);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
///获取iOS native的accuracyAuthorization类型
|
|
||||||
void requestAccuracyAuthorization() async {
|
|
||||||
AMapAccuracyAuthorization currentAccuracyAuthorization =
|
|
||||||
await _amapLocationPlugin.getSystemAccuracyAuthorization();
|
|
||||||
if (currentAccuracyAuthorization ==
|
|
||||||
AMapAccuracyAuthorization.AMapAccuracyAuthorizationFullAccuracy) {
|
|
||||||
print("精确定位类型");
|
|
||||||
} else if (currentAccuracyAuthorization ==
|
|
||||||
AMapAccuracyAuthorization.AMapAccuracyAuthorizationReducedAccuracy) {
|
|
||||||
print("模糊定位类型");
|
|
||||||
} else {
|
|
||||||
print("未知定位类型");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 动态申请定位权限
|
|
||||||
void requestPermission() async {
|
|
||||||
// 申请权限
|
|
||||||
final bool hasLocationPermission =
|
|
||||||
await PermissionDialog.request(Permission.location);
|
|
||||||
if (hasLocationPermission) {
|
|
||||||
print("定位权限申请通过");
|
|
||||||
} else {
|
|
||||||
print("定位权限申请不通过");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 从上级界面进入 当前界面即将出现
|
|
||||||
@override
|
|
||||||
void didPush() {
|
|
||||||
super.didPush();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 返回上一个界面 当前界面即将消失
|
|
||||||
@override
|
|
||||||
void didPop() {
|
|
||||||
super.didPop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 从下级返回 当前界面即将出现
|
|
||||||
@override
|
|
||||||
void didPopNext() {
|
|
||||||
super.didPopNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 进入下级界面 当前界面即将消失
|
|
||||||
@override
|
|
||||||
void didPushNext() {
|
|
||||||
super.didPushNext();
|
|
||||||
|
|
||||||
_amapLocationPlugin.stopLocation();
|
|
||||||
_amapLocationPlugin.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
|
|
||||||
import 'package:amap_flutter_location/amap_flutter_location.dart';
|
|
||||||
import 'package:amap_flutter_map/amap_flutter_map.dart';
|
|
||||||
import 'package:amap_flutter_base/amap_flutter_base.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
|
||||||
|
|
||||||
class LockAddressGaoDeState{
|
|
||||||
|
|
||||||
var pwdTimestamp= 0.obs;
|
|
||||||
var lockInfo = {};
|
|
||||||
var featureValue = '';
|
|
||||||
var featureSettingValue = '';
|
|
||||||
var featureSettingParams = [];
|
|
||||||
|
|
||||||
LockAddressGaoDeState() {
|
|
||||||
Map map = Get.arguments;
|
|
||||||
pwdTimestamp.value = map["pwdTimestamp"];
|
|
||||||
lockInfo = map["lockInfo"];
|
|
||||||
featureValue = map["featureValue"];
|
|
||||||
featureSettingValue = map["featureSettingValue"];
|
|
||||||
featureSettingParams = map["featureSettingParams"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
// import 'package:google_maps_flutter/google_maps_flutter.dart';
|
|
||||||
|
|
||||||
class LockAddressGooglePage extends StatefulWidget {
|
|
||||||
const LockAddressGooglePage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<LockAddressGooglePage> createState() => _LockAddressGooglePageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LockAddressGooglePageState extends State<LockAddressGooglePage> {
|
|
||||||
|
|
||||||
var deviceFindData = Get.arguments['data'];
|
|
||||||
var source;
|
|
||||||
var result;
|
|
||||||
|
|
||||||
// LatLng _kMapCenter;
|
|
||||||
// CameraPosition _kInitialPosition;
|
|
||||||
|
|
||||||
var _markers;
|
|
||||||
var setmarkers;
|
|
||||||
var restaurantMarker;
|
|
||||||
bool isSetupReady = false;
|
|
||||||
|
|
||||||
String? currentAddress;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
// doSetup();
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// doSetup() async {
|
|
||||||
// List<Placemark> placemarks = await placemarkFromCoordinates(deviceFindData.latitude, deviceFindData.longitude);
|
|
||||||
// Placemark place1 = placemarks[0];
|
|
||||||
// currentAddress = "${place1.country} ${place1.administrativeArea} ${place1.locality} ${place1.subLocality} ${place1.name}";
|
|
||||||
// // AppLog.log("objectfasdfasdfasdfasdf:${placemarks}fasdfasdf${place1} ${currentAddress}");
|
|
||||||
//
|
|
||||||
// restaurantMarker = await BitmapDescriptor.fromAssetImage(
|
|
||||||
// ImageConfiguration(size: Size(w(27), h(31))), Platform.isIOS ? R.assetsImgsDeviceFindDeviceIcon : R.assetsImgsDeviceFindDeviceAndroidIcon);
|
|
||||||
// _markers = [
|
|
||||||
// Marker(
|
|
||||||
// markerId: MarkerId("marker_2"),
|
|
||||||
// infoWindow: InfoWindow(title: currentAddress),
|
|
||||||
// icon: restaurantMarker,
|
|
||||||
// // position:_kMapCenter,
|
|
||||||
// ),
|
|
||||||
// ];
|
|
||||||
// setmarkers = _markers.toSet();
|
|
||||||
// setState(() {
|
|
||||||
// isSetupReady = true;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return const Placeholder();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
import '../../../../tools/baseGetXController.dart';
|
|
||||||
|
|
||||||
class LockAddressLogic extends BaseGetXController {
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,76 +0,0 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
||||||
import 'package:get/get.dart';
|
|
||||||
|
|
||||||
import '../../../../appRouters.dart';
|
|
||||||
import '../../../../app_settings/app_colors.dart';
|
|
||||||
import '../../../../tools/titleAppBar.dart';
|
|
||||||
|
|
||||||
class LockAddressPage extends StatefulWidget {
|
|
||||||
const LockAddressPage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<LockAddressPage> createState() => _LockAddressPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LockAddressPageState extends State<LockAddressPage> with RouteAware{
|
|
||||||
Map<String, Object>? addressInfo;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: AppColors.mainBackgroundColor,
|
|
||||||
appBar: TitleAppBar(
|
|
||||||
barTitle: '锁地址'.tr,
|
|
||||||
haveBack: true,
|
|
||||||
backgroundColor: AppColors.mainColor,
|
|
||||||
actionsList: [
|
|
||||||
TextButton(
|
|
||||||
child: Text(
|
|
||||||
'下一步'.tr,
|
|
||||||
style: TextStyle(color: Colors.white, fontSize: 24.sp),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
if(addressInfo!.isEmpty){
|
|
||||||
EasyLoading.showToast('请先获取到位置信息哦'.tr, duration: 2000.milliseconds);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Get.toNamed(Routers.saveLockPage, arguments: addressInfo);
|
|
||||||
// Navigator.pushNamed(context, Routers.saveLockPage);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
// body: LockAddressGaoDePage(callback: (addressInfoMap){
|
|
||||||
// addressInfo = addressInfoMap;
|
|
||||||
// },)
|
|
||||||
body: Container(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
// routeObserver.unsubscribe(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
// 订阅 routeObserver,之后就会尝试调用抽象类 RouteAware 的方法
|
|
||||||
// routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didPush() {
|
|
||||||
// 当前页面入栈
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didPopNext() {
|
|
||||||
// 当前路由的下个路由出栈,且当前页面显示
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -330,13 +330,24 @@ class NearbyLockLogic extends BaseGetXController {
|
|||||||
state.featureSettingParams = featureParaTotalList;
|
state.featureSettingParams = featureParaTotalList;
|
||||||
AppLog.log('featureParaTotalList:$featureParaTotalList');
|
AppLog.log('featureParaTotalList:$featureParaTotalList');
|
||||||
|
|
||||||
Get.toNamed(Routers.lockAddressGaoDePage, arguments: <String, Object>{
|
// Get.toNamed(Routers.lockAddressGaoDePage, arguments: <String, Object>{
|
||||||
'pwdTimestamp': state.timestampValue * 1000,
|
// 'pwdTimestamp': state.timestampValue * 1000,
|
||||||
'lockInfo': state.lockInfo,
|
// 'lockInfo': state.lockInfo,
|
||||||
'featureValue': state.featureValue,
|
// 'featureValue': state.featureValue,
|
||||||
'featureSettingValue': state.featureSettingValue,
|
// 'featureSettingValue': state.featureSettingValue,
|
||||||
'featureSettingParams': state.featureSettingParams,
|
// 'featureSettingParams': state.featureSettingParams,
|
||||||
});
|
// });
|
||||||
|
Get.toNamed(Routers.saveLockPage,
|
||||||
|
arguments: <String, Object?>{
|
||||||
|
'addressInfo': {},
|
||||||
|
'pwdTimestamp': state.timestampValue * 1000,
|
||||||
|
'lockInfo': state.lockInfo,
|
||||||
|
'featureValue': state.featureValue,
|
||||||
|
'featureSettingValue': state.featureSettingValue,
|
||||||
|
'featureSettingParams': state.featureSettingParams,
|
||||||
|
'isFromMap': 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 0x06:
|
case 0x06:
|
||||||
|
|||||||
@ -365,15 +365,15 @@ class SaveLockLogic extends BaseGetXController {
|
|||||||
void bindBlueAdmin() async {
|
void bindBlueAdmin() async {
|
||||||
state.lockInfo['adminPwd'] = state.adminPassword;
|
state.lockInfo['adminPwd'] = state.adminPassword;
|
||||||
|
|
||||||
final Map<String, dynamic> positionMap = <String, dynamic>{};
|
// final Map<String, dynamic> positionMap = <String, dynamic>{};
|
||||||
positionMap['longitude'] = state.addressInfo['longitude'];
|
// positionMap['longitude'] = state.addressInfo['longitude'];
|
||||||
positionMap['latitude'] = state.addressInfo['latitude'];
|
// positionMap['latitude'] = state.addressInfo['latitude'];
|
||||||
positionMap['country'] = state.addressInfo['country'];
|
// positionMap['country'] = state.addressInfo['country'];
|
||||||
positionMap['province'] = state.addressInfo['province'];
|
// positionMap['province'] = state.addressInfo['province'];
|
||||||
positionMap['city'] = state.addressInfo['city'];
|
// positionMap['city'] = state.addressInfo['city'];
|
||||||
positionMap['district'] = state.addressInfo['district'];
|
// positionMap['district'] = state.addressInfo['district'];
|
||||||
positionMap['township'] = state.addressInfo['street'];
|
// positionMap['township'] = state.addressInfo['street'];
|
||||||
positionMap['address'] = state.addressInfo['address'];
|
// positionMap['address'] = state.addressInfo['address'];
|
||||||
|
|
||||||
final Map<String, dynamic> bluetooth = <String, dynamic>{};
|
final Map<String, dynamic> bluetooth = <String, dynamic>{};
|
||||||
bluetooth['bluetoothDeviceId'] = BlueManage().connectDeviceMacAddress;
|
bluetooth['bluetoothDeviceId'] = BlueManage().connectDeviceMacAddress;
|
||||||
@ -395,7 +395,7 @@ class SaveLockLogic extends BaseGetXController {
|
|||||||
|
|
||||||
final SaveLockEntity entity = await ApiRepository.to.bindingBlueAdmin(
|
final SaveLockEntity entity = await ApiRepository.to.bindingBlueAdmin(
|
||||||
lockAlias: state.aliName.value,
|
lockAlias: state.aliName.value,
|
||||||
position: positionMap,
|
position: {},
|
||||||
bluetooth: bluetooth,
|
bluetooth: bluetooth,
|
||||||
lockInfo: state.lockInfo,
|
lockInfo: state.lockInfo,
|
||||||
lockUserNo: state.lockUserNo.toString(),
|
lockUserNo: state.lockUserNo.toString(),
|
||||||
@ -505,9 +505,10 @@ class SaveLockLogic extends BaseGetXController {
|
|||||||
} else {
|
} else {
|
||||||
eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true));
|
eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true));
|
||||||
Future<void>.delayed(const Duration(seconds: 1), () {
|
Future<void>.delayed(const Duration(seconds: 1), () {
|
||||||
Get.close(state.isFromMap == 1
|
// Get.close(state.isFromMap == 1
|
||||||
? (CommonDataManage().seletLockType == 0 ? 4 : 5)
|
// ? (CommonDataManage().seletLockType == 0 ? 4 : 5)
|
||||||
: (CommonDataManage().seletLockType == 0 ? 5 : 6));
|
// : (CommonDataManage().seletLockType == 0 ? 5 : 6));
|
||||||
|
Get.until((route) => route.isFirst);
|
||||||
});
|
});
|
||||||
//刚刚配对完,需要对开锁页锁死 2 秒
|
//刚刚配对完,需要对开锁页锁死 2 秒
|
||||||
Future<void>.delayed(const Duration(milliseconds: 200), () {
|
Future<void>.delayed(const Duration(milliseconds: 200), () {
|
||||||
@ -521,9 +522,10 @@ class SaveLockLogic extends BaseGetXController {
|
|||||||
} else {
|
} else {
|
||||||
eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true));
|
eventBus.fire(RefreshLockListInfoDataEvent(clearScanDevices: true,isUnShowLoading: true));
|
||||||
Future<void>.delayed(const Duration(seconds: 1), () {
|
Future<void>.delayed(const Duration(seconds: 1), () {
|
||||||
Get.close(state.isFromMap == 1
|
// Get.close(state.isFromMap == 1
|
||||||
? (CommonDataManage().seletLockType == 0 ? 4 : 5)
|
// ? (CommonDataManage().seletLockType == 0 ? 4 : 5)
|
||||||
: (CommonDataManage().seletLockType == 0 ? 5 : 6));
|
// : (CommonDataManage().seletLockType == 0 ? 5 : 6));
|
||||||
|
Get.until((route) => route.isFirst);
|
||||||
});
|
});
|
||||||
//刚刚配对完,需要对开锁页锁死 2 秒
|
//刚刚配对完,需要对开锁页锁死 2 秒
|
||||||
Future<void>.delayed(const Duration(milliseconds: 200), () {
|
Future<void>.delayed(const Duration(milliseconds: 200), () {
|
||||||
|
|||||||
@ -15,17 +15,31 @@ class SaveLockState {
|
|||||||
adminPassword = getAdminPassword();
|
adminPassword = getAdminPassword();
|
||||||
|
|
||||||
final Map map = Get.arguments;
|
final Map map = Get.arguments;
|
||||||
|
if (map['pwdTimestamp']!= null) {
|
||||||
pwdTimestamp.value = map['pwdTimestamp'];
|
pwdTimestamp.value = map['pwdTimestamp'];
|
||||||
addressInfo.value = map['addressInfo'];
|
}
|
||||||
|
// if (map['addressInfo'] != null) {
|
||||||
|
// addressInfo.value = map['addressInfo'];
|
||||||
|
// }
|
||||||
|
if (map['lockInfo'] != null) {
|
||||||
lockInfo = map['lockInfo'];
|
lockInfo = map['lockInfo'];
|
||||||
|
}
|
||||||
|
if (map['featureValue'] != null) {
|
||||||
featureValue = map['featureValue'];
|
featureValue = map['featureValue'];
|
||||||
|
}
|
||||||
|
if (map['featureSettingValue'] != null) {
|
||||||
featureSettingValue = map['featureSettingValue'];
|
featureSettingValue = map['featureSettingValue'];
|
||||||
|
}
|
||||||
|
if (map['featureSettingParams'] != null) {
|
||||||
featureSettingParams = map['featureSettingParams'];
|
featureSettingParams = map['featureSettingParams'];
|
||||||
isFromMap = map['isFromMap'];
|
}
|
||||||
|
// if (map['isFromMap'] != null) {
|
||||||
|
// isFromMap = map['isFromMap'];
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
RxString aliName = ''.obs;
|
RxString aliName = ''.obs;
|
||||||
RxInt pwdTimestamp = 0.obs;
|
RxInt pwdTimestamp = 0.obs;
|
||||||
RxMap addressInfo = {}.obs;
|
// RxMap addressInfo = {}.obs;
|
||||||
final Rx<LockSetInfoData> lockSetInfoData = LockSetInfoData().obs;
|
final Rx<LockSetInfoData> lockSetInfoData = LockSetInfoData().obs;
|
||||||
TextEditingController aliNameController = TextEditingController();
|
TextEditingController aliNameController = TextEditingController();
|
||||||
FocusNode focusNode = FocusNode();
|
FocusNode focusNode = FocusNode();
|
||||||
@ -35,7 +49,7 @@ class SaveLockState {
|
|||||||
String featureValue = '';
|
String featureValue = '';
|
||||||
String featureSettingValue = '';
|
String featureSettingValue = '';
|
||||||
List featureSettingParams = [];
|
List featureSettingParams = [];
|
||||||
int isFromMap = 0; // 0:不是从地图界面进入 1:从地图界面进入
|
// int isFromMap = 0; // 0:不是从地图界面进入 1:从地图界面进入
|
||||||
|
|
||||||
RxBool ifCurrentScreen = true.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示
|
RxBool ifCurrentScreen = true.obs; // 是否是当前界面,用于判断是否需要针对当前界面进行展示
|
||||||
RxInt sureBtnState = 0.obs; // 0可点击 1 不可点击
|
RxInt sureBtnState = 0.obs; // 0可点击 1 不可点击
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter_app_badger/flutter_app_badger.dart';
|
||||||
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||||
import 'package:star_lock/tools/baseGetXController.dart';
|
import 'package:star_lock/tools/baseGetXController.dart';
|
||||||
import '../../../network/api_repository.dart';
|
import '../../../network/api_repository.dart';
|
||||||
import '../../../tools/eventBusEventManage.dart';
|
import '../../../tools/eventBusEventManage.dart';
|
||||||
@ -46,6 +48,8 @@ class MessageListLogic extends BaseGetXController {
|
|||||||
if (entity.errorCode!.codeIsSuccessful) {
|
if (entity.errorCode!.codeIsSuccessful) {
|
||||||
pageNo = 1;
|
pageNo = 1;
|
||||||
messageListDataRequest();
|
messageListDataRequest();
|
||||||
|
// 清除角标
|
||||||
|
FlutterAppBadger.removeBadge();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
pubspec.yaml
10
pubspec.yaml
@ -194,14 +194,14 @@ dependencies:
|
|||||||
easy_refresh: ^3.3.4
|
easy_refresh: ^3.3.4
|
||||||
|
|
||||||
#高德地图定位
|
#高德地图定位
|
||||||
amap_flutter_location: 3.0.0
|
# amap_flutter_location: 3.0.0
|
||||||
#权限使用
|
#权限使用
|
||||||
permission_handler: ^11.3.1
|
permission_handler: ^11.3.1
|
||||||
#高德地图地图
|
# #高德地图地图
|
||||||
amap_flutter_map: 3.0.0
|
# amap_flutter_map: 3.0.0
|
||||||
|
|
||||||
# 谷歌地图
|
# 谷歌地图
|
||||||
google_maps_flutter: ^2.2.5
|
# google_maps_flutter: ^2.2.5
|
||||||
# geocoding: ^2.1.0
|
# geocoding: ^2.1.0
|
||||||
|
|
||||||
# 允许App发现网络的相关信息并且进行相应的配置
|
# 允许App发现网络的相关信息并且进行相应的配置
|
||||||
@ -275,6 +275,8 @@ dependencies:
|
|||||||
provider: ^6.1.2
|
provider: ^6.1.2
|
||||||
dio: ^4.0.6 # 网络请求库
|
dio: ^4.0.6 # 网络请求库
|
||||||
video_thumbnail: ^0.5.3
|
video_thumbnail: ^0.5.3
|
||||||
|
# 角标管理
|
||||||
|
flutter_app_badger: ^1.3.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user