This commit is contained in:
魏少阳 2024-04-10 13:36:05 +08:00
commit 40818eaf99
25 changed files with 1795 additions and 20 deletions

View File

@ -1,2 +1,9 @@
FLUTTER_STORAGE_BASE_URL="https://mirrors.tuna.tsinghua.edu.cn/flutter"
PUB_HOSTED_URL="https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
HTTP_PROXY=http://127.0.0.1:1080/```
HTTPS_PROXY=http://127.0.0.1:1080/
# curl只支持小写
http_proxy=http://127.0.0.1:1080/
https_proxy=http://127.0.0.1:1080/

View File

@ -1 +1,2 @@
.env
gradle.properties

View File

@ -2,17 +2,31 @@
构建镜像来自https://github.com/MobileDevOps/flutter-sdk-image/
## 使用方法
1. 复制.env文件,并编辑其中的代理设置
1. 复制文件,并编辑其中的代理设置
```bash
cp .docker/.env.example .docker/.env
# ~/.gradle 如不存在请新建该目录缓存一些gradle包
mkdir -p ~/.gradle && chmod -R 777 ~/.gradle
cp .docker/gradle.properties.example ~/.gradle/gradle.properties
```
2. 构建命令
```bash
cd <path-to-this-repo>
# 构建目录,防止目录权限问题
mkdir /tmp/build-cache
echo 'hello!' > /tmp/build-cache/isMe.txt
chown -R 999:996 /tmp/build-cache
# 构建sky版本APK
docker run --env-file .docker/.env --rm -it -v .:/home/mobiledevops/app mobiledevops/flutter-sdk-image:3.16.4 \
docker run --rm -it \
--env-file .docker/.env \
-v .:/home/mobiledevops/app \
-v /tmp/build-cache/:/home/mobiledevops/app/build/ \
-v ~/.gradle/:/home/mobiledevops/.gradle/ \
-v ~/android-sdk-linux:/opt/android-sdk-linux \
mobiledevops/flutter-sdk-image:3.16.4 \
flutter build apk --release --flavor sky -t lib/main_sky_full.dart
```
@ -21,8 +35,83 @@ flutter build apk --release --flavor sky -t lib/main_sky_full.dart
## 排除故障
测试谷歌连接
### 内存要求
4G内存下经常有异常崩溃建议虚拟机8G内存
### 测试谷歌连接
```bash
# flutter以及maven 下载地址是否正常
curl -i https://storage.googleapis.com/flutter_infra_release/
```
### 卡在Running Gradle task 'assembleSkyRelease'...
这一步最耗时的是在下载maven仓库的依赖如果卡在这里可能是代理设置有问题
请检查代理~/.gradle/gradle.properties中配置的代理代理面板是否有请求输出
在网络请求平息了之后又进入了漫长到令人绝望的等待中这时候你可能会怀疑地球是否仍在转动我们是否陷入了是时空停滞别担心这大概是由于计算机性能太低或者在CPU受限的虚拟机中导致的你可以在另外的窗口运行htop命令或直接查看宿主机的CPU使用率来观察系统是否处于卡顿多线程编译导致的以及进程树列表是否在变动这些观察可以让你继续耐心等待直到屏幕出现一片红色的报错信息。
如果在报错信息中看到正在编译XX或者下载XX没有看到任何错误但是终止了这可能是内存不够导致的崩溃。
参考的信息
```bash
# du -sh ~/android-sdk-linux/
7.1G /root/android-sdk-linux/
# du -sh ~/.gradle/
4.6G /root/.gradle/
# du -sh /tmp/build-cache
514M /tmp/build-cache
```
正常的输出
```bash
mobiledevops@946e5e22d9c5:~/app$ flutter build apk --release --flavor sky -t lib/main_sky_full.dart
Flutter assets will be downloaded from https://mirrors.tuna.tsinghua.edu.cn/flutter. Make sure you trust this source!
Warning: The plugin camera_android requires Android SDK version 34.
For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
Warning: The plugin flutter_local_notifications requires Android SDK version 34.
For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
Warning: The plugin fluwx requires Android SDK version 34.
For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
Warning: The plugin google_maps_flutter_android requires Android SDK version 34.
For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
Warning: The plugin image_picker_android requires Android SDK version 34.
For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
Warning: The plugin url_launcher_android requires Android SDK version 34.
For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
Warning: The plugin video_player_android requires Android SDK version 34.
For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
Warning: The plugin webview_flutter_android requires Android SDK version 34.
For more information about build configuration, see https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
One or more plugins require a higher Android SDK version.
Fix this issue by adding the following to /home/mobiledevops/app/android/app/build.gradle:
android {
compileSdkVersion 34
...
}
Flutter assets will be downloaded from https://mirrors.tuna.tsinghua.edu.cn/flutter. Make sure you trust this source!
Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 2388 bytes (99.9% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app.
WARNING: [Processor] Library '/home/mobiledevops/.gradle/caches/modules-2/files-2.1/androidx.media2/media2-session/1.2.1/f927563711e36371c19b2e86fb7ccf1c3f259ca4/media2-session-1.2.1.aar' contains references to both AndroidX and old support library. This seems like the library is partially migrated. Jetifier will try to rewrite the library anyway.
Example of androidX reference: 'androidx/media2/session/MediaBrowser$Builder'
Example of support library reference: 'android/support/v4/media/session/MediaSessionCompat$Token'
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Running Gradle task 'assembleSkyRelease'... 257.0s
✓ Built build/app/outputs/flutter-apk/app-sky-release.apk (45.3MB).
mobiledevops@946e5e22d9c5:~/app$
exit
```
### 手动编译
```bash
cd android
./gradlew assembleSkyRelease
```

View File

@ -0,0 +1,4 @@
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=1080
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=1080

View File

@ -9,6 +9,9 @@ import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/ma
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/massSendLockGroupList_page.dart';
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/massSendReceiver/massSendReceiver_page.dart';
import 'package:star_lock/main/lockDetail/face/faceDetail/faceDetail_page.dart';
import 'package:star_lock/main/lockDetail/iris/addIris/addIris_page.dart';
import 'package:star_lock/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_page.dart';
import 'package:star_lock/main/lockDetail/iris/irisList/irisList_page.dart';
import 'package:star_lock/main/lockDetail/lockSet/addFamily/addFamily_page.dart';
import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeCustomMode/catEyeCustomMode_page.dart';
import 'package:star_lock/main/lockDetail/lockSet/catEyeSet/catEyeSet/catEyeSet_page.dart';
@ -414,10 +417,14 @@ abstract class Routers {
static const addFingerprintTypeManagePage =
'/AddFingerprintTypeManagePage'; //
static const fingerprintDetailPage = '/FingerprintDetailPage'; //
static const faceList = '/FaceList'; //
static const faceListPage = '/FaceListPage'; //
static const addFaceTypeManagePage = '/AddFaceTypeManagePage'; //
static const faceDetailPage = '/faceDetailPage'; //
static const irisListPage = '/IrisListPage'; //
static const addIrisTypeManagePage = '/AddIrisTypeManagePage'; //
static const addIrisPage = '/AddIrisPage'; //
static const passwordKeyDetailChangeDatePage =
'/passwordKeyDetailChangeDatePage'; //
static const realTimePicturePage = '/realTimePicturePage'; //
@ -427,7 +434,8 @@ abstract class Routers {
static const liveVideoPage = '/liveVideoPage'; //
static const accessoriesListPage = '/accessoriesListPage'; //
static const seletKeyCyclicDatePage = '/SeletKeyCyclicDatePage';//
static const seletKeyCyclicDatePage =
'/SeletKeyCyclicDatePage'; //
}
abstract class AppRouters {
@ -1005,7 +1013,7 @@ abstract class AppRouters {
GetPage(
name: Routers.fingerprintDetailPage,
page: () => const FingerprintDetailPage()),
GetPage(name: Routers.faceList, page: () => const FaceList()),
GetPage(name: Routers.faceListPage, page: () => const FaceListPage()),
GetPage(
name: Routers.addFaceTypeManagePage,
page: () => const AddFaceTypeManagePage()),
@ -1028,11 +1036,14 @@ abstract class AppRouters {
GetPage(
name: Routers.accessoriesListPage,
page: (() => const AccessoriesListPage())),
GetPage(
name: Routers.wifiListPage,
page: (() => const WifiListPage())),
GetPage(name: Routers.wifiListPage, page: (() => const WifiListPage())),
GetPage(
name: Routers.seletKeyCyclicDatePage,
page: (() => const SeletKeyCyclicDatePage()))
page: (() => const SeletKeyCyclicDatePage())),
GetPage(name: Routers.irisListPage, page: (() => const IrisListPage())),
GetPage(
name: Routers.addIrisTypeManagePage,
page: (() => const AddIrisTypeManagePage())),
GetPage(name: Routers.addIrisPage, page: (() => const AddIrisPage()))
];
}

View File

@ -16,14 +16,14 @@ import '../../../../tools/titleAppBar.dart';
import '../../../../translations/trans_lib.dart';
import 'faceList_logic.dart';
class FaceList extends StatefulWidget {
const FaceList({Key? key}) : super(key: key);
class FaceListPage extends StatefulWidget {
const FaceListPage({Key? key}) : super(key: key);
@override
State<FaceList> createState() => _FaceListState();
State<FaceListPage> createState() => _FaceListPageState();
}
class _FaceListState extends State<FaceList> {
class _FaceListPageState extends State<FaceListPage> {
final logic = Get.put(FaceListLogic());
final state = Get.find<FaceListLogic>().state;

View File

@ -0,0 +1,46 @@
import 'dart:async';
// import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:get/get.dart';
import 'package:star_lock/blue/io_protocol/io_addFace.dart';
import 'package:star_lock/blue/io_type.dart';
import 'package:star_lock/main/lockDetail/face/addFace/addFace_state.dart';
import 'package:star_lock/tools/eventBusEventManage.dart';
import '../../../../../blue/blue_manage.dart';
import '../../../../../blue/io_reply.dart';
import '../../../../../blue/io_tool/io_tool.dart';
import '../../../../../blue/io_tool/manager_event_bus.dart';
import '../../../../../blue/sender_manage.dart';
import '../../../../../network/api_repository.dart';
import '../../../../../tools/baseGetXController.dart';
import '../../../../../tools/storage.dart';
class AddIrisLogic extends BaseGetXController {
final AddFaceState state = AddFaceState();
@override
void onReady() {
// TODO: implement onReady
super.onReady();
// _initReplySubscription();
}
@override
void onInit() {
// TODO: implement onInit
super.onInit();
//
// senderAddFace();
}
@override
void onClose() {
// TODO: implement onClose
super.onClose();
// _replySubscription.cancel();
}
}

View File

@ -0,0 +1,94 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/iris/addIris/addIris_logic.dart';
import '../../../../../app_settings/app_colors.dart';
import '../../../../../tools/submitBtn.dart';
import '../../../../../tools/titleAppBar.dart';
import '../../../../../translations/trans_lib.dart';
class AddIrisPage extends StatefulWidget {
const AddIrisPage({Key? key}) : super(key: key);
@override
State<AddIrisPage> createState() => _AddIrisPageState();
}
class _AddIrisPageState extends State<AddIrisPage> {
final logic = Get.put(AddIrisLogic());
final state = Get.find<AddIrisLogic>().state;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: TitleAppBar(
barTitle: "${TranslationLoader.lanKeys!.addTip!.tr}虹膜",
haveBack: true,
backgroundColor: AppColors.mainColor),
body: ListView(
children: [
SizedBox(
height: 50.h,
),
Obx(() => Image.asset(
state.isClickAddFace.value == false
? 'images/main/icon_addFace_step1.png'
: 'images/main/icon_addFace_step2.png',
width: 100.w,
height: 457.h,
fit: BoxFit.fitHeight,
)),
SizedBox(
height: 60.h,
),
Container(
padding: EdgeInsets.only(left: 20.w, right: 20.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: Text(
"请单人正对门锁,距离一个成年人手臂长度\n(约0.6米)。\n保持脸部无遮挡,露出五官。",
textAlign: TextAlign.left,
maxLines: null,
style:
TextStyle(fontSize: 24.sp, fontWeight: FontWeight.w600),
),
),
],
),
),
SizedBox(
height: 120.h,
),
Obx(
() => state.isClickAddFace.value == false
? Container(
padding: EdgeInsets.only(left: 20.w, right: 20.w),
child: SubmitBtn(
btnName: "准备好了,开始添加",
borderRadius: 20.w,
onClick: () {
state.isClickAddFace.value = true;
}),
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'正在录入中...',
style: TextStyle(
color: AppColors.darkGrayTextColor,
fontSize: 22.sp),
textAlign: TextAlign.center,
)
],
),
)
],
),
);
}
}

View File

@ -0,0 +1,37 @@
import 'package:get/get.dart';
class AddIrisState {
var ifCurrentScreen = true.obs; // ,
var ifConnectScuess = false.obs;
var maxRegCount = 0.obs; //
var regIndex = 0.obs; //
var faceNumber = "".obs;
final lockId = 0.obs;
final endDate = 0.obs;
final addType = "".obs;
final faceName = "".obs;
final faceType = 0.obs;
final startDate = 0.obs;
final cyclicConfig = [].obs;
final fromType = 1.obs;
final featureData = ''.obs;
final isClickAddFace = false.obs;
final isAdministrator = false.obs;
AddIrisState() {
Map map = Get.arguments;
lockId.value = map["lockId"];
endDate.value = map["endDate"];
addType.value = map["addType"];
faceName.value = map["faceName"];
faceType.value = map["faceType"];
startDate.value = map["startDate"];
lockId.value = map["lockId"];
cyclicConfig.value = map["cyclicConfig"];
fromType.value = map["fromType"];
isAdministrator.value = map["isAdministrator"];
}
}

View File

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/iris/addIrisType/addIrisTypeManage/addIrisTypeManage_tabbar.dart';
import '../../../../../app_settings/app_colors.dart';
import '../../../../../tools/titleAppBar.dart';
import '../../../../../translations/trans_lib.dart';
class AddIrisTypeManagePage extends StatefulWidget {
const AddIrisTypeManagePage({Key? key}) : super(key: key);
@override
State<AddIrisTypeManagePage> createState() => _AddIrisTypeManagePageState();
}
class _AddIrisTypeManagePageState extends State<AddIrisTypeManagePage> {
var index = 0;
@override
Widget build(BuildContext context) {
Map map = Get.arguments;
var lockId = map["lockId"];
var fromType = map["fromType"]; // 1 2
var fromTypeTwoStaffName = "";
if (fromType == 2) {
fromTypeTwoStaffName = map["fromTypeTwoStaffName"]; //
}
return Scaffold(
backgroundColor: AppColors.mainBackgroundColor,
appBar: TitleAppBar(
barTitle: "${TranslationLoader.lanKeys!.addTip!.tr}虹膜",
haveBack: true,
backgroundColor: AppColors.mainColor),
body: Column(
children: [
AddIrisTypeManageTabbar(
lockId: lockId,
fromType: fromType,
fromTypeTwoStaffName: fromTypeTwoStaffName,
initialIndex: index),
],
),
);
}
}

View File

@ -0,0 +1,138 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/iris/addIrisType/addIrisType_page.dart';
import '../../../../../app_settings/app_colors.dart';
import '../../../../../tools/CustomUnderlineTabIndicator.dart';
import '../../../../../translations/trans_lib.dart';
class AddIrisTypeManageTabbar extends StatefulWidget {
var initialIndex = 1;
var lockId = 0;
var fromType = 1; // 1 2
var fromTypeTwoStaffName = ""; //
AddIrisTypeManageTabbar(
{Key? key,
required this.lockId,
required this.fromType,
required this.fromTypeTwoStaffName,
required this.initialIndex})
: super(key: key);
@override
State<AddIrisTypeManageTabbar> createState() =>
_AddFaceTypeManageTabbarState();
}
class _AddFaceTypeManageTabbarState extends State<AddIrisTypeManageTabbar>
with SingleTickerProviderStateMixin {
late TabController _tabController;
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"),
];
@override
void initState() {
// TODO: implement initState
super.initState();
_tabController = TabController(
vsync: this,
length: _itemTabs.length,
initialIndex: widget.initialIndex);
_tabController.addListener(() {
// print("_tabController.animation!.value:${_tabController.animation!.value} _tabController.index:${_tabController.index}");
if (_tabController.animation!.value == _tabController.index) {
FocusScope.of(context).requestFocus(FocusNode());
}
});
}
@override
Widget build(BuildContext context) {
return Expanded(
child: Column(
children: [
_tabBar(),
_pageWidget(),
],
));
}
TabBar _tabBar() {
return TabBar(
controller: _tabController,
tabs: widget.fromType == 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: _tabController,
children: widget.fromType == 1
? _itemTabs
.map((ItemView item) => AddIrisTypePage(
selectType: item.selectType,
lockId: widget.lockId,
fromType: widget.fromType,
fromTypeTwoStaffName: widget.fromTypeTwoStaffName))
.toList()
: _itemTabs
.map((ItemView item) => AddIrisTypePage(
selectType: item.selectType,
lockId: widget.lockId,
fromType: widget.fromType,
fromTypeTwoStaffName: widget.fromTypeTwoStaffName))
.toList(),
// _itemTabs.map((ItemView item) => AddFaceTypePage(selectType: item.selectType, lockId: widget.lockId, fromType: widget.fromType, fromTypeTwoStaffName:widget.fromTypeTwoStaffName)).toList(),
),
);
}
}
class ItemView {
const ItemView({required this.title, required this.selectType});
final String title;
final String selectType;
}

View File

@ -0,0 +1,99 @@
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/face/addFaceType/addFaceType_state.dart';
import 'package:star_lock/tools/baseGetXController.dart';
import '../../../../appRouters.dart';
import '../../../../network/api_repository.dart';
class AddIrisTypeLogic extends BaseGetXController {
AddFaceTypeState state = AddFaceTypeState();
//
void addFaceData() async {
var faceType = 0; // :1;23:4
var startDate = "";
var endDate = "";
if (state.seletType.value == "0") {
faceType = 1;
startDate = "0";
endDate = "0";
} else if (state.seletType.value == "1") {
faceType = 2;
if (state.beginTimeTimestamp.value.isEmpty) {
showToast("请选择开始时间");
return;
}
if (state.endTimeTimestamp.value.isEmpty) {
showToast("请选择结束时间");
return;
}
// if(DateTime.now().millisecondsSinceEpoch > int.parse(state.beginTimeTimestamp.value)){
// Toast.show(msg: "生效时间要大于当前时间");
// return;
// }
if (int.parse(state.beginTimeTimestamp.value) >=
int.parse(state.endTimeTimestamp.value)) {
showToast("失效时间要大于生效时间");
return;
}
startDate = state.beginTimeTimestamp.value;
endDate = state.endTimeTimestamp.value;
} else if (state.seletType.value == "2") {
if (state.effectiveDateTime.value <= 0) {
showToast("请选择生效时间");
return;
}
if (state.failureDateTime.value <= 0) {
showToast("请选择失效时间");
return;
}
if (state.weekdaysList.value.isEmpty) {
showToast("请选择有效日");
return;
}
// if(DateTime.now().millisecondsSinceEpoch >= state.effectiveDateTime.value){
// Toast.show(msg: "生效时间要大于当前时间");
// return;
// }
if (state.effectiveDateTime.value >= state.failureDateTime.value) {
showToast("失效时间要大于生效时间");
return;
}
startDate = state.effectiveDateTime.value.toString();
endDate = state.failureDateTime.value.toString();
faceType = 4;
}
print(
"传出去的给你限时人脸开始时间:${int.parse(startDate) ~/ 1000} 限时人脸结束时间:${int.parse(endDate) ~/ 1000}");
//
Get.toNamed(Routers.addIrisPage, arguments: {
"lockId": state.lockId.value,
"endDate": int.parse(endDate),
"addType": "1",
"faceName": state.nameController.text,
"faceNumber": "123456",
"faceType": faceType,
"startDate": int.parse(startDate),
"cyclicConfig": state.weekdaysList.value,
"fromType": state.fromType.value,
"isAdministrator": state.isAdministrator.value,
});
}
//
void checkFaceNameDuplicated(String faceName) async {
var entity = await ApiRepository.to.checkFaceNameDuplicatedData(
lockId: state.lockId.value.toString(),
faceName: faceName,
);
if (entity.errorCode!.codeIsSuccessful) {
addFaceData();
}
}
}

View File

@ -0,0 +1,322 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/iris/addIrisType/addIrisType_logic.dart';
import 'package:star_lock/tools/pickers/pickers.dart';
import 'package:star_lock/tools/pickers/time_picker/model/date_mode.dart';
import '../../../../appRouters.dart';
import '../../../../app_settings/app_colors.dart';
import '../../../../tools/commonItem.dart';
import '../../../../tools/storage.dart';
import '../../../../tools/submitBtn.dart';
import '../../../../translations/trans_lib.dart';
class AddIrisTypePage extends StatefulWidget {
final String selectType; //
final int lockId;
final int fromType; // // 1 2
final String fromTypeTwoStaffName; //
const AddIrisTypePage(
{Key? key,
required this.selectType,
required this.lockId,
required this.fromType,
required this.fromTypeTwoStaffName})
: super(key: key);
@override
State<AddIrisTypePage> createState() => _AddFaceTypePageState();
}
class _AddFaceTypePageState extends State<AddIrisTypePage> {
final logic = Get.put(AddIrisTypeLogic());
final state = Get.find<AddIrisTypeLogic>().state;
@override
Widget build(BuildContext context) {
state.seletType.value = widget.selectType;
state.lockId.value = widget.lockId;
if (widget.fromTypeTwoStaffName.isNotEmpty) {
state.nameController.text = widget.fromTypeTwoStaffName;
}
state.fromType.value = widget.fromType;
return indexChangeWidget();
}
Widget indexChangeWidget() {
switch (int.parse(widget.selectType)) {
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(),
keyBottomWidget()
],
);
}
case 2:
{
//
return Column(
children: [
perpetualKeyWidget(
TranslationLoader.lanKeys!.name!.tr,
TranslationLoader.lanKeys!.pleaseEnter!.tr,
state.nameController),
CommonItem(
leftTitel: TranslationLoader.lanKeys!.periodValidity!.tr,
rightTitle: "",
isHaveDirection: true,
action: () async {
Map result = await Get.toNamed(
Routers.electronicKeyPeriodValidityPage);
state.weekdaysList.value = result['validityValue'];
state.effectiveDateTime.value =
result['starDate'].millisecondsSinceEpoch;
state.failureDateTime.value =
result['endDate'].millisecondsSinceEpoch;
print(
'得到的有效期数据:${state.weekdaysList.value} == ${state.effectiveDateTime.value} == ${state.failureDateTime.value}');
}),
SizedBox(height: 10.h),
keyBottomWidget()
],
);
}
default:
return Container();
}
}
//
Widget perpetualKeyWidget(
String titleStr, String rightTitle, TextEditingController controller) {
return Column(
children: [
Container(height: 10.h),
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.beginTime.value,
isHaveLine: true,
isHaveDirection: true,
action: () async {
Pickers.showDatePicker(context, mode: DateMode.YMDHM,
onConfirm: (p) {
state.beginTime.value =
'${p.year}-${p.month!.toString().padLeft(2, '0')}-${p.day!.toString().padLeft(2, '0')} ${p.hour!.toString().padLeft(2, '0')}:${p.minute!.toString().padLeft(2, '0')}';
state.beginTimeTimestamp.value =
DateTime.parse(state.beginTime.value)
.millisecondsSinceEpoch
.toString();
});
})),
Obx(() => CommonItem(
leftTitel: TranslationLoader.lanKeys!.failureTime!.tr,
rightTitle: state.endTime.value,
isHaveDirection: true,
action: () {
Pickers.showDatePicker(context, mode: DateMode.YMDHM,
onConfirm: (p) {
state.endTime.value =
'${p.year}-${p.month!.toString().padLeft(2, '0')}-${p.day!.toString().padLeft(2, '0')} ${p.hour!.toString().padLeft(2, '0')}:${p.minute!.toString().padLeft(2, '0')}';
state.endTimeTimestamp.value =
DateTime.parse(state.endTime.value)
.millisecondsSinceEpoch
.toString();
});
})),
Container(height: 10.h),
],
);
}
Widget keyBottomWidget() {
return Column(
children: [
// CommonItem(
// leftTitel: TranslationLoader.lanKeys!.face!.tr,
// rightTitle: "",
// isTipsImg: false,
// isHaveRightWidget: true,
// rightWidget: SizedBox(
// width: 60.w, height: 50.h, child: _isStressFingerprint())),
CommonItem(
leftTitel: "是否是管理员",
rightTitle: "",
isTipsImg: false,
isHaveRightWidget: true,
rightWidget: SizedBox(
width: 60.w, height: 50.h, child: Obx(() => _isAdmin()))),
SizedBox(height: 30.h),
SubmitBtn(
btnName: TranslationLoader.lanKeys!.next!.tr,
onClick: () async {
var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot);
if (isDemoMode == false) {
// print("state.selectType:${state.selectType.value}");
if (state.nameController.text.isEmpty) {
logic.showToast("请输入姓名");
return;
}
logic.checkFaceNameDuplicated(state.nameController.text);
} 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: '完成',
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(
height: 50.h,
width: 300.w,
child: Row(
children: [
Expanded(
child: TextField(
//
maxLines: 1,
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: 24.sp),
//线
border: InputBorder.none,
),
),
),
SizedBox(
width: 10.w,
),
],
),
);
}
//
CupertinoSwitch _isAdmin() {
return CupertinoSwitch(
activeColor: CupertinoColors.activeBlue,
trackColor: CupertinoColors.systemGrey5,
thumbColor: CupertinoColors.white,
value: state.isAdministrator.value,
onChanged: (value) {
state.isAdministrator.value = value;
},
);
}
}

View File

@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class AddFaceTypeState {
final lockId = 0.obs;
final seletType = "0".obs; // 0 1 2
final fromType = 1.obs; // // 1 2
var fromTypeTwoStaffName = "".obs; //
final isStressFingerprint = false.obs;
final isAdministrator = false.obs; //
var beginTime = "".obs; //
var endTime = "".obs; //
var beginTimeTimestamp = "".obs; //
var endTimeTimestamp = "".obs; //
var effectiveDateTime = 0.obs; //
var failureDateTime = 0.obs; //
var weekdaysList = [].obs;
final TextEditingController nameController = TextEditingController();
AddFaceTypeState() {
// Map map = Get.arguments;
// lockId.value = map["lockId"];
// fromType.value = map["fromType"];
// if(fromType.value == 2){
// fromTypeTwoStaffName = map["fromTypeTwoStaffName"]; //
// // nameController.text = fromTypeTwoStaffName.value;
// }
// print("lockId:${lockId.value} fromType:${fromType.value}");
}
}

View File

@ -0,0 +1,445 @@
import 'dart:async';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:star_lock/blue/io_protocol/io_addFace.dart';
import 'package:star_lock/blue/io_protocol/io_queryingFaceStatus.dart';
import 'package:star_lock/blue/io_type.dart';
import 'package:star_lock/main/lockDetail/iris/irisList/irisList_state.dart';
import 'package:star_lock/tools/baseGetXController.dart';
import '../../../../blue/blue_manage.dart';
import '../../../../blue/io_protocol/io_checkingUserInfoCount.dart';
import '../../../../blue/io_reply.dart';
import '../../../../blue/io_tool/io_tool.dart';
import '../../../../blue/io_tool/manager_event_bus.dart';
import '../../../../blue/sender_manage.dart';
import '../../../../network/api_repository.dart';
import '../../../../tools/eventBusEventManage.dart';
import '../../../../tools/storage.dart';
class IrisListLogic extends BaseGetXController {
IrisListState state = IrisListState();
//
late StreamSubscription<Reply> _replySubscription;
void _initReplySubscription() {
_replySubscription =
EventBusManager().eventBus!.on<Reply>().listen((reply) {
// ()
if ((reply is SenderAddFaceReply) && (state.isDeletFaceData == true)) {
_replyAddFaceBegin(reply);
}
if (reply is SenderQueryingFaceStatusReply) {
//
_replyQueryingFaceStatus(reply);
}
if (reply is SenderCheckingUserInfoCountReply) {
_replyCheckingUserInfoCount(reply);
}
});
}
// ---
Future<void> _replyAddFaceBegin(Reply reply) async {
int status = reply.data[2];
print("status:$status");
switch (status) {
case 0x00:
//
print("${reply.commandType!.typeValue} list人脸数据解析成功");
state.isDeletFaceData = false;
cancelBlueConnetctToastTimer();
dismissEasyLoading();
if (state.isDeletAll == false) {
deletFacesData();
} else {
clearAllFacesData();
}
break;
case 0x06:
//
print("${reply.commandType!.typeValue} 需要鉴权");
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var publicKey = await Storage.getStringList(saveBluePublicKey);
List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
var token = await Storage.getStringList(saveBlueToken);
List<int> getTokenList = changeStringListToIntList(token!);
IoSenderManage.senderAddFaceCommand(
keyID: state.deletKeyID,
userID: state.deletUserID,
faceNo: state.deletFaceNo,
useCountLimit: 0,
startTime: 0x11223344,
endTime: 0x11223344,
needAuthor: 1,
publicKey: publicKeyDataList,
privateKey: getPrivateKeyList,
token: getTokenList,
);
break;
case 0x07:
//
print("${reply.commandType!.typeValue} 用户无权限");
break;
case 0x09:
//
print("${reply.commandType!.typeValue} 权限校验错误");
break;
default:
//
print("${reply.commandType!.typeValue} list人脸失败");
break;
}
}
//
Future<void> _replyQueryingFaceStatus(Reply reply) async {
int status = reply.data[2];
switch (status) {
case 0x00:
//
print("${reply.commandType}数据解析成功");
// _getLockStatus();
break;
case 0x06:
//
print("${reply.commandType}需要鉴权");
break;
case 0x07:
//
print("${reply.commandType}用户无权限");
break;
case 0x09:
//
print("${reply.commandType}权限校验错误");
break;
default:
//
print("${reply.commandType}失败");
break;
}
}
//
Future<void> _replyReferEventRecordNumber(Reply reply) async {
int status = reply.data[2];
switch (status) {
case 0x00:
//
print("${reply.commandType}数据解析成功");
// _getLockStatus();
break;
case 0x06:
//
print("${reply.commandType}需要鉴权");
break;
case 0x07:
//
print("${reply.commandType}用户无权限");
break;
case 0x09:
//
print("${reply.commandType}权限校验错误");
break;
default:
//
print("${reply.commandType}失败");
break;
}
}
// ()
Future<void> _replyCheckingUserInfoCount(Reply reply) async {
int status = reply.data[2];
//
int userNum = reply.data[5];
// print("userNum:$userNum");
//
int fingerNum = reply.data[6];
// print("fingerNum:$fingerNum");
//
int pwdNum = reply.data[7];
//
int cardNum = reply.data[8];
//
int logsNum = reply.data[9];
//
int verNo = reply.data[10];
//
int maxAdminFingerNum = reply.data[11];
//
int maxUserFingerNum = reply.data[12];
//
int maxAdminPassNum = reply.data[13];
//
int maxUserPassNum = reply.data[14];
//
int maxAdminCardNum = reply.data[15];
//
int maxUserCardNum = reply.data[16];
//
var serialNo = reply.data.sublist(17, 21);
print("serialNo:$serialNo");
switch (status) {
case 0x00:
//
print("${reply.commandType}数据解析成功");
// _getLockStatus();
break;
case 0x06:
//
print("${reply.commandType}需要鉴权");
break;
case 0x07:
//
print("${reply.commandType}用户无权限");
break;
case 0x09:
//
print("${reply.commandType}权限校验错误");
break;
default:
//
print("${reply.commandType}失败");
break;
}
}
//
Future<void> senderQueryingFaceStatus() async {
BlueManage().bludSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState state) async {
if (state == BluetoothConnectionState.connected) {
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var token = await Storage.getStringList(saveBlueToken);
List<int> getTokenList = changeStringListToIntList(token!);
var publicKey = await Storage.getStringList(saveBluePublicKey);
List<int> getPublicKeyList = changeStringListToIntList(publicKey!);
IoSenderManage.senderQueryingFaceStatusCommand(
keyID: BlueManage().connectDeviceName,
userID: await Storage.getUid(),
role: 0xff,
faceCount: 20,
faceNo: 1,
token: getTokenList,
needAuthor: 1,
publicKey: getPublicKeyList,
privateKey: getPrivateKeyList,
);
}
});
}
// ()
Future<void> senderCheckingUserInfoCount() async {
BlueManage().bludSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState state) async {
if (state == BluetoothConnectionState.connected) {
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var token = await Storage.getStringList(saveBlueToken);
List<int> getTokenList = changeStringListToIntList(token!);
var publicKey = await Storage.getStringList(saveBluePublicKey);
List<int> getPublicKeyList = changeStringListToIntList(publicKey!);
IoSenderManage.senderCheckingUserInfoCountCommand(
keyID: BlueManage().connectDeviceName,
userID: await Storage.getUid(),
role: 0xff,
nowTime: DateTime.now().millisecondsSinceEpoch ~/ 1000,
token: getTokenList,
needAuthor: 1,
publicKey: getPublicKeyList,
privateKey: getPrivateKeyList,
);
}
});
}
//
Future<void> senderAddFace() async {
showEasyLoading();
showBlueConnetctToastTimer(action: () {
dismissEasyLoading();
});
BlueManage().bludSendData(BlueManage().connectDeviceName,
(BluetoothConnectionState deviceConnectionState) async {
if (deviceConnectionState == BluetoothConnectionState.connected) {
var publicKey = await Storage.getStringList(saveBluePublicKey);
List<int> publicKeyDataList = changeStringListToIntList(publicKey!);
var privateKey = await Storage.getStringList(saveBluePrivateKey);
List<int> getPrivateKeyList = changeStringListToIntList(privateKey!);
var token = await Storage.getStringList(saveBlueToken);
List<int> getTokenList = changeStringListToIntList(token!);
IoSenderManage.senderAddFaceCommand(
keyID: state.deletKeyID,
userID: state.deletUserID,
faceNo: state.deletFaceNo,
useCountLimit: 0,
startTime: 0x11223344,
endTime: 0x11223344,
needAuthor: 1,
publicKey: publicKeyDataList,
privateKey: getPrivateKeyList,
token: getTokenList,
);
} else if (deviceConnectionState ==
BluetoothConnectionState.disconnected) {
dismissEasyLoading();
cancelBlueConnetctToastTimer();
if (state.ifCurrentScreen.value == true) {
showBlueConnetctToast();
}
}
});
}
//
void getFaceListData() async {
var entity = await ApiRepository.to.getFaceListData(
lockId: state.lockId.value.toString(),
pageNo: '1',
pageSize: '20',
searchStr: state.searchController.text,
);
if (entity.errorCode!.codeIsSuccessful) {
state.faceItemListData.value = entity.data!.list!;
}
}
//
void deletFacesData() async {
var faceId = "";
var type = "1";
if (state.isDeletAll == false) {
faceId = state.deletKeyID;
type = "0";
}
print("delet faceId $faceId");
var entity = await ApiRepository.to.deleteFaceData(
faceId: int.parse(faceId),
lockId: state.lockId.value,
);
if (entity.errorCode!.codeIsSuccessful) {
showToast("删除成功");
state.isDeletFaceData = false;
getFaceListData();
}
}
//
void clearAllFacesData() async {
var faceId = "";
var type = "1";
if (state.isDeletAll == false) {
faceId = state.deletKeyID;
type = "0";
}
print("delet faceId $faceId");
var entity = await ApiRepository.to.clearFaceData(
lockId: state.lockId.value,
);
if (entity.errorCode!.codeIsSuccessful) {
showToast("重置成功");
state.isDeletFaceData = false;
getFaceListData();
}
}
//
late StreamSubscription _teamEvent;
void _initRefreshAction() {
_teamEvent = eventBus.on<OtherTypeRefreshListEvent>().listen((event) {
getFaceListData();
});
}
@override
Future<void> onReady() async {
// TODO: implement onReady
super.onReady();
print("onReady()");
//
var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot);
// print("aaaaaaa:$isDemoMode");
if (isDemoMode == false) {
_initReplySubscription();
_initRefreshAction();
getFaceListData();
}
}
@override
Future<void> onInit() async {
// TODO: implement onInit
super.onInit();
print("onInit()");
var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot);
if (isDemoMode == false) {
// senderQueryingFingerprintStatus();
// senderCheckingCardStatus();
// senderCheckingUserInfoCount();
}
}
@override
Future<void> onClose() async {
// TODO: implement onClose
super.onClose();
var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot);
if (isDemoMode == false) {
_replySubscription.cancel();
_teamEvent.cancel();
}
}
}

View File

@ -0,0 +1,280 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/fingerprint/fingerprintList/fingerprintListData_entity.dart';
import 'package:star_lock/main/lockDetail/iris/irisList/irisList_logic.dart';
import 'package:star_lock/tools/keySearchWidget.dart';
import 'package:star_lock/tools/left_slide_actions.dart';
import '../../../../appRouters.dart';
import '../../../../app_settings/app_colors.dart';
import '../../../../tools/noData.dart';
import '../../../../tools/showIosTipView.dart';
import '../../../../tools/storage.dart';
import '../../../../tools/submitBtn.dart';
import '../../../../tools/titleAppBar.dart';
import '../../../../translations/trans_lib.dart';
class IrisListPage extends StatefulWidget {
const IrisListPage({Key? key}) : super(key: key);
@override
State<IrisListPage> createState() => _IrisListPageState();
}
class _IrisListPageState extends State<IrisListPage> {
final logic = Get.put(IrisListLogic());
final state = Get.find<IrisListLogic>().state;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.mainBackgroundColor,
appBar: TitleAppBar(
barTitle: '虹膜',
haveBack: true,
backgroundColor: AppColors.mainColor,
actionsList: [
TextButton(
child: Text(
TranslationLoader.lanKeys!.reset!.tr,
style: TextStyle(color: Colors.white, fontSize: 24.sp),
),
onPressed: () async {
var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot);
if (isDemoMode == false) {
showDeletAlertDialog(context);
} else {
// Get.toNamed(Routers.selectLockTypePage);
logic.showToast("演示模式");
}
},
),
],
),
body: Column(
children: [
KeySearchWidget(
editingController: state.searchController,
onSubmittedAction: () {
logic.getFaceListData();
},
),
SizedBox(
height: 20.h,
),
Expanded(child: _buildMainUI()),
AddBottomWhiteBtn(
btnName: '${TranslationLoader.lanKeys!.add!.tr}虹膜',
onClick: () async {
// var data =
// await Get.toNamed(Routers.addFaceTypeManagePage, arguments: {
// "lockId": state.lockId.value,
// "fromType": 1 // 1 2
// });
var data =
await Get.toNamed(Routers.addIrisTypeManagePage, arguments: {
"lockId": state.lockId.value,
"fromType": 1 // 1 2
});
if (data != null) {
logic.getFaceListData();
}
},
),
SizedBox(height: 64.h)
],
),
);
}
Widget _buildMainUI() {
{
return Obx(() => state.faceItemListData.value.isNotEmpty
? ListView.separated(
itemCount: state.faceItemListData.value.length,
itemBuilder: (c, index) {
FingerprintItemData getFaceItemData =
state.faceItemListData.value[index];
//
if (index < state.faceItemListData.value.length) {
return LeftSlideActions(
key: Key(getFaceItemData.faceName!),
actionsWidth: 60,
actions: [
_buildDeleteBtn(getFaceItemData),
],
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(1)),
),
child: _keyItem(
'images/icon_face.png',
getFaceItemData.faceName!,
(getFaceItemData.faceType! != 1)
? (getFaceItemData.endDate! <
DateTime.now().millisecondsSinceEpoch
? "已失效"
: "")
: "",
getFaceItemData.validTimeStr!,
// fingerprintItemData.fingerprintType! == 1
// ? "永久"
// : "${DateTool().dateToYMDHNString(fingerprintItemData.startDate.toString())} - ${DateTool().dateToYMDHNString(fingerprintItemData.endDate.toString())}",
() async {
var data =
await Get.toNamed(Routers.faceDetailPage, arguments: {
"faceItemData": getFaceItemData,
});
if (data != null) {
logic.getFaceListData();
}
}),
);
}
return const SizedBox.shrink();
},
separatorBuilder: (BuildContext context, int index) {
return const Divider(
height: 1,
color: AppColors.greyLineColor,
);
},
)
: NoData(noDataHeight: 1.sh - ScreenUtil().statusBarHeight - 170.h));
}
}
Widget _buildDeleteBtn(FingerprintItemData faceItemData) {
return GestureDetector(
onTap: () {
// :
state.deletKeyID = faceItemData.faceId.toString();
state.deletFaceNo = int.parse(faceItemData.faceNumber!);
showIosTipViewDialog(context);
},
child: Container(
width: 60,
color: const Color(0xFFF20101),
alignment: Alignment.center,
child: const Text(
'删除',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.white,
height: 1,
),
),
),
);
}
void showIosTipViewDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return ShowIosTipView(
title: "提示",
tipTitle: "确定要删除吗?",
sureClick: () async {
Get.back();
state.isDeletFaceData = true;
state.isDeletAll = false;
state.deletUserID = (await Storage.getUid())!;
logic.senderAddFace();
},
cancelClick: () {
Get.back();
},
);
},
);
}
Widget _keyItem(String lockTypeIcon, String lockTypeTitle,
String ifInvalidation, String showTime, Function() action) {
return GestureDetector(
onTap: action,
child: Container(
height: 90.h,
// margin: EdgeInsets.only(left: 20.w, right: 20.w, top: 20.w),
color: Colors.white,
// decoration: BoxDecoration(
// color: Colors.white,
// // borderRadius: BorderRadius.circular(10.w),
// ),
child: Row(
children: [
SizedBox(width: 30.w),
Image.asset(lockTypeIcon, width: 60.w, height: 60.w),
SizedBox(width: 20.w),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(lockTypeTitle,
style: TextStyle(
fontSize: 24.sp, color: AppColors.blackColor)),
Expanded(child: Container()),
Text(ifInvalidation,
style: TextStyle(fontSize: 22.sp, color: Colors.red)),
SizedBox(width: 10.w),
],
),
SizedBox(height: 5.h),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(showTime,
style: TextStyle(
fontSize: 18.sp,
color: AppColors.placeholderTextColor)),
],
),
SizedBox(width: 20.h),
],
),
),
SizedBox(width: 20.h),
],
),
),
);
}
void showDeletAlertDialog(BuildContext context) {
showCupertinoDialog(
context: context,
builder: (context) {
return CupertinoAlertDialog(
title: const Text("提示"),
content: const Text('重置后,该锁的人脸都将被删除哦,确认要重置吗?'),
actions: [
CupertinoDialogAction(
child: Text(TranslationLoader.lanKeys!.cancel!.tr),
onPressed: () {
Navigator.pop(context);
},
),
CupertinoDialogAction(
child: Text(TranslationLoader.lanKeys!.sure!.tr),
onPressed: () {
Navigator.pop(context);
state.isDeletFaceData = true;
state.isDeletAll = true;
state.deletKeyID = "1";
state.deletUserID = "DeleteAll!@#";
state.deletFaceNo = 255;
logic.senderAddFace();
},
),
],
);
},
);
}
}

View File

@ -0,0 +1,24 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/fingerprint/fingerprintList/fingerprintListData_entity.dart';
class IrisListState {
final TextEditingController searchController = TextEditingController();
final lockId = 0.obs;
//
var isDeletFaceData = false;
var isDeletAll = false;
var deletKeyID = "";
var deletUserID = "DeleteAll!@#";
var deletFaceNo = 0;
final faceItemListData = <FingerprintItemData>[].obs;
var ifCurrentScreen = true.obs; // ,
IrisListState() {
Map map = Get.arguments;
lockId.value = map["lockId"];
}
}

View File

@ -1,6 +1,5 @@
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
@ -672,13 +671,31 @@ class _LockDetailPageState extends State<LockDetailPage>
TranslationLoader.lanKeys!.humanFace!.tr,
state.openDoorBtnisUneable.value,
state.bottomBtnisEable.value, () {
Get.toNamed(Routers.faceList, arguments: {
Get.toNamed(Routers.faceListPage, arguments: {
"lockId": state.keyInfos.value.lockId,
}); // Toast.show(msg: "功能暂未开放");
});
}),
);
}
showWidgetArr.add(
bottomItem('images/main/icon_face.png', '虹膜',
state.openDoorBtnisUneable.value, state.bottomBtnisEable.value, () {
Get.toNamed(Routers.irisListPage, arguments: {
"lockId": state.keyInfos.value.lockId,
});
}),
);
showWidgetArr.add(
bottomItem(
'images/main/icon_face.png',
'手掌',
state.openDoorBtnisUneable.value,
state.bottomBtnisEable.value,
() {}),
);
//->
if (state.keyInfos.value.lockFeature!.videoIntercom == 1) {
showWidgetArr.add(

View File

@ -46,7 +46,7 @@ class _LockMonitoringPageState extends State<LockMonitoringPage> {
child: Container(
width: 1.sw,
height: 1.sh,
color: Colors.white,
// color: Colors.white,
child: Stack(
children: [
Obx(() {

View File

@ -292,7 +292,7 @@ class _DemoModeLockDetailPageState extends State<DemoModeLockDetailPage> {
bottomItem('images/main/icon_face.png', '人脸', () {
// gotoLogin();
Get.toNamed(Routers.faceList, arguments: {
Get.toNamed(Routers.faceListPage, arguments: {
"lockId": 1,
});
}),

View File

@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:star_lock/app_settings/app_settings.dart';
class PermissionDialog {
static Map<Permission, String> titles = {
Permission.camera: '相机',
Permission.photos: '相册',
Permission.storage: '读写',
Permission.location: '定位',
};
static Map<Permission, String> contents = {
Permission.camera: '需要访问相机权限才能拍照上传文件例如头像上传',
Permission.photos: '需要访问相机权限才能使用相册图片上传文件上传头像',
Permission.storage: '需要访问读写权限才能使用本地图片上传头像',
Permission.location: '需要访问定位权限才能使用添加钥匙功能的位置信息',
};
//
static Future<bool> request(Permission permission) async {
if (Get.context == null) {
return false;
}
bool application = true;
if (AppPlatform.isAndroid) {
application = await showDialog(
context: Get.context!,
builder: (BuildContext context) {
return AlertDialog(
title: Text('申请${titles[permission] ?? ''}权限'),
content: Text(contents[permission] ?? ''),
actions: <Widget>[
TextButton(
child: const Text('不允许'),
onPressed: () {
Get.back(result: false);
},
),
TextButton(
child: const Text('允许'),
onPressed: () {
Get.back(result: true);
},
),
],
);
},
);
}
if (!application) {
showSet(permission);
return false;
} else {
return await permission.request().isGranted;
}
}
//
static Future<void> showSet(Permission permission) async {
if (Get.context == null) {
return;
}
showDialog(
context: Get.context!,
builder: (BuildContext context) {
return AlertDialog(
title: Text('${titles[permission] ?? ''}权限被拒绝'),
content: Text('${contents[permission] ?? ''},请手动在系统设置中开启${titles[permission]}权限以继续使用应用。'),
actions: <Widget>[
TextButton(
child: Text('去设置'),
onPressed: () {
Get.back(); //
openAppSettings(); //
},
),
],
);
},
);
}
}

View File

@ -133,7 +133,6 @@ dependencies:
#控制横竖屏控件
auto_orientation: ^2.3.1
audioplayers: ^5.2.1
g711_flutter: ^2.0.0
ffi: ^2.1.0
flutter_mjpeg: ^2.0.4
image_gallery_saver: ^2.0.3