feat: 完善设备设置页、设备基本信息页、设备支持项、设备设置项、搜索wifi、连接wifi
This commit is contained in:
parent
47d9e666c1
commit
3cc225c762
@ -15,6 +15,9 @@ class BaseController extends GetxController {
|
||||
}
|
||||
|
||||
void showLoading() {
|
||||
if (EasyLoading.isShow) {
|
||||
return;
|
||||
}
|
||||
EasyLoading.show(status: AppToastMessages.loading);
|
||||
}
|
||||
|
||||
|
||||
3
lib/common/constant/lock_function_number.dart
Normal file
3
lib/common/constant/lock_function_number.dart
Normal file
@ -0,0 +1,3 @@
|
||||
class LockFunctionNumber {
|
||||
static const int remoteUnlocking = 28;
|
||||
}
|
||||
@ -13,27 +13,33 @@ class CustomCellListWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// ✅ 第一步:过滤出 visible == true 的项
|
||||
final visibleChildren = children
|
||||
.where((child) => (child.visible ?? true)) // 假设 CustomCellWidget 有 visible 属性
|
||||
.toList();
|
||||
|
||||
// ✅ 第二步:只在可见项之间添加 Divider
|
||||
final List<Widget> items = [];
|
||||
for (int i = 0; i < visibleChildren.length; i++) {
|
||||
items.add(visibleChildren[i]);
|
||||
if (i < visibleChildren.length - 1) {
|
||||
items.add(Divider(
|
||||
height: 0.5.h,
|
||||
thickness: 0.5.h,
|
||||
color: Colors.grey[300],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w),
|
||||
child: Column(
|
||||
children: [
|
||||
for (int i = 0; i < children.length; i++) ...[
|
||||
children[i],
|
||||
if (i < children.length - 1)
|
||||
Divider(
|
||||
height: 0.5.h,
|
||||
thickness: 0.5.h,
|
||||
color: Colors.grey[300],
|
||||
),
|
||||
],
|
||||
],
|
||||
children: items, // ✅ 只渲染可见项和它们之间的分隔线
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -9,15 +9,20 @@ class CustomCellWidget extends StatelessWidget {
|
||||
this.leftIcon,
|
||||
this.rightWidget,
|
||||
this.onTap,
|
||||
this.visible = true,
|
||||
});
|
||||
|
||||
final String leftText;
|
||||
final Icon? leftIcon;
|
||||
final Widget? rightWidget;
|
||||
final GestureTapCallback? onTap;
|
||||
|
||||
final bool visible; // 控制是否显示
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 如果不显示,返回空
|
||||
if (!visible) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
|
||||
@ -2,12 +2,16 @@ import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/routes/app_routes.dart';
|
||||
import 'package:starwork_flutter/views/device/confirmPairDevice/confirm_pair_device_binding.dart';
|
||||
import 'package:starwork_flutter/views/device/confirmPairDevice/confirm_pair_device_view.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceBasisInfo/device_basis_info_binding.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceBasisInfo/device_basis_info_view.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceConfigureNetwork/device_configure_network_binding.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceConfigureNetwork/device_configure_network_view.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceManage/device_manage_binding.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceManage/device_manage_view.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceSearchNetwork/device_search_network_binding.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceSearchNetwork/device_search_network_view.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceSetting/device_setting_binding.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceSetting/device_setting_view.dart';
|
||||
import 'package:starwork_flutter/views/device/removeDevice/remove_device_binding.dart';
|
||||
import 'package:starwork_flutter/views/device/removeDevice/remove_device_view.dart';
|
||||
import 'package:starwork_flutter/views/device/searchDevice/search_device_binding.dart';
|
||||
@ -151,5 +155,15 @@ class AppPages {
|
||||
page: () => DeviceSearchNetworkView(),
|
||||
binding: DeviceSearchNetworkBinding(),
|
||||
),
|
||||
GetPage(
|
||||
name: AppRoutes.deviceSetting,
|
||||
page: () => DeviceSettingView(),
|
||||
binding: DeviceSettingBinding(),
|
||||
),
|
||||
GetPage(
|
||||
name: AppRoutes.deviceBasisInfo,
|
||||
page: () => DeviceBasisInfoView(),
|
||||
binding: DeviceBasisInfoBinding(),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@ -21,4 +21,6 @@ class AppRoutes{
|
||||
static const String deviceRemoveDevice = '/device/removeDevice';
|
||||
static const String deviceSearchNetwork = '/device/searchNetwork';
|
||||
static const String deviceConfigureNetwork = '/device/configureNetwork';
|
||||
static const String deviceSetting = '/device/deviceSetting';
|
||||
static const String deviceBasisInfo = '/device/deviceBasisInfo';
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceBasisInfo/device_basis_info_controller.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceSetting/device_setting_controller.dart';
|
||||
|
||||
class DeviceBasisInfoBinding extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut(() => DeviceBasisInfoController());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starcloud/entity/star_cloud_lock_list.dart';
|
||||
import 'package:starcloud/sdk/sdk_device_operate_extension.dart';
|
||||
import 'package:starcloud/sdk/starcloud.dart';
|
||||
import 'package:starwork_flutter/base/app_logger.dart';
|
||||
import 'package:starwork_flutter/base/base_controller.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_view_parameter_keys.dart';
|
||||
|
||||
class DeviceBasisInfoController extends BaseController {
|
||||
// 页面传递过来的锁信息
|
||||
StarCloudLock? lockInfo;
|
||||
|
||||
// 锁详情信息
|
||||
final lockDetailsInfo = StarCloudLock.empty().obs;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
// 读取参数
|
||||
final args = Get.arguments;
|
||||
if (args != null && args.containsKey(AppViewParameterKeys.lockInfo)) {
|
||||
final json = args[AppViewParameterKeys.lockInfo];
|
||||
lockInfo = StarCloudLock.fromJson(json, 0);
|
||||
}
|
||||
|
||||
_requestDetailsInfo();
|
||||
}
|
||||
|
||||
void _requestDetailsInfo() async {
|
||||
await StarCloudSDK.instance.getDevice(
|
||||
lockId: lockInfo?.lockId ?? 0,
|
||||
onSuccess: (lockInfo) {
|
||||
|
||||
lockDetailsInfo.value = lockInfo;
|
||||
AppLogger.highlight('message:${lockInfo}');
|
||||
},
|
||||
onError: (error) {
|
||||
AppLogger.error('message:${error}');
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
154
lib/views/device/deviceBasisInfo/device_basis_info_view.dart
Normal file
154
lib/views/device/deviceBasisInfo/device_basis_info_view.dart
Normal file
@ -0,0 +1,154 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_colors.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_images.dart';
|
||||
import 'package:starwork_flutter/common/widgets/custom_cell_list_widget.dart';
|
||||
import 'package:starwork_flutter/common/widgets/custom_cell_widget.dart';
|
||||
import 'package:starwork_flutter/common/widgets/custome_app_bar_wdiget.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceBasisInfo/device_basis_info_controller.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceSetting/device_setting_controller.dart';
|
||||
|
||||
class DeviceBasisInfoView extends GetView<DeviceBasisInfoController> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 即使不使用,只是引用一下 controller 就能触发初始化
|
||||
final _ = controller; // 添加这一行
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.scaffoldBackgroundColor,
|
||||
appBar: CustomAppBarWidget(
|
||||
title: '基本信息'.tr,
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
vertical: 10.h,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Obx(
|
||||
() => CustomCellListWidget(
|
||||
children: [
|
||||
CustomCellWidget(
|
||||
leftText: '设备图片'.tr,
|
||||
onTap: () {},
|
||||
rightWidget: Image(
|
||||
image: AssetImage(AppImages.iconLockTypeDoorLock),
|
||||
width: 48.w,
|
||||
height: 48.w,
|
||||
fit: BoxFit.contain,
|
||||
gaplessPlayback: true,
|
||||
// 防止闪烁
|
||||
filterQuality: FilterQuality.medium,
|
||||
// 优化过滤质量
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Icon(
|
||||
Icons.image_not_supported,
|
||||
size: 26.sp,
|
||||
color: Colors.grey,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
CustomCellWidget(
|
||||
leftText: '型号'.tr,
|
||||
onTap: () {
|
||||
// 复制到剪切板
|
||||
Clipboard.setData(ClipboardData(text: '1231231231'));
|
||||
controller.showToast('内容已复制'.tr);
|
||||
},
|
||||
rightWidget: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
controller.lockDetailsInfo.value.model,
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: Colors.black54,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 4.w,
|
||||
),
|
||||
Icon(
|
||||
Icons.library_books_rounded,
|
||||
size: 16.sp,
|
||||
color: Colors.grey,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
CustomCellWidget(
|
||||
leftText: '名称'.tr,
|
||||
onTap: () {
|
||||
// 复制到剪切板
|
||||
Clipboard.setData(ClipboardData(text: '1231231231'));
|
||||
controller.showToast('内容已复制'.tr);
|
||||
},
|
||||
rightWidget: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
controller.lockDetailsInfo.value.lockName,
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: Colors.black54,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 4.w,
|
||||
),
|
||||
Icon(
|
||||
Icons.library_books_rounded,
|
||||
size: 16.sp,
|
||||
color: Colors.grey,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
CustomCellWidget(
|
||||
leftText: '当前固件版本'.tr,
|
||||
onTap: () {
|
||||
// 复制到剪切板
|
||||
Clipboard.setData(ClipboardData(text: '1231231231'));
|
||||
controller.showToast('内容已复制'.tr);
|
||||
},
|
||||
rightWidget: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
controller.lockDetailsInfo.value.fwVersion,
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: Colors.black54,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 4.w,
|
||||
),
|
||||
Icon(
|
||||
Icons.library_books_rounded,
|
||||
size: 16.sp,
|
||||
color: Colors.grey,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,8 @@ import 'package:starcloud/sdk/sdk_configure_network_operate_extension.dart';
|
||||
import 'package:starcloud/sdk/starcloud.dart';
|
||||
import 'package:starwork_flutter/base/base_controller.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_view_parameter_keys.dart';
|
||||
import 'package:starwork_flutter/flavors.dart';
|
||||
import 'package:starwork_flutter/routes/app_routes.dart';
|
||||
|
||||
class DeviceConfigureNetworkController extends BaseController {
|
||||
// 锁信息
|
||||
@ -13,6 +15,7 @@ class DeviceConfigureNetworkController extends BaseController {
|
||||
StarCloudSearchWifiResult? networkInfo;
|
||||
|
||||
TextEditingController wifiNameInputController = TextEditingController();
|
||||
TextEditingController wifiPasswordInputController = TextEditingController();
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
@ -27,19 +30,30 @@ class DeviceConfigureNetworkController extends BaseController {
|
||||
final json = args[AppViewParameterKeys.networkInfo];
|
||||
networkInfo = StarCloudSearchWifiResult.fromJson(json);
|
||||
}
|
||||
|
||||
wifiNameInputController.text = networkInfo?.ssid ?? '';
|
||||
}
|
||||
|
||||
void configureNetwork() {
|
||||
if (wifiNameInputController.text.isEmpty) {
|
||||
showToast('WIFI昵称不能为空');
|
||||
return;
|
||||
}
|
||||
showLoading();
|
||||
StarCloudSDK.instance.connectWiFi(
|
||||
lockId: lockInfo!.lockId,
|
||||
onError: (err) {
|
||||
print("配置网络失败:${err}");
|
||||
showError(message: '配网失败,请重试'.tr);
|
||||
},
|
||||
onSuccess: () {},
|
||||
wifiName: networkInfo!.ssid,
|
||||
wifiPassword: '',
|
||||
clientId: '',
|
||||
starLockPeerId: '',
|
||||
onSuccess: () {
|
||||
showSuccess(message: '配网成功'.tr);
|
||||
Get.back();
|
||||
},
|
||||
wifiName: wifiNameInputController.text,
|
||||
wifiPassword: wifiPasswordInputController.text,
|
||||
clientId: F.starCloudClientId,
|
||||
starLockPeerId: '1232235156156',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_colors.dart';
|
||||
import 'package:starwork_flutter/common/widgets/custome_app_bar_wdiget.dart';
|
||||
import 'package:starwork_flutter/extension/function_extension.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceConfigureNetwork/device_configure_network_controller.dart';
|
||||
|
||||
class DeviceConfigureNetworkView extends GetView<DeviceConfigureNetworkController> {
|
||||
@ -18,61 +19,166 @@ class DeviceConfigureNetworkView extends GetView<DeviceConfigureNetworkControlle
|
||||
title: '配置网络'.tr,
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 38.h,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'*',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.red,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
vertical: 10.h,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 38.h,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'*',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'团队名称',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
Text(
|
||||
'WIFI名称',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
// 使用Expanded来确保TextField可以正确填充剩余空间
|
||||
child: TextField(
|
||||
controller: controller.wifiNameInputController,
|
||||
keyboardType: TextInputType.text,
|
||||
textInputAction: TextInputAction.done,
|
||||
textAlign: TextAlign.end,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'WIFI名称'.tr,
|
||||
// 设置无边框
|
||||
border: InputBorder.none,
|
||||
// 获取焦点时的边框
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
// 使用Expanded来确保TextField可以正确填充剩余空间
|
||||
child: TextField(
|
||||
controller: controller.wifiNameInputController,
|
||||
keyboardType: TextInputType.text,
|
||||
textInputAction: TextInputAction.done,
|
||||
textAlign: TextAlign.end,
|
||||
decoration: InputDecoration(
|
||||
hintText: '请输入团队/家庭名称'.tr,
|
||||
// 设置无边框
|
||||
border: InputBorder.none,
|
||||
// 获取焦点时的边框
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
),
|
||||
Container(
|
||||
height: 38.h,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'*',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'密码',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
// 使用Expanded来确保TextField可以正确填充剩余空间
|
||||
child: TextField(
|
||||
controller: controller.wifiPasswordInputController,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
textInputAction: TextInputAction.done,
|
||||
textAlign: TextAlign.end,
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'WIFI密码'.tr,
|
||||
// 设置无边框
|
||||
border: InputBorder.none,
|
||||
// 获取焦点时的边框
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
if (controller.wifiNameInputController.text.isEmpty) {
|
||||
controller.showToast('请先输入wifi名称'.tr);
|
||||
return;
|
||||
}
|
||||
if (controller.wifiPasswordInputController.text.isEmpty) {
|
||||
controller.showToast('请先输入wifi密码'.tr);
|
||||
return;
|
||||
}
|
||||
controller.configureNetwork();
|
||||
}.debounce(),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.blue,
|
||||
padding: EdgeInsets.symmetric(vertical: 12.h),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.r)),
|
||||
),
|
||||
child: Text(
|
||||
'确定'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
),
|
||||
Text(
|
||||
'请确保连接的WIFI为 2.4GHz',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: Colors.black87,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -37,6 +37,9 @@ class DeviceManageController extends BaseController with GetSingleTickerProvider
|
||||
// 刷新设备列表事件留监听
|
||||
late StreamSubscription _refreshDeviceListSubscription;
|
||||
|
||||
// 搜索输入框
|
||||
TextEditingController searchInputController = TextEditingController();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
@ -46,12 +49,18 @@ class DeviceManageController extends BaseController with GetSingleTickerProvider
|
||||
_refreshDeviceListSubscription = EventBusUtil().instance.on<RefreshDeviceListEvent>().listen((event) async {
|
||||
_requestTeamDeviceList();
|
||||
});
|
||||
|
||||
// 监听搜索输入框变化
|
||||
searchInputController.addListener(() {
|
||||
_updateFilteredList(); // 输入变化时重新过滤
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
_refreshDeviceListSubscription.cancel();
|
||||
searchInputController.dispose();
|
||||
}
|
||||
|
||||
void initData() async {
|
||||
@ -65,23 +74,33 @@ class DeviceManageController extends BaseController with GetSingleTickerProvider
|
||||
}
|
||||
|
||||
/// 根据当前 selectedStatusIndex 过滤设备列表
|
||||
/// 根据当前 selectedStatusIndex 和 搜索关键词 过滤设备列表
|
||||
void _updateFilteredList() {
|
||||
List<StarCloudLock> filtered = [];
|
||||
List<StarCloudLock> filtered = deviceList;
|
||||
|
||||
// Step 1: 先按状态筛选
|
||||
switch (selectedStatusIndex.value) {
|
||||
case 0: // 全部
|
||||
filtered = deviceList;
|
||||
break;
|
||||
case 1: // 在线
|
||||
filtered = deviceList.where((device) => device.isOnline == true).toList();
|
||||
filtered = filtered.where((device) => device.network?.isOnline == 1).toList();
|
||||
break;
|
||||
case 2: // 离线
|
||||
filtered = deviceList.where((device) => device.isOnline == false).toList();
|
||||
filtered = filtered.where((device) => device.network?.isOnline == 0).toList();
|
||||
break;
|
||||
default:
|
||||
filtered = deviceList;
|
||||
}
|
||||
filteredDeviceList.assignAll(filtered); // 更新响应式列表
|
||||
|
||||
// Step 2: 再按搜索关键词过滤(设备名称)
|
||||
final String keyword = searchInputController.text.trim();
|
||||
if (keyword.isNotEmpty) {
|
||||
filtered = filtered.where((device) {
|
||||
final name = device.lockName ?? '';
|
||||
return name.toLowerCase().contains(keyword.toLowerCase());
|
||||
}).toList();
|
||||
}
|
||||
|
||||
// 更新 UI 列表
|
||||
filteredDeviceList.assignAll(filtered);
|
||||
}
|
||||
|
||||
void _requestTeamDeviceList() async {
|
||||
@ -96,13 +115,21 @@ class DeviceManageController extends BaseController with GetSingleTickerProvider
|
||||
for (var groupItem in list.groupList) {
|
||||
for (var lock in groupItem.lockList) {
|
||||
deviceList.add(lock);
|
||||
if (lock.isOnline ?? false) {
|
||||
if (lock.network?.isOnline == 1) {
|
||||
onlineDeviceCount.value++;
|
||||
} else {
|
||||
offlineDeviceCount.value++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ✅ 在更新过滤前,先对 deviceList 按在线状态排序:在线在前,离线在后
|
||||
deviceList.sort((a, b) {
|
||||
final aOnline = a.network?.isOnline == 1;
|
||||
final bOnline = b.network?.isOnline == 1;
|
||||
if (aOnline == bOnline) return 0; // 状态相同,顺序不变
|
||||
if (aOnline) return -1; // a 在线,排前面
|
||||
return 1; // b 在线,或都离线,a 排后面
|
||||
});
|
||||
// ✅ 加载完原始数据后,更新过滤列表
|
||||
_updateFilteredList();
|
||||
hideLoading();
|
||||
|
||||
@ -114,8 +114,10 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
|
||||
_buildSearchBar() {
|
||||
return TextField(
|
||||
controller: controller.searchInputController,
|
||||
textInputAction: TextInputAction.search,
|
||||
decoration: InputDecoration(
|
||||
hintText: '请输入设备名称或编号'.tr,
|
||||
hintText: '请输入设备名称'.tr,
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: const Color(0xFF999999),
|
||||
@ -290,8 +292,8 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
final lock = controller.filteredDeviceList[index];
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Get.toNamed(AppRoutes.deviceSearchNetwork, arguments: {
|
||||
'lockInfo': lock.toJson(),
|
||||
Get.toNamed(AppRoutes.deviceSetting, arguments: {
|
||||
AppViewParameterKeys.lockInfo: lock.toJson(),
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
@ -333,8 +335,8 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
Text(
|
||||
lock.lockName,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 11.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@ -343,9 +345,9 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
height: 4.h,
|
||||
),
|
||||
Text(
|
||||
lock.isOnline ?? false ? '在线' : '离线',
|
||||
lock.network?.isOnline == 1 ? '在线' : '离线',
|
||||
style: TextStyle(
|
||||
color: lock.isOnline ?? false ? Colors.green : Colors.grey,
|
||||
color: lock.network?.isOnline == 1 ? Colors.green : Colors.grey,
|
||||
fontSize: 10.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceSetting/device_setting_controller.dart';
|
||||
|
||||
class DeviceSettingBinding extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut(() => DeviceSettingController());
|
||||
}
|
||||
}
|
||||
102
lib/views/device/deviceSetting/device_setting_controller.dart
Normal file
102
lib/views/device/deviceSetting/device_setting_controller.dart
Normal file
@ -0,0 +1,102 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_rx/get_rx.dart';
|
||||
import 'package:starcloud/entity/star_cloud_lock_list.dart';
|
||||
import 'package:starcloud/net/entity/api_response.dart';
|
||||
import 'package:starcloud/sdk/entity/entity_sender/enable_lock_settings.dart';
|
||||
|
||||
import 'package:starcloud/sdk/sdk_lock_setting_operate_extension.dart';
|
||||
import 'package:starcloud/sdk/starcloud.dart';
|
||||
import 'package:starwork_flutter/base/app_logger.dart';
|
||||
import 'package:starwork_flutter/base/base_controller.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_view_parameter_keys.dart';
|
||||
import 'package:starwork_flutter/common/constant/lock_function_number.dart';
|
||||
import 'package:starwork_flutter/common/events/refresh_device_list_event.dart';
|
||||
import 'package:starwork_flutter/common/utils/event_bus_util.dart';
|
||||
|
||||
class DeviceSettingController extends BaseController {
|
||||
// 锁信息
|
||||
StarCloudLock? lockInfo;
|
||||
|
||||
// 锁名称
|
||||
RxString lockName = ''.obs;
|
||||
|
||||
// 定义一个可观察的 Map
|
||||
final lockFeatureMap = <String, dynamic>{}.obs;
|
||||
final lockSettingMap = <String, dynamic>{}.obs;
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
// 读取参数
|
||||
final args = Get.arguments;
|
||||
if (args != null && args.containsKey(AppViewParameterKeys.lockInfo)) {
|
||||
final json = args[AppViewParameterKeys.lockInfo];
|
||||
lockInfo = StarCloudLock.fromJson(json, 0);
|
||||
lockName.value = lockInfo?.lockName ?? '';
|
||||
}
|
||||
|
||||
_readLockSetting();
|
||||
_readLockFeature();
|
||||
}
|
||||
|
||||
// 开启/关闭远程开锁
|
||||
void enableRemoteUnlock(bool value) async {
|
||||
showLoading();
|
||||
await StarCloudSDK.instance.enableLockSettings(
|
||||
lockId: lockInfo?.lockId ?? 0,
|
||||
lockSettings: EnableLockSettings(
|
||||
featureBit: LockFunctionNumber.remoteUnlocking,
|
||||
featureEnable: value,
|
||||
parameter: null,
|
||||
),
|
||||
onSuccess: () {
|
||||
_readLockSetting();
|
||||
hideLoading();
|
||||
},
|
||||
onError: (err) {
|
||||
AppLogger.error('开启/关闭远程开锁失败:${err}');
|
||||
hideLoading();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _readLockSetting() async {
|
||||
showLoading();
|
||||
await StarCloudSDK.instance.readLockSetting(
|
||||
lockId: lockInfo?.lockId ?? 0,
|
||||
onSuccess: (response) {
|
||||
if (response is ApiResponse) {
|
||||
final resultData = response as ApiResponse;
|
||||
if (resultData.isSuccess) {
|
||||
lockSettingMap.value = resultData.data['lockSetting'];
|
||||
}
|
||||
}
|
||||
hideLoading();
|
||||
},
|
||||
onError: (err) {
|
||||
AppLogger.error('读取锁设置失败:${err}');
|
||||
hideLoading();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _readLockFeature() async {
|
||||
showLoading();
|
||||
await StarCloudSDK.instance.readLockFeature(
|
||||
lockId: lockInfo?.lockId ?? 0,
|
||||
onSuccess: (response) {
|
||||
if (response is ApiResponse) {
|
||||
final resultData = response as ApiResponse;
|
||||
if (resultData.isSuccess) {
|
||||
lockFeatureMap.value = resultData.data['lockFeature'];
|
||||
}
|
||||
}
|
||||
hideLoading();
|
||||
},
|
||||
onError: (err) {
|
||||
AppLogger.error('读取锁设置失败:${err}');
|
||||
hideLoading();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
182
lib/views/device/deviceSetting/device_setting_view.dart
Normal file
182
lib/views/device/deviceSetting/device_setting_view.dart
Normal file
@ -0,0 +1,182 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_colors.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_images.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_view_parameter_keys.dart';
|
||||
import 'package:starwork_flutter/common/widgets/custom_cell_list_widget.dart';
|
||||
import 'package:starwork_flutter/common/widgets/custom_cell_widget.dart';
|
||||
import 'package:starwork_flutter/common/widgets/custome_app_bar_wdiget.dart';
|
||||
import 'package:starwork_flutter/extension/function_extension.dart';
|
||||
import 'package:starwork_flutter/routes/app_routes.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceSetting/device_setting_controller.dart';
|
||||
|
||||
class DeviceSettingView extends GetView<DeviceSettingController> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 即使不使用,只是引用一下 controller 就能触发初始化
|
||||
final _ = controller; // 添加这一行
|
||||
|
||||
return Scaffold(
|
||||
appBar: CustomAppBarWidget(
|
||||
title: '设置'.tr,
|
||||
),
|
||||
backgroundColor: AppColors.scaffoldBackgroundColor,
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
vertical: 10.h,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.toNamed(AppRoutes.deviceBasisInfo, arguments: {
|
||||
AppViewParameterKeys.lockInfo: controller.lockInfo?.toJson(),
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
vertical: 10.h,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Image(
|
||||
image: const AssetImage(AppImages.iconLockTypeDoorLock),
|
||||
width: 38.w,
|
||||
height: 38.w,
|
||||
fit: BoxFit.contain,
|
||||
gaplessPlayback: true,
|
||||
// 防止闪烁
|
||||
filterQuality: FilterQuality.medium,
|
||||
// 优化过滤质量
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Icon(
|
||||
Icons.image_not_supported,
|
||||
size: 26.sp,
|
||||
color: Colors.grey,
|
||||
);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
width: 10.w,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Obx(
|
||||
() => Text(
|
||||
controller.lockName.value,
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 4.h,
|
||||
),
|
||||
Text(
|
||||
'设备名称、序列号、版本等',
|
||||
style: TextStyle(fontSize: 12.sp, fontWeight: FontWeight.w400, color: Colors.grey),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
size: 16.sp,
|
||||
color: Colors.grey,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
),
|
||||
Obx(
|
||||
() => CustomCellListWidget(
|
||||
children: [
|
||||
CustomCellWidget(
|
||||
leftText: '远程开锁'.tr,
|
||||
onTap: () {},
|
||||
visible: controller.lockFeatureMap['remoteUnlock'] == 1,
|
||||
rightWidget: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CupertinoSwitch(
|
||||
value: controller.lockSettingMap['remoteUnlock'] == 1,
|
||||
onChanged: (bool value) {
|
||||
controller.enableRemoteUnlock(value);
|
||||
},
|
||||
activeColor: Colors.blue, // 可选:打开时的颜色(iOS 默认为系统蓝色,可自定义)
|
||||
trackColor: Colors.grey, // 可选:关闭时的背景轨道颜色
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
CustomCellWidget(
|
||||
leftText: '网络配置'.tr,
|
||||
onTap: () {
|
||||
Get.toNamed(AppRoutes.deviceSearchNetwork, arguments: {
|
||||
AppViewParameterKeys.lockInfo: controller.lockInfo?.toJson(),
|
||||
});
|
||||
},
|
||||
visible: controller.lockFeatureMap['wifi'] == 1,
|
||||
rightWidget: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_rounded,
|
||||
size: 16.sp,
|
||||
color: Colors.grey,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {}.debounce(),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.red,
|
||||
padding: EdgeInsets.symmetric(vertical: 12.h),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.r)),
|
||||
),
|
||||
child: Text(
|
||||
'删除设备'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user