497 lines
17 KiB
Dart
Executable File
497 lines
17 KiB
Dart
Executable File
import 'package:flutter/cupertino.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/tools/pickers/pickers.dart';
|
|
import 'package:star_lock/tools/pickers/time_picker/model/date_mode.dart';
|
|
import 'package:star_lock/tools/pickers/time_picker/model/pduration.dart';
|
|
|
|
import '../../../../appRouters.dart';
|
|
import '../../../../app_settings/app_colors.dart';
|
|
import '../../../../tools/CustomUnderlineTabIndicator.dart';
|
|
import '../../../../tools/commonItem.dart';
|
|
import '../../../../tools/dateTool.dart';
|
|
import '../../../../tools/storage.dart';
|
|
import '../../../../tools/submitBtn.dart';
|
|
import '../../../../tools/titleAppBar.dart';
|
|
import '../../../../translations/trans_lib.dart';
|
|
import 'addRemoteControl_logic.dart';
|
|
|
|
class AddRemoteControlPage extends StatefulWidget {
|
|
const AddRemoteControlPage({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
State<AddRemoteControlPage> createState() => _AddRemoteControlPageState();
|
|
}
|
|
|
|
class _AddRemoteControlPageState extends State<AddRemoteControlPage>
|
|
with SingleTickerProviderStateMixin {
|
|
final logic = Get.put(AddRemoteControlLoigc());
|
|
final state = Get.find<AddRemoteControlLoigc>().state;
|
|
|
|
@override
|
|
void initState() {
|
|
// TODO: implement initState
|
|
super.initState();
|
|
|
|
state.tabController = TabController(
|
|
vsync: this,
|
|
length: state.fromType.value == 1
|
|
? _itemTabs.length
|
|
: _fromCheckInTypeItemTabs.length,
|
|
initialIndex: 0);
|
|
state.tabController.addListener(() {
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
state.selectType.value = state.tabController.index.toString();
|
|
});
|
|
|
|
if (state.tabController.animation!.value == state.tabController.index) {
|
|
FocusScope.of(context).requestFocus(FocusNode());
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: AppColors.mainBackgroundColor,
|
|
appBar: TitleAppBar(
|
|
barTitle:
|
|
"${TranslationLoader.lanKeys!.addTip!.tr}${TranslationLoader.lanKeys!.fingerprint!.tr}",
|
|
haveBack: true,
|
|
backgroundColor: AppColors.mainColor),
|
|
body: Column(
|
|
children: [
|
|
_tabBar(),
|
|
_pageWidget(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget indexChangeWidget() {
|
|
switch (int.parse(state.selectType.value)) {
|
|
case 0:
|
|
{
|
|
// 永久
|
|
// return sendElectronicKeySucceed();
|
|
return Column(
|
|
children: [
|
|
perpetualKeyWidget(
|
|
TranslationLoader.lanKeys!.name!.tr,
|
|
TranslationLoader.lanKeys!.pleaseEnter!.tr,
|
|
state.nameController),
|
|
keyBottomWidget()
|
|
],
|
|
);
|
|
}
|
|
case 1:
|
|
{
|
|
// 限时
|
|
return Column(
|
|
children: [
|
|
perpetualKeyWidget(
|
|
TranslationLoader.lanKeys!.name!.tr,
|
|
TranslationLoader.lanKeys!.pleaseEnter!.tr,
|
|
state.nameController),
|
|
keyTimeLimitWidget(),
|
|
SizedBox(height: 10.h),
|
|
keyBottomWidget()
|
|
],
|
|
);
|
|
}
|
|
case 2:
|
|
{
|
|
// 循环
|
|
return SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
perpetualKeyWidget(
|
|
TranslationLoader.lanKeys!.name!.tr,
|
|
TranslationLoader.lanKeys!.pleaseEnter!.tr,
|
|
state.nameController),
|
|
keyCyclicDate(),
|
|
SizedBox(height: 10.h),
|
|
keyBottomWidget()
|
|
],
|
|
),
|
|
);
|
|
}
|
|
default:
|
|
return Container();
|
|
}
|
|
}
|
|
|
|
// 密码命名输入框
|
|
Widget perpetualKeyWidget(
|
|
String titleStr, String rightTitle, TextEditingController controller) {
|
|
return Column(
|
|
children: [
|
|
CommonItem(
|
|
leftTitel: titleStr,
|
|
rightTitle: '',
|
|
isHaveRightWidget: true,
|
|
rightWidget: getTFWidget(rightTitle)),
|
|
Container(height: 10.h),
|
|
],
|
|
);
|
|
}
|
|
|
|
// 限时顶部选择日期
|
|
Widget keyTimeLimitWidget() {
|
|
return Column(
|
|
children: [
|
|
Obx(() => CommonItem(
|
|
leftTitel: TranslationLoader.lanKeys!.effectiveTime!.tr,
|
|
rightTitle: state.timeLimitBeginTime.value,
|
|
isHaveLine: true,
|
|
isHaveDirection: true,
|
|
action: () async {
|
|
PDuration selectDate = PDuration.parse(
|
|
DateTime.parse(state.timeLimitBeginTime.value));
|
|
Pickers.showDatePicker(context,
|
|
selectDate: selectDate, mode: DateMode.YMDHM, onConfirm: (p) {
|
|
state.timeLimitBeginTime.value =
|
|
DateTool().getYMDHNDateString(p, 1);
|
|
});
|
|
})),
|
|
Obx(() => CommonItem(
|
|
leftTitel: TranslationLoader.lanKeys!.failureTime!.tr,
|
|
rightTitle: state.timeLimitEndTime.value,
|
|
isHaveDirection: true,
|
|
action: () {
|
|
PDuration selectDate = PDuration.parse(
|
|
DateTime.tryParse(state.timeLimitEndTime.value));
|
|
Pickers.showDatePicker(context,
|
|
selectDate: selectDate, mode: DateMode.YMDHM, onConfirm: (p) {
|
|
state.timeLimitEndTime.value =
|
|
DateTool().getYMDHNDateString(p, 1);
|
|
});
|
|
})),
|
|
Container(height: 10.h),
|
|
],
|
|
);
|
|
}
|
|
|
|
// 循环顶部选择日期
|
|
Widget keyCyclicDate() {
|
|
return Column(
|
|
children: [
|
|
Obx(() => CommonItem(
|
|
leftTitel: TranslationLoader.lanKeys!.periodValidity!.tr,
|
|
rightTitle:
|
|
'${state.cycleBeginTime.value}\n${state.cycleEndTime.value}',
|
|
isHaveDirection: true,
|
|
isHaveLine: true,
|
|
action: () async {
|
|
var result =
|
|
await Get.toNamed(Routers.seletKeyCyclicDatePage, arguments: {
|
|
'validityValue': state.weekdaysList.value,
|
|
'starDate': state.cycleBeginTime.value,
|
|
'endDate': state.cycleEndTime.value,
|
|
'starTime': state.effectiveDateTime.value,
|
|
'endTime': state.failureDateTime.value
|
|
});
|
|
if (result != null && result.isNotEmpty) {
|
|
state.weekdaysList.value = result['validityValue'];
|
|
state.cycleBeginTime.value = result['starDate'];
|
|
state.cycleEndTime.value = result['endDate'];
|
|
state.effectiveDateTime.value = result['starTime'];
|
|
state.failureDateTime.value = result['endTime'];
|
|
}
|
|
})),
|
|
Obx(() => Visibility(
|
|
visible: state.weekdaysList.isNotEmpty,
|
|
child: CommonItem(
|
|
leftTitel: '有效日'.tr,
|
|
rightTitle: logic.weekDayStr.join(',').toString(),
|
|
isHaveDirection: true,
|
|
isHaveLine: true,
|
|
action: () async {
|
|
var result = await Get.toNamed(Routers.seletKeyCyclicDatePage,
|
|
arguments: {
|
|
'validityValue': state.weekdaysList.value,
|
|
'starDate': state.cycleBeginTime.value,
|
|
'endDate': state.cycleEndTime.value,
|
|
'starTime': state.effectiveDateTime.value,
|
|
'endTime': state.failureDateTime.value
|
|
});
|
|
if (result != null && result.isNotEmpty) {
|
|
state.weekdaysList.value = result['validityValue'];
|
|
state.cycleBeginTime.value = result['starDate'];
|
|
state.cycleEndTime.value = result['endDate'];
|
|
state.effectiveDateTime.value = result['starTime'];
|
|
state.failureDateTime.value = result['endTime'];
|
|
}
|
|
}))),
|
|
Obx(() => Visibility(
|
|
visible: state.effectiveDateTime.value.isNotEmpty,
|
|
child: CommonItem(
|
|
leftTitel: '有效时间'.tr,
|
|
rightTitle:
|
|
'${state.effectiveDateTime.value}-${state.failureDateTime.value}',
|
|
isHaveDirection: true,
|
|
action: () async {
|
|
var result = await Get.toNamed(Routers.seletKeyCyclicDatePage,
|
|
arguments: {
|
|
'validityValue': state.weekdaysList.value,
|
|
'starDate': state.cycleBeginTime.value,
|
|
'endDate': state.cycleEndTime.value,
|
|
'starTime': state.effectiveDateTime.value,
|
|
'endTime': state.failureDateTime.value
|
|
});
|
|
if (result != null && result.isNotEmpty) {
|
|
state.weekdaysList.value = result['validityValue'];
|
|
state.cycleBeginTime.value = result['starDate'];
|
|
state.cycleEndTime.value = result['endDate'];
|
|
state.effectiveDateTime.value = result['starTime'];
|
|
state.failureDateTime.value = result['endTime'];
|
|
}
|
|
}))),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget keyBottomWidget() {
|
|
return Column(
|
|
children: [
|
|
// CommonItem(
|
|
// leftTitel: TranslationLoader.lanKeys!.remoteControl!.tr,
|
|
// rightTitle: "",
|
|
// isTipsImg: false,
|
|
// isHaveRightWidget: true,
|
|
// rightWidget: SizedBox(
|
|
// width: 60.w, height: 50.h, child: _isStressFingerprint())),
|
|
SizedBox(height: 30.h),
|
|
SubmitBtn(
|
|
btnName: TranslationLoader.lanKeys!.next!.tr,
|
|
onClick: () async {
|
|
var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot);
|
|
if (isDemoMode == false) {
|
|
if (state.nameController.text.isEmpty) {
|
|
logic.showToast('请输入姓名');
|
|
return;
|
|
}
|
|
logic.showToast('请确保在设备附近');
|
|
// logic.addFingerprintsData();
|
|
} else {
|
|
// Get.toNamed(Routers.selectLockTypePage);
|
|
logic.showToast('演示模式');
|
|
}
|
|
}),
|
|
],
|
|
);
|
|
}
|
|
|
|
// 发送电子钥匙成功
|
|
Widget sendElectronicKeySucceed() {
|
|
return Column(
|
|
children: [
|
|
Container(
|
|
height: 300.h,
|
|
width: 1.sw,
|
|
color: Colors.white,
|
|
child: Column(
|
|
children: [
|
|
SizedBox(
|
|
height: 30.h,
|
|
),
|
|
Image.asset(
|
|
'images/main/icon_main_addLock.png',
|
|
width: 150.w,
|
|
height: 150.w,
|
|
color: AppColors.mainColor,
|
|
),
|
|
SizedBox(
|
|
height: 20.h,
|
|
),
|
|
Text(
|
|
'操作成功,密码为',
|
|
style: TextStyle(
|
|
fontSize: 32.sp,
|
|
color: Colors.black,
|
|
fontWeight: FontWeight.w500),
|
|
),
|
|
SizedBox(
|
|
height: 10.h,
|
|
),
|
|
Text(
|
|
'62689876',
|
|
style: TextStyle(
|
|
fontSize: 60.sp,
|
|
color: Colors.black,
|
|
fontWeight: FontWeight.w500),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(
|
|
height: 20.h,
|
|
),
|
|
SubmitBtn(
|
|
btnName: '完成'.tr,
|
|
fontSize: 28.sp,
|
|
borderRadius: 20.w,
|
|
margin: EdgeInsets.only(left: 30.w, right: 30.w, top: 30.w),
|
|
padding: EdgeInsets.only(top: 25.w, bottom: 25.w),
|
|
onClick: () {}),
|
|
SubmitBtn(
|
|
btnName: '分享',
|
|
fontSize: 28.sp,
|
|
borderRadius: 20.w,
|
|
margin: EdgeInsets.only(left: 30.w, right: 30.w, top: 30.w),
|
|
padding: EdgeInsets.only(top: 25.w, bottom: 25.w),
|
|
onClick: () {}),
|
|
SubmitBtn(
|
|
btnName: '标记为:已入住',
|
|
fontSize: 28.sp,
|
|
borderRadius: 20.w,
|
|
margin: EdgeInsets.only(left: 30.w, right: 30.w, top: 30.w),
|
|
padding: EdgeInsets.only(top: 25.w, bottom: 25.w),
|
|
onClick: () {}),
|
|
],
|
|
);
|
|
}
|
|
|
|
// 接受者信息输入框
|
|
Widget getTFWidget(String tfStr) {
|
|
return Container(
|
|
// color: Colors.red,
|
|
height: 65.h,
|
|
width: 300.w,
|
|
padding: EdgeInsets.only(top: 5.h),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Expanded(
|
|
child: TextField(
|
|
//输入框一行
|
|
maxLines: 1,
|
|
inputFormatters: <TextInputFormatter>[
|
|
FilteringTextInputFormatter.deny('\n'),
|
|
LengthLimitingTextInputFormatter(18),
|
|
],
|
|
style: TextStyle(
|
|
fontSize: 22.sp, color: AppColors.darkGrayTextColor),
|
|
controller: state.nameController,
|
|
autofocus: false,
|
|
textAlign: TextAlign.end,
|
|
decoration: InputDecoration(
|
|
//输入里面输入文字内边距设置
|
|
// contentPadding: const EdgeInsets.only(top: 12.0, bottom: 8.0),
|
|
hintText: tfStr,
|
|
hintStyle: TextStyle(fontSize: 22.sp),
|
|
focusedBorder: const OutlineInputBorder(
|
|
borderSide:
|
|
BorderSide(width: 0, color: Colors.transparent)),
|
|
disabledBorder: const OutlineInputBorder(
|
|
borderSide:
|
|
BorderSide(width: 0, color: Colors.transparent)),
|
|
enabledBorder: const OutlineInputBorder(
|
|
borderSide:
|
|
BorderSide(width: 0, color: Colors.transparent)),
|
|
border: const OutlineInputBorder(
|
|
borderSide:
|
|
BorderSide(width: 0, color: Colors.transparent)),
|
|
contentPadding: const EdgeInsets.symmetric(vertical: 0),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(
|
|
width: 10.w,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
//isStressFingerprint false:不是胁迫指纹 ture:胁迫指纹
|
|
CupertinoSwitch _isStressFingerprint() {
|
|
return CupertinoSwitch(
|
|
activeColor: CupertinoColors.activeBlue,
|
|
trackColor: CupertinoColors.systemGrey5,
|
|
thumbColor: CupertinoColors.white,
|
|
value: true,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
// state.isStressFingerprint.value = value;
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
final List<ItemView> _itemTabs = <ItemView>[
|
|
ItemView(title: TranslationLoader.lanKeys!.permanent!.tr, selectType: '0'),
|
|
ItemView(title: TranslationLoader.lanKeys!.timeLimit!.tr, selectType: '1'),
|
|
ItemView(
|
|
title: TranslationLoader.lanKeys!.circulation!.tr, selectType: '2'),
|
|
];
|
|
|
|
final List<ItemView> _fromCheckInTypeItemTabs = <ItemView>[
|
|
ItemView(title: TranslationLoader.lanKeys!.permanent!.tr, selectType: '0'),
|
|
ItemView(title: TranslationLoader.lanKeys!.timeLimit!.tr, selectType: '1'),
|
|
];
|
|
|
|
TabBar _tabBar() {
|
|
return TabBar(
|
|
controller: state.tabController,
|
|
onTap: (index) {
|
|
FocusScope.of(context).requestFocus(FocusNode());
|
|
},
|
|
tabs: state.fromType.value == 1
|
|
? _itemTabs.map((ItemView item) => _tab(item)).toList()
|
|
: _fromCheckInTypeItemTabs
|
|
.map((ItemView item) => _tab(item))
|
|
.toList(),
|
|
isScrollable: true,
|
|
indicatorColor: Colors.red,
|
|
unselectedLabelColor: Colors.black,
|
|
unselectedLabelStyle: TextStyle(
|
|
color: AppColors.mainColor,
|
|
fontSize: 24.sp,
|
|
),
|
|
automaticIndicatorColorAdjustment: true,
|
|
labelColor: AppColors.mainColor,
|
|
labelStyle: TextStyle(
|
|
color: AppColors.mainColor,
|
|
fontSize: 24.sp,
|
|
fontWeight: FontWeight.w600),
|
|
indicator: CustomUnderlineTabIndicator(
|
|
borderSide: BorderSide(color: AppColors.mainColor, width: 4.w),
|
|
strokeCap: StrokeCap.round,
|
|
width: 30.w),
|
|
);
|
|
}
|
|
|
|
Tab _tab(ItemView item) {
|
|
return Tab(
|
|
child: SizedBox(
|
|
width: 1.sw / 5,
|
|
child: Text(item.title, textAlign: TextAlign.center)));
|
|
}
|
|
|
|
Widget _pageWidget() {
|
|
return Expanded(
|
|
child: TabBarView(
|
|
controller: state.tabController,
|
|
children: state.fromType.value == 1
|
|
? _itemTabs
|
|
.map((ItemView item) => Obx(() => indexChangeWidget()))
|
|
.toList()
|
|
: _fromCheckInTypeItemTabs
|
|
.map((ItemView item) => Obx(() => indexChangeWidget()))
|
|
.toList(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class ItemView {
|
|
const ItemView({required this.title, required this.selectType});
|
|
|
|
final String title;
|
|
final String selectType;
|
|
}
|