feat: 完善设备管理页面、添加设备、删除设备
This commit is contained in:
parent
496ac22528
commit
80d8a7b104
@ -1,13 +1,15 @@
|
||||
class BindTeamStarCloudAccountRequest {
|
||||
String teamId;
|
||||
int teamId;
|
||||
String teamNo;
|
||||
String username;
|
||||
int cloudUid;
|
||||
String password;
|
||||
|
||||
BindTeamStarCloudAccountRequest({
|
||||
required this.teamId,
|
||||
required this.teamNo,
|
||||
required this.username,
|
||||
required this.cloudUid,
|
||||
required this.password,
|
||||
});
|
||||
|
||||
@ -16,21 +18,25 @@ class BindTeamStarCloudAccountRequest {
|
||||
data['teamId'] = teamId;
|
||||
data['teamNo'] = teamNo;
|
||||
data['username'] = username;
|
||||
data['cloudUid'] = cloudUid;
|
||||
data['password'] = password;
|
||||
return data;
|
||||
}
|
||||
|
||||
factory BindTeamStarCloudAccountRequest.fromJson(Map<String, dynamic> json) {
|
||||
return BindTeamStarCloudAccountRequest(
|
||||
teamId: json['teamId'] as String,
|
||||
teamId: json['teamId'] as int,
|
||||
teamNo: json['teamNo'] as String,
|
||||
username: json['username'] as String,
|
||||
cloudUid: json['cloudUid'] as int,
|
||||
password: json['password'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BindTeamStarCloudAccountRequest{teamId: $teamId, teamNo: $teamNo, username: $username, password: $password}';
|
||||
return 'BindTeamStarCloudAccountRequest{teamId: $teamId,cloudUid:$cloudUid, teamNo: $teamNo, username: $username,'
|
||||
' password:'
|
||||
' $password}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,19 +1,23 @@
|
||||
class CreateTeamResponse {
|
||||
final String? teamNo;
|
||||
final int? teamId;
|
||||
|
||||
CreateTeamResponse({
|
||||
this.teamNo,
|
||||
this.teamId,
|
||||
});
|
||||
|
||||
factory CreateTeamResponse.fromJson(Map<String, dynamic> json) {
|
||||
return CreateTeamResponse(
|
||||
teamNo: json['teamNo'] as String?,
|
||||
teamId: json['teamId'] as int?,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'teamNo': teamNo,
|
||||
'teamId': teamId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ class TeamInfoResponse {
|
||||
String? sceneCustomName; // 其他场景名称
|
||||
String? personNo; // 人员编号
|
||||
bool? isOwner; // 是否我的团队
|
||||
TeamCloudInfo? cloudInfo;
|
||||
TeamCloudInfo? teamCloudInfo;
|
||||
|
||||
TeamInfoResponse({
|
||||
this.id,
|
||||
@ -20,7 +20,7 @@ class TeamInfoResponse {
|
||||
this.sceneCustomName,
|
||||
this.personNo,
|
||||
this.isOwner,
|
||||
this.cloudInfo,
|
||||
this.teamCloudInfo,
|
||||
});
|
||||
|
||||
// 从JSON构造函数
|
||||
@ -35,7 +35,7 @@ class TeamInfoResponse {
|
||||
sceneCustomName: json['sceneCustomName'] as String?,
|
||||
personNo: json['personNo'] as String?,
|
||||
isOwner: json['isOwner'] as bool?,
|
||||
cloudInfo: json['cloudInfo'] != null ? TeamCloudInfo.fromJson(json['cloudInfo']) : null,
|
||||
teamCloudInfo: json['teamCloudInfo'] != null ? TeamCloudInfo.fromJson(json['teamCloudInfo']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ class TeamInfoResponse {
|
||||
'sceneCustomName': sceneCustomName,
|
||||
'personNo': personNo,
|
||||
'isOwner': isOwner,
|
||||
'cloudInfo': cloudInfo?.toJson(),
|
||||
'teamCloudInfo': teamCloudInfo?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ class TeamInfoResponse {
|
||||
'scene: $scene, sceneCustomName: $sceneCustomName,'
|
||||
' sceneName: $sceneName, '
|
||||
' personNo: $personNo, '
|
||||
' cloudInfo: $cloudInfo,'
|
||||
' teamCloudInfo: $teamCloudInfo,'
|
||||
' isOwner: $isOwner}';
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,21 +59,21 @@ class TeamApiService {
|
||||
// 通过实例调用
|
||||
path: ApiPath.changeTeam,
|
||||
method: HttpConstant.post,
|
||||
data: request,
|
||||
data: request.toJson(),
|
||||
fromJson: (data) {},
|
||||
);
|
||||
}
|
||||
|
||||
// 团队绑定星云账号
|
||||
Future<ApiResponse<SceneInfoResponseList>> requestBindTeamStarCloudAccount({
|
||||
Future<ApiResponse<void>> requestBindTeamStarCloudAccount({
|
||||
required BindTeamStarCloudAccountRequest request,
|
||||
}) {
|
||||
return _api.makeRequest(
|
||||
// 通过实例调用
|
||||
path: ApiPath.bindTeamStarCloudAccount,
|
||||
method: HttpConstant.post,
|
||||
data: request,
|
||||
fromJson: (data) => SceneInfoResponseList.fromJson(data),
|
||||
data: request.toJson(),
|
||||
fromJson: (data){},
|
||||
);
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ class TeamApiService {
|
||||
// 通过实例调用
|
||||
path: ApiPath.updateTeamInfo,
|
||||
method: HttpConstant.post,
|
||||
data: request,
|
||||
data: request.toJson(),
|
||||
fromJson: (data) {},
|
||||
);
|
||||
}
|
||||
|
||||
34
lib/app.dart
34
lib/app.dart
@ -29,21 +29,27 @@ class _AppState extends State<App> {
|
||||
builder: (_, child) {
|
||||
return GetMaterialApp(
|
||||
theme: ThemeData(
|
||||
scaffoldBackgroundColor: Colors.white,
|
||||
brightness: Brightness.light,
|
||||
textSelectionTheme: TextSelectionThemeData(
|
||||
cursorColor: Colors.blue.shade200,
|
||||
selectionColor: Colors.blue.shade100,
|
||||
selectionHandleColor: Colors.blue.shade300,
|
||||
scaffoldBackgroundColor: Colors.white,
|
||||
brightness: Brightness.light,
|
||||
textSelectionTheme: TextSelectionThemeData(
|
||||
cursorColor: Colors.blue.shade200,
|
||||
selectionColor: Colors.blue.shade100,
|
||||
selectionHandleColor: Colors.blue.shade300,
|
||||
),
|
||||
dialogBackgroundColor: Colors.white,
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
scrolledUnderElevation: 0,
|
||||
titleTextStyle: TextStyle(
|
||||
color: Colors.black87,
|
||||
fontSize: 18.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
dialogBackgroundColor: Colors.white,
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
scrolledUnderElevation: 0,
|
||||
)),
|
||||
),
|
||||
),
|
||||
// 必须配置以下三个本地化代理
|
||||
localizationsDelegates: const [
|
||||
GlobalMaterialLocalizations.delegate, // 提供Material组件本地化字符串
|
||||
|
||||
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_toast_messages.dart';
|
||||
import 'package:starwork_flutter/common/widgets/custom_dialog_widget.dart';
|
||||
|
||||
class BaseController extends GetxController {
|
||||
@ -14,7 +15,7 @@ class BaseController extends GetxController {
|
||||
}
|
||||
|
||||
void showLoading() {
|
||||
EasyLoading.show(status: 'loading...');
|
||||
EasyLoading.show(status: AppToastMessages.loading);
|
||||
}
|
||||
|
||||
void hideLoading() {
|
||||
@ -33,12 +34,8 @@ class BaseController extends GetxController {
|
||||
EasyLoading.showError(message.tr);
|
||||
}
|
||||
|
||||
void showCustomDialog({
|
||||
required String title,
|
||||
required Widget content,
|
||||
required VoidCallback onConfirm,
|
||||
String? confirmText
|
||||
}) {
|
||||
void showCustomDialog(
|
||||
{required String title, required Widget content, required VoidCallback onConfirm, String? confirmText}) {
|
||||
Get.dialog(
|
||||
CustomDialogWidget(
|
||||
title: title,
|
||||
|
||||
@ -8,10 +8,7 @@ class AppSupportDeviceType {
|
||||
|
||||
// 获取所有类型
|
||||
static List<AppSupportDeviceType> get allTypes => [
|
||||
all,
|
||||
lock,
|
||||
gateway,
|
||||
attendanceMachine,
|
||||
];
|
||||
|
||||
final String value;
|
||||
|
||||
4
lib/common/constant/app_view_parameter_keys.dart
Normal file
4
lib/common/constant/app_view_parameter_keys.dart
Normal file
@ -0,0 +1,4 @@
|
||||
class AppViewParameterKeys {
|
||||
static const String deviceList = "deviceList";
|
||||
|
||||
}
|
||||
3
lib/common/events/refresh_device_list_event.dart
Normal file
3
lib/common/events/refresh_device_list_event.dart
Normal file
@ -0,0 +1,3 @@
|
||||
class RefreshDeviceListEvent {
|
||||
RefreshDeviceListEvent();
|
||||
}
|
||||
49
lib/common/utils/event_bus_util.dart
Normal file
49
lib/common/utils/event_bus_util.dart
Normal file
@ -0,0 +1,49 @@
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
|
||||
// 创建 EventBus 实例(私有)
|
||||
EventBus _eventBus = EventBus();
|
||||
|
||||
/// 全局事件总线工具类(单例)
|
||||
class EventBusUtil {
|
||||
// 工厂构造函数,确保返回唯一实例
|
||||
factory EventBusUtil() => _instance;
|
||||
|
||||
// 私有构造函数
|
||||
EventBusUtil._internal();
|
||||
|
||||
// 静态实例
|
||||
static final EventBusUtil _instance = EventBusUtil._internal();
|
||||
|
||||
/// 获取 EventBus 实例
|
||||
EventBus get instance => _eventBus;
|
||||
|
||||
/// 监听指定类型的事件
|
||||
///
|
||||
/// 示例:
|
||||
/// ```dart
|
||||
/// EventBusUtil().on<UserLoginEvent>((event) {
|
||||
/// print('用户登录:${event.userId}');
|
||||
/// });
|
||||
/// ```
|
||||
Stream<T> on<T>() {
|
||||
return _eventBus.on<T>();
|
||||
}
|
||||
|
||||
/// 发送事件
|
||||
///
|
||||
/// 示例:
|
||||
/// ```dart
|
||||
/// EventBusUtil().fire(UserLoginEvent('123'));
|
||||
/// ```
|
||||
void fire<T>(T event) {
|
||||
_eventBus.fire(event);
|
||||
}
|
||||
|
||||
/// 销毁 EventBus(一般不用调用,除非应用退出)
|
||||
void destroy() {
|
||||
_eventBus.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/// 快捷访问方式(可选)
|
||||
EventBusUtil $eventBus = EventBusUtil();
|
||||
@ -4,6 +4,8 @@ import 'package:starwork_flutter/views/device/confirmPairDevice/confirm_pair_dev
|
||||
import 'package:starwork_flutter/views/device/confirmPairDevice/confirm_pair_device_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/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';
|
||||
import 'package:starwork_flutter/views/device/searchDevice/search_device_view.dart';
|
||||
import 'package:starwork_flutter/views/home/home_binding.dart';
|
||||
@ -130,5 +132,10 @@ class AppPages {
|
||||
page: () => DeviceManageView(),
|
||||
binding: DeviceManageBinding(),
|
||||
),
|
||||
GetPage(
|
||||
name: AppRoutes.deviceRemoveDevice,
|
||||
page: () => RemoveDeviceView(),
|
||||
binding: RemoveDeviceBinding(),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@ -18,4 +18,5 @@ class AppRoutes{
|
||||
static const String deviceManage = '/device/deviceManage';
|
||||
static const String searchDevice = '/device/searchDevice';
|
||||
static const String confirmPairDevice = '/device/confirmPairDevice';
|
||||
static const String deviceRemoveDevice = '/device/removeDevice';
|
||||
}
|
||||
@ -1,12 +1,116 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
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/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_support_device_type.dart';
|
||||
import 'package:starwork_flutter/common/events/refresh_device_list_event.dart';
|
||||
import 'package:starwork_flutter/common/utils/event_bus_util.dart';
|
||||
import 'package:starwork_flutter/views/main/main_controller.dart';
|
||||
|
||||
class DeviceManageController extends BaseController with GetSingleTickerProviderStateMixin {
|
||||
final mainController = Get.find<MainController>();
|
||||
|
||||
class DeviceManageController extends GetxController with GetSingleTickerProviderStateMixin {
|
||||
// 选中状态 0:全部状态 1:在线 2:离线
|
||||
final RxInt selectedStatusIndex = 0.obs;
|
||||
|
||||
// 选中设备类型
|
||||
final selectedDeviceType = AppSupportDeviceType.all.obs;
|
||||
final selectedDeviceType = AppSupportDeviceType.lock.obs;
|
||||
|
||||
// 设备列表管理
|
||||
final deviceList = <StarCloudLock>[].obs;
|
||||
|
||||
// 用于 UI 显示的过滤后列表
|
||||
final filteredDeviceList = <StarCloudLock>[].obs;
|
||||
|
||||
// 在线设备数量
|
||||
final onlineDeviceCount = 0.obs;
|
||||
|
||||
// 离线设备数量
|
||||
final offlineDeviceCount = 0.obs;
|
||||
|
||||
// 刷新设备列表事件留监听
|
||||
late StreamSubscription _refreshDeviceListSubscription;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
initData();
|
||||
|
||||
// 监听刷新设备列表事件
|
||||
_refreshDeviceListSubscription = EventBusUtil().instance.on<RefreshDeviceListEvent>().listen((event) async {
|
||||
_requestTeamDeviceList();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
_refreshDeviceListSubscription.cancel();
|
||||
}
|
||||
|
||||
void initData() async {
|
||||
_requestTeamDeviceList();
|
||||
}
|
||||
|
||||
/// 切换设备状态筛选
|
||||
void changeStatusFilter(int index) {
|
||||
selectedStatusIndex.value = index;
|
||||
_updateFilteredList();
|
||||
}
|
||||
|
||||
/// 根据当前 selectedStatusIndex 过滤设备列表
|
||||
void _updateFilteredList() {
|
||||
List<StarCloudLock> filtered = [];
|
||||
|
||||
switch (selectedStatusIndex.value) {
|
||||
case 0: // 全部
|
||||
filtered = deviceList;
|
||||
break;
|
||||
case 1: // 在线
|
||||
filtered = deviceList.where((device) => device.isOnline == true).toList();
|
||||
break;
|
||||
case 2: // 离线
|
||||
filtered = deviceList.where((device) => device.isOnline == false).toList();
|
||||
break;
|
||||
default:
|
||||
filtered = deviceList;
|
||||
}
|
||||
filteredDeviceList.assignAll(filtered); // 更新响应式列表
|
||||
}
|
||||
|
||||
void _requestTeamDeviceList() async {
|
||||
showLoading();
|
||||
await StarCloudSDK.instance.getDeviceList(
|
||||
pageNo: 1,
|
||||
pageSize: 999,
|
||||
cloudUid: mainController.selectedTeam.value.teamCloudInfo!.uid!,
|
||||
onSuccess: (StarCloudLockList list) {
|
||||
filteredDeviceList.clear();
|
||||
deviceList.clear();
|
||||
for (var groupItem in list.groupList) {
|
||||
for (var lock in groupItem.lockList) {
|
||||
deviceList.add(lock);
|
||||
if (lock.isOnline ?? false) {
|
||||
onlineDeviceCount.value++;
|
||||
} else {
|
||||
offlineDeviceCount.value++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ✅ 加载完原始数据后,更新过滤列表
|
||||
_updateFilteredList();
|
||||
hideLoading();
|
||||
},
|
||||
onError: (err) {
|
||||
AppLogger.error('获取设备列表失败:${err}');
|
||||
hideLoading();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,10 @@ 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_support_device_type.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_view_parameter_keys.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/deviceManage/device_manage_controller.dart';
|
||||
|
||||
class DeviceManageView extends GetView<DeviceManageController> {
|
||||
@ -35,7 +37,7 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
horizontal: 10.w,
|
||||
vertical: 10.h,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
@ -57,7 +59,9 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
Get.toNamed(AppRoutes.searchDevice);
|
||||
},
|
||||
child: Text(
|
||||
'添加设备',
|
||||
style: TextStyle(
|
||||
@ -68,7 +72,14 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
Get.toNamed(
|
||||
AppRoutes.deviceRemoveDevice,
|
||||
arguments: {
|
||||
AppViewParameterKeys.deviceList: controller.deviceList,
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'删除设备',
|
||||
style: TextStyle(
|
||||
@ -79,7 +90,9 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
onPressed: () {
|
||||
controller.showFunctionNotOpen();
|
||||
},
|
||||
child: Text(
|
||||
'更多管理',
|
||||
style: TextStyle(
|
||||
@ -139,7 +152,7 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
controller.selectedStatusIndex.value = 0;
|
||||
controller.changeStatusFilter(0);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.h),
|
||||
@ -162,7 +175,7 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
controller.selectedStatusIndex.value = 1;
|
||||
controller.changeStatusFilter(1);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.h),
|
||||
@ -171,7 +184,7 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
borderRadius: BorderRadius.circular(4.r),
|
||||
),
|
||||
child: Text(
|
||||
'在线(${1})'.tr,
|
||||
'在线(${controller.onlineDeviceCount.value})'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: controller.selectedStatusIndex == 1 ? Colors.white : Colors.grey[500],
|
||||
@ -185,7 +198,7 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
controller.selectedStatusIndex.value = 2;
|
||||
controller.changeStatusFilter(2);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 4.h),
|
||||
@ -194,7 +207,7 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
borderRadius: BorderRadius.circular(4.r),
|
||||
),
|
||||
child: Text(
|
||||
'离线(${1})'.tr,
|
||||
'离线(${controller.offlineDeviceCount.value})'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: controller.selectedStatusIndex == 2 ? Colors.white : Colors.grey[500],
|
||||
@ -246,7 +259,7 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'${deviceType.label}(${0})',
|
||||
'${deviceType.label}(${controller.deviceList.length})',
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
color: Colors.black,
|
||||
@ -262,78 +275,81 @@ class DeviceManageView extends GetView<DeviceManageController> {
|
||||
}
|
||||
|
||||
_buildRightDeviceList() {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 10.h),
|
||||
child: GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2, // 每行两列
|
||||
crossAxisSpacing: 6.w, // 列间距
|
||||
mainAxisSpacing: 6.h, // 行间距
|
||||
childAspectRatio: 1.6, // 宽高比,可根据需要调整
|
||||
),
|
||||
itemCount: 100,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Obx(
|
||||
() => Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (controller.selectedDeviceType.value.iconImagePath != null)
|
||||
Image(
|
||||
image: AssetImage(controller.selectedDeviceType.value.iconImagePath!),
|
||||
width: 26.w,
|
||||
height: 26.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,
|
||||
);
|
||||
},
|
||||
),
|
||||
return Obx(
|
||||
() => Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 10.h),
|
||||
child: GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2, // 每行两列
|
||||
crossAxisSpacing: 6.w, // 列间距
|
||||
mainAxisSpacing: 6.h, // 行间距
|
||||
childAspectRatio: 1.6, // 宽高比,可根据需要调整
|
||||
),
|
||||
itemCount: controller.filteredDeviceList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final lock = controller.filteredDeviceList[index];
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.r)),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Obx(
|
||||
() => Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (controller.selectedDeviceType.value.iconImagePath != null)
|
||||
Image(
|
||||
image: AssetImage(controller.selectedDeviceType.value.iconImagePath!),
|
||||
width: 26.w,
|
||||
height: 26.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(
|
||||
height: 6.h,
|
||||
),
|
||||
Text(
|
||||
'TMH_5sdds5465a4sd5665$index',
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
fontWeight: FontWeight.w400,
|
||||
Text(
|
||||
lock.lockName,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
SizedBox(
|
||||
height: 4.h,
|
||||
),
|
||||
Text(
|
||||
'在线',
|
||||
style: TextStyle(
|
||||
color: Colors.green,
|
||||
fontSize: 10.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
SizedBox(
|
||||
height: 4.h,
|
||||
),
|
||||
)
|
||||
],
|
||||
Text(
|
||||
lock.isOnline ?? false ? '在线' : '离线',
|
||||
style: TextStyle(
|
||||
color: lock.isOnline ?? false ? Colors.green : Colors.grey,
|
||||
fontSize: 10.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
10
lib/views/device/removeDevice/remove_device_binding.dart
Normal file
10
lib/views/device/removeDevice/remove_device_binding.dart
Normal file
@ -0,0 +1,10 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/views/device/deviceManage/device_manage_controller.dart';
|
||||
import 'package:starwork_flutter/views/device/removeDevice/remove_device_controller.dart';
|
||||
|
||||
class RemoveDeviceBinding implements Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut(() => RemoveDeviceController());
|
||||
}
|
||||
}
|
||||
104
lib/views/device/removeDevice/remove_device_controller.dart
Normal file
104
lib/views/device/removeDevice/remove_device_controller.dart
Normal file
@ -0,0 +1,104 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starcloud/entity/star_cloud_lock_list.dart';
|
||||
import 'package:starcloud/sdk/sdk_lock_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/events/refresh_device_list_event.dart';
|
||||
import 'package:starwork_flutter/common/utils/event_bus_util.dart';
|
||||
import 'package:starwork_flutter/views/main/main_controller.dart';
|
||||
|
||||
class RemoveDeviceController extends BaseController {
|
||||
// 选中的设备
|
||||
RxList<StarCloudLock> selectedDevices = <StarCloudLock>[].obs;
|
||||
RxList<StarCloudLock> deviceList = <StarCloudLock>[].obs;
|
||||
final mainController = Get.find<MainController>();
|
||||
final currentProgress = ''.obs; // 显示进度文本,如 "正在重置设备 1/3"
|
||||
@override
|
||||
void onInit() {
|
||||
deviceList.value = (Get.arguments?[AppViewParameterKeys.deviceList] as List<StarCloudLock>?) ?? [];
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
// 判断某个设备是否被选中
|
||||
bool isSelected(StarCloudLock device) {
|
||||
AppLogger.highlight('${selectedDevices.contains(device)}');
|
||||
return selectedDevices.contains(device);
|
||||
}
|
||||
|
||||
// 切换选中状态
|
||||
void toggleDevice(StarCloudLock device) {
|
||||
if (isSelected(device)) {
|
||||
selectedDevices.remove(device);
|
||||
} else {
|
||||
selectedDevices.add(device);
|
||||
}
|
||||
}
|
||||
|
||||
// 全选
|
||||
void selectAll(List<StarCloudLock> allDevices) {
|
||||
selectedDevices.assignAll(allDevices);
|
||||
}
|
||||
|
||||
// 清空选择
|
||||
void clearSelection() {
|
||||
selectedDevices.clear();
|
||||
}
|
||||
|
||||
// 是否全选
|
||||
bool isAllSelected(List<StarCloudLock> allDevices) {
|
||||
return allDevices.isNotEmpty && selectedDevices.length == allDevices.length;
|
||||
}
|
||||
|
||||
// 删除设备
|
||||
void removeDevice(RxList<StarCloudLock> selectedDevices) async {
|
||||
showLoading();
|
||||
var teamInfo = mainController.selectedTeam.value;
|
||||
var teamCloudInfo = teamInfo.teamCloudInfo;
|
||||
|
||||
if (teamCloudInfo == null) {
|
||||
showToast('没找到对应的星云账户信息');
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
if (selectedDevices.isEmpty) {
|
||||
showToast('没有选择要重置的设备');
|
||||
hideLoading();
|
||||
return;
|
||||
}
|
||||
|
||||
bool allSuccess = true; // 标记是否全部成功
|
||||
|
||||
for (int i = 0; i < selectedDevices.length; i++) {
|
||||
final device = selectedDevices[i];
|
||||
|
||||
try {
|
||||
await StarCloudSDK.instance.resetLock(
|
||||
lockId: device.lockId,
|
||||
cloudUid: teamCloudInfo.uid,
|
||||
onSuccess: () {
|
||||
// 可以在这里做点成功反馈(如打印日志)
|
||||
},
|
||||
onError: (err) {
|
||||
allSuccess = false; // 标记为非全成功
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
allSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
// === 所有设备处理完成后判断 ===
|
||||
if (allSuccess) {
|
||||
Future.delayed(1.seconds, () {
|
||||
EventBusUtil().instance.fire(RefreshDeviceListEvent());
|
||||
Get.back();
|
||||
});
|
||||
} else {
|
||||
Future.delayed(2.seconds, () {});
|
||||
}
|
||||
hideLoading();
|
||||
}
|
||||
}
|
||||
159
lib/views/device/removeDevice/remove_device_view.dart
Normal file
159
lib/views/device/removeDevice/remove_device_view.dart
Normal file
@ -0,0 +1,159 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starcloud/entity/star_cloud_lock_list.dart';
|
||||
import 'package:starwork_flutter/base/app_logger.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/custome_app_bar_wdiget.dart';
|
||||
import 'package:starwork_flutter/extension/function_extension.dart';
|
||||
import 'package:starwork_flutter/views/device/removeDevice/remove_device_controller.dart';
|
||||
|
||||
class RemoveDeviceView extends GetView<RemoveDeviceController> {
|
||||
const RemoveDeviceView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.scaffoldBackgroundColor,
|
||||
appBar: CustomAppBarWidget(
|
||||
title: '选择设备'.tr,
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
var allSelected = controller.isAllSelected(controller.deviceList);
|
||||
if (allSelected) {
|
||||
controller.clearSelection();
|
||||
} else {
|
||||
controller.selectAll(controller.deviceList);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
'全选'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
vertical: 10.h,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
_buildDeviceList(),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
if (controller.selectedDevices.isEmpty) {
|
||||
controller.showToast('请至少选中一个设备');
|
||||
}
|
||||
controller.removeDevice(controller.selectedDevices);
|
||||
}.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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_buildDeviceList() {
|
||||
return Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: controller.deviceList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final device = controller.deviceList[index];
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
controller.toggleDevice(device);
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 10.h),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10.w,
|
||||
vertical: 4.h,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Obx(
|
||||
() => Checkbox(
|
||||
value: controller.isSelected(device), // 动态判断是否选中
|
||||
shape: CircleBorder(
|
||||
side: BorderSide(width: 0.4.w),
|
||||
),
|
||||
activeColor: Colors.blue,
|
||||
onChanged: (value) {
|
||||
controller.toggleDevice(device); // 切换状态
|
||||
},
|
||||
),
|
||||
),
|
||||
Image(
|
||||
image: const AssetImage(AppImages.iconLockTypeDoorLock),
|
||||
width: 26.w,
|
||||
height: 26.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: 8.w,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
device.lockName,
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black87,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,8 @@ import 'package:starwork_flutter/base/app_permission.dart';
|
||||
import 'package:starwork_flutter/base/base_controller.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_toast_messages.dart';
|
||||
import 'package:starwork_flutter/common/constant/cache_keys.dart';
|
||||
import 'package:starwork_flutter/common/events/refresh_device_list_event.dart';
|
||||
import 'package:starwork_flutter/common/utils/event_bus_util.dart';
|
||||
import 'package:starwork_flutter/common/utils/shared_preferences_utils.dart';
|
||||
|
||||
class SearchDeviceController extends BaseController {
|
||||
@ -35,6 +37,7 @@ class SearchDeviceController extends BaseController {
|
||||
void onClose() {
|
||||
StarCloudSDK.instance.stopScan(onError: (err) {});
|
||||
isSearching.value = false;
|
||||
deviceList.clear();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@ -121,40 +124,17 @@ class SearchDeviceController extends BaseController {
|
||||
void connectingDevices(StarCloudScanResult device) async {
|
||||
showLoading();
|
||||
try {
|
||||
var cacheStarCloudUserName = await SharedPreferencesUtils.getString(CacheKeys.starCloudUserName);
|
||||
var cacheStarCloudPassword = await SharedPreferencesUtils.getString(CacheKeys.starCloudPassword);
|
||||
var cacheStarCloudUid = await SharedPreferencesUtils.getString(CacheKeys.starCloudUid);
|
||||
if (cacheStarCloudUserName == null || cacheStarCloudPassword == null || cacheStarCloudUid == null) {
|
||||
await StarCloudSDK.instance.createCloudUser(
|
||||
onError: (err) {
|
||||
AppLogger.error('err:${err}');
|
||||
hideLoading();
|
||||
},
|
||||
onSuccess: (userInfo) {
|
||||
SharedPreferencesUtils.setString(CacheKeys.starCloudUserName, userInfo.username);
|
||||
SharedPreferencesUtils.setString(CacheKeys.starCloudPassword, userInfo.password);
|
||||
SharedPreferencesUtils.setString(CacheKeys.starCloudUid, userInfo.uid.toString());
|
||||
},
|
||||
);
|
||||
}
|
||||
StarCloudSDK.instance.setCloudAccounts(
|
||||
[
|
||||
CloudUserInfo(
|
||||
username: cacheStarCloudUserName!,
|
||||
password: cacheStarCloudPassword!,
|
||||
uid: int.parse(cacheStarCloudUid!),
|
||||
)
|
||||
],
|
||||
);
|
||||
await StarCloudSDK.instance.pairDevice(
|
||||
onError: (err) {
|
||||
AppLogger.error('err:${err}');
|
||||
AppLogger.error('连接设备时出现错误:${err}');
|
||||
hideLoading();
|
||||
},
|
||||
onSuccess: (StarCloudLock lockInfo) {
|
||||
AppLogger.highlight('lockInfo:${lockInfo.toString()}');
|
||||
// 设备连接成功
|
||||
showSuccess(message: '设备添加成功'.tr);
|
||||
hideLoading();
|
||||
// 触发刷新设备列表
|
||||
EventBusUtil().instance.fire(RefreshDeviceListEvent());
|
||||
Get.back();
|
||||
},
|
||||
scanResult: device,
|
||||
|
||||
@ -2,11 +2,16 @@ import 'package:carousel_slider/carousel_controller.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:permission_handler/permission_handler.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/api/model/team/response/team_info_response.dart';
|
||||
import 'package:starwork_flutter/api/service/team_api_service.dart';
|
||||
import 'package:starwork_flutter/base/app_logger.dart';
|
||||
import 'package:starwork_flutter/base/app_permission.dart';
|
||||
import 'package:starwork_flutter/base/base_controller.dart';
|
||||
import 'package:starwork_flutter/common/events/refresh_device_list_event.dart';
|
||||
import 'package:starwork_flutter/common/utils/event_bus_util.dart';
|
||||
import 'package:starwork_flutter/routes/app_routes.dart';
|
||||
import 'package:starwork_flutter/views/main/main_controller.dart';
|
||||
|
||||
@ -15,7 +20,6 @@ class HomeController extends BaseController {
|
||||
|
||||
final isOpenNotificationPermission = false.obs;
|
||||
|
||||
|
||||
var carouselCurrentIndex = 0.obs;
|
||||
|
||||
// 渐变颜色列表
|
||||
@ -42,18 +46,14 @@ class HomeController extends BaseController {
|
||||
|
||||
// 初始化数据
|
||||
void _initializeData() async {
|
||||
showLoading();
|
||||
|
||||
|
||||
// 检查通知权限
|
||||
isOpenNotificationPermission.value = await AppPermission.checkPermission(
|
||||
permission: Permission.notification,
|
||||
);
|
||||
hideLoading();
|
||||
// 触发刷新设备列表
|
||||
EventBusUtil().instance.fire(RefreshDeviceListEvent());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 根据轮播图索引更新渐变颜色
|
||||
void updateGradientColor(int index) {
|
||||
if (index < gradientColors.length) {
|
||||
@ -66,27 +66,8 @@ class HomeController extends BaseController {
|
||||
|
||||
// 首页刷新方法
|
||||
Future<void> refreshHome() async {
|
||||
// 显示加载状态(可选)
|
||||
// isLoading.value = true;
|
||||
|
||||
// 模拟网络请求延迟
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
|
||||
// 这里可以添加实际的刷新逻辑,比如:
|
||||
// 1. 重新获取轮播图数据
|
||||
// 2. 刷新统计数据
|
||||
// 3. 更新功能列表
|
||||
// 4. 刷新考勤图表数据
|
||||
// 5. 更新门禁列表
|
||||
|
||||
// 重新检查通知权限
|
||||
isOpenNotificationPermission.value = await AppPermission.checkPermission(
|
||||
permission: Permission.notification,
|
||||
);
|
||||
|
||||
// 隐藏加载状态
|
||||
// isLoading.value = false;
|
||||
|
||||
print('首页数据刷新完成');
|
||||
_initializeData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,12 +232,18 @@ class HomeView extends GetView<HomeController> {
|
||||
HomeCarouselAreaWidget(
|
||||
carouselCurrentIndex: controller.carouselCurrentIndex,
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
HomeNotDeviceArea(),
|
||||
Visibility(
|
||||
child: SizedBox(height: 10.h),
|
||||
visible: controller.mainController.deviceCountSize.value == 0,
|
||||
),
|
||||
Visibility(
|
||||
visible: controller.mainController.deviceCountSize.value == 0,
|
||||
child: HomeNotDeviceArea(),
|
||||
),
|
||||
HomeTeamNoticeRowWidget(),
|
||||
HomeStatisticsRowWidget(
|
||||
personCount: 0,
|
||||
deviceCount: 0,
|
||||
deviceCount: controller.mainController.deviceCountSize.value,
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
HomeFunctionListAreaWidget(),
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starwork_flutter/routes/app_routes.dart';
|
||||
|
||||
class HomeStatisticsRowWidget extends StatelessWidget {
|
||||
final int personCount;
|
||||
@ -47,80 +48,85 @@ class HomeStatisticsRowWidget extends StatelessWidget {
|
||||
}) {
|
||||
return Expanded(
|
||||
// 使用Expanded让卡片自适应宽度
|
||||
child: Container(
|
||||
height: 62.h,
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 10.h),
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 上半部分:数字 + 单位 + 管理按钮
|
||||
Row(
|
||||
children: [
|
||||
// 数字和单位
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||
// 使用baseline对齐
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
// 设置文本基线
|
||||
children: [
|
||||
Text(
|
||||
count.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 20.sp, // text-5
|
||||
fontWeight: FontWeight.bold,
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
unit,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp, // text-3
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
// 管理按钮
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.w, vertical: 4.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(4.r),
|
||||
),
|
||||
child: Text(
|
||||
buttonText,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp, // text-2.5
|
||||
fontWeight: FontWeight.w600,
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4.h), // mt-1
|
||||
// 下半部分:标签
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp, // text-2.5
|
||||
color: textColor,
|
||||
child: GestureDetector(
|
||||
onTap: (){
|
||||
Get.toNamed(AppRoutes.deviceManage);
|
||||
},
|
||||
child: Container(
|
||||
height: 62.h,
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 10.h),
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(8.r),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 上半部分:数字 + 单位 + 管理按钮
|
||||
Row(
|
||||
children: [
|
||||
// 数字和单位
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||
// 使用baseline对齐
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
// 设置文本基线
|
||||
children: [
|
||||
Text(
|
||||
count.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 20.sp, // text-5
|
||||
fontWeight: FontWeight.bold,
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
unit,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp, // text-3
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
// 管理按钮
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.w, vertical: 4.h),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(4.r),
|
||||
),
|
||||
child: Text(
|
||||
buttonText,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp, // text-2.5
|
||||
fontWeight: FontWeight.w600,
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4.h), // mt-1
|
||||
// 下半部分:标签
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 10.sp, // text-2.5
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -4,14 +4,19 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starcloud/entity/star_cloud_lock_list.dart';
|
||||
import 'package:starcloud/sdk/entity/cloud_user_info.dart';
|
||||
import 'package:starcloud/sdk/sdk_device_operate_extension.dart';
|
||||
import 'package:starcloud/sdk/starcloud.dart';
|
||||
import 'package:starwork_flutter/api/model/team/request/bind_team_star_cloud_account_request.dart';
|
||||
import 'package:starwork_flutter/api/model/team/request/change_current_team_request.dart';
|
||||
import 'package:starwork_flutter/api/model/team/response/team_info_response.dart';
|
||||
import 'package:starwork_flutter/api/service/team_api_service.dart';
|
||||
import 'package:starwork_flutter/base/app_logger.dart';
|
||||
import 'package:starwork_flutter/base/base_controller.dart';
|
||||
import 'package:starwork_flutter/common/constant/app_images.dart';
|
||||
import 'package:starwork_flutter/common/events/refresh_device_list_event.dart';
|
||||
import 'package:starwork_flutter/common/utils/event_bus_util.dart';
|
||||
import 'package:starwork_flutter/routes/app_routes.dart';
|
||||
import 'package:starwork_flutter/views/home/home_controller.dart';
|
||||
import 'package:starwork_flutter/views/home/home_view.dart';
|
||||
@ -39,11 +44,32 @@ class MainController extends BaseController {
|
||||
// 选中的团队
|
||||
var selectedTeam = TeamInfoResponse().obs;
|
||||
|
||||
// 设备数量
|
||||
final deviceCountSize = 0.obs;
|
||||
|
||||
// 团队数量
|
||||
final teamCountSize = 0.obs;
|
||||
|
||||
// 刷新设备列表事件留监听
|
||||
late StreamSubscription _refreshDeviceListSubscription;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
|
||||
/// 请求团队信息
|
||||
requestAllTeamInfoList();
|
||||
super.onInit();
|
||||
|
||||
// 监听刷新设备列表事件
|
||||
_refreshDeviceListSubscription = EventBusUtil().instance.on<RefreshDeviceListEvent>().listen((event) {
|
||||
_requestTeamDeviceList();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
_refreshDeviceListSubscription.cancel();
|
||||
}
|
||||
|
||||
// 更新索引
|
||||
@ -115,13 +141,27 @@ class MainController extends BaseController {
|
||||
if (myTeamList.isEmpty) {
|
||||
// 如果是空的则自动创建并跳转到团队使用场景页面
|
||||
Get.toNamed(AppRoutes.teamUseCaseSetting);
|
||||
return;
|
||||
}
|
||||
selectedTeam.value = myTeamList.first;
|
||||
|
||||
// 设置星云账户
|
||||
if (selectedTeam.value.teamCloudInfo != null) {
|
||||
StarCloudSDK.instance.setCloudAccounts([
|
||||
CloudUserInfo(
|
||||
username: selectedTeam.value.teamCloudInfo!.username!,
|
||||
password: selectedTeam.value.teamCloudInfo!.password!,
|
||||
uid: selectedTeam.value.teamCloudInfo!.uid!,
|
||||
)
|
||||
]);
|
||||
_requestTeamDeviceList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 切换当前团队
|
||||
void requestChangeCurrentTeam(TeamInfoResponse teamInfo) async {
|
||||
if (teamInfo.teamNo == selectedTeam.value.teamNo) return;
|
||||
var teamNo = teamInfo.teamNo;
|
||||
if (teamNo == null) {
|
||||
return;
|
||||
@ -132,19 +172,58 @@ class MainController extends BaseController {
|
||||
),
|
||||
);
|
||||
if (changeCurrentTeamResponse.isSuccess) {
|
||||
AppLogger.highlight('切换当前团队成功');
|
||||
selectedTeam.value = teamInfo;
|
||||
|
||||
// 如果teamInfo中的cloudInfo不为空,则设置云账号
|
||||
if (teamInfo.cloudInfo != null) {
|
||||
if (teamInfo.teamCloudInfo != null) {
|
||||
StarCloudSDK.instance.setCloudAccounts([
|
||||
CloudUserInfo(
|
||||
username: teamInfo.cloudInfo!.username!,
|
||||
password: teamInfo.cloudInfo!.password!,
|
||||
uid: teamInfo.cloudInfo!.uid!,
|
||||
username: teamInfo.teamCloudInfo!.username!,
|
||||
password: teamInfo.teamCloudInfo!.password!,
|
||||
uid: teamInfo.teamCloudInfo!.uid!,
|
||||
)
|
||||
]);
|
||||
_requestTeamDeviceList();
|
||||
} else {
|
||||
// 如果是空的就申请新的云账户进行绑定
|
||||
StarCloudSDK.instance.createCloudUser(
|
||||
onSuccess: (CloudUserInfo userInfo) async {
|
||||
var teamStarCloudAccountResponse = await teamApi.requestBindTeamStarCloudAccount(
|
||||
request: BindTeamStarCloudAccountRequest(
|
||||
teamNo: teamNo,
|
||||
username: userInfo.username,
|
||||
password: userInfo.password,
|
||||
teamId: teamInfo.id!,
|
||||
cloudUid: userInfo.uid,
|
||||
),
|
||||
);
|
||||
if (teamStarCloudAccountResponse.isSuccess) {
|
||||
StarCloudSDK.instance.setCloudAccounts([
|
||||
CloudUserInfo(
|
||||
username: userInfo.username,
|
||||
password: userInfo.password,
|
||||
uid: userInfo.uid,
|
||||
)
|
||||
]);
|
||||
_requestTeamDeviceList();
|
||||
}
|
||||
},
|
||||
onError: (err) {},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _requestTeamDeviceList() async {
|
||||
await StarCloudSDK.instance.getDeviceList(
|
||||
pageNo: 1,
|
||||
pageSize: 999,
|
||||
cloudUid: selectedTeam.value.teamCloudInfo!.uid!,
|
||||
onSuccess: (StarCloudLockList list) {
|
||||
deviceCountSize.value = list.total;
|
||||
},
|
||||
onError: (err) {
|
||||
AppLogger.error('获取设备列表失败:${err}');
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starcloud/sdk/entity/cloud_user_info.dart';
|
||||
import 'package:starcloud/sdk/starcloud.dart';
|
||||
import 'package:starwork_flutter/api/model/team/request/bind_team_star_cloud_account_request.dart';
|
||||
import 'package:starwork_flutter/api/model/team/request/create_team_request.dart';
|
||||
import 'package:starwork_flutter/api/model/team/response/scene_info_response.dart';
|
||||
import 'package:starwork_flutter/api/service/team_api_service.dart';
|
||||
import 'package:starwork_flutter/base/app_logger.dart';
|
||||
import 'package:starwork_flutter/base/base_controller.dart';
|
||||
|
||||
class CreateTeamController extends BaseController {
|
||||
@ -35,21 +39,46 @@ class CreateTeamController extends BaseController {
|
||||
}
|
||||
|
||||
void requestCreateTeam() async {
|
||||
showLoading();
|
||||
var createTeamResponse = await teamApi.requestCreateTeam(
|
||||
request: CreateTeamRequest(
|
||||
teamName: teamNameInputController.text,
|
||||
scene: selectedUseCase.value?.id ?? 0,
|
||||
),
|
||||
// 先注册星云用户
|
||||
await StarCloudSDK.instance.createCloudUser(
|
||||
onSuccess: (CloudUserInfo userInfo) async {
|
||||
// 创建团队
|
||||
var createTeamResponse = await teamApi.requestCreateTeam(
|
||||
request: CreateTeamRequest(
|
||||
teamName: teamNameInputController.text,
|
||||
scene: selectedUseCase.value?.id ?? 0,
|
||||
),
|
||||
);
|
||||
if (createTeamResponse.isSuccess) {
|
||||
var teamNo = createTeamResponse.data?.teamNo;
|
||||
var teamId = createTeamResponse.data?.teamId;
|
||||
var username = userInfo.username;
|
||||
var cloudUid = userInfo.uid;
|
||||
var password = userInfo.password;
|
||||
if (teamNo != null && teamId != null) {
|
||||
var bindTeamStarCloudAccountResponse = await teamApi.requestBindTeamStarCloudAccount(
|
||||
request: BindTeamStarCloudAccountRequest(
|
||||
teamId: teamId,
|
||||
teamNo: teamNo,
|
||||
username: username,
|
||||
cloudUid: cloudUid,
|
||||
password: password,
|
||||
),
|
||||
);
|
||||
AppLogger.highlight('bindTeamStarCloudAccountResponse:${bindTeamStarCloudAccountResponse.toString()}');
|
||||
if (bindTeamStarCloudAccountResponse.isSuccess) {
|
||||
// 创建成功,使用 Get.back(result: true) 返回并传递结果
|
||||
showSuccess();
|
||||
// 返回添加成功结果
|
||||
Get.back(result: {'created': true});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 创建失败
|
||||
showError(message: createTeamResponse.errorMsg!);
|
||||
}
|
||||
},
|
||||
onError: (err) {},
|
||||
);
|
||||
if (createTeamResponse.isSuccess) {
|
||||
// 创建成功,使用 Get.back(result: true) 返回并传递结果
|
||||
showSuccess();
|
||||
// 返回添加成功结果
|
||||
Get.back(result: {'created': true});
|
||||
} else {
|
||||
// 创建失败
|
||||
showError(message: createTeamResponse.errorMsg!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import 'package:flutter/widgets.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:starcloud/sdk/entity/cloud_user_info.dart';
|
||||
import 'package:starcloud/sdk/starcloud.dart';
|
||||
import 'package:starwork_flutter/api/model/team/request/bind_team_star_cloud_account_request.dart';
|
||||
import 'package:starwork_flutter/api/model/team/request/create_team_request.dart';
|
||||
import 'package:starwork_flutter/api/model/team/response/scene_info_response.dart';
|
||||
import 'package:starwork_flutter/api/service/team_api_service.dart';
|
||||
@ -39,46 +40,46 @@ class UseCaseSettingController extends BaseController {
|
||||
}
|
||||
|
||||
void requestCreateTeam() async {
|
||||
var cacheStarCloudUserName = await SharedPreferencesUtils.getString(CacheKeys.starCloudUserName);
|
||||
var cacheStarCloudPassword = await SharedPreferencesUtils.getString(CacheKeys.starCloudPassword);
|
||||
var cacheStarCloudUid = await SharedPreferencesUtils.getString(CacheKeys.starCloudUid);
|
||||
if (cacheStarCloudUserName == null || cacheStarCloudPassword == null || cacheStarCloudUid == null) {
|
||||
await StarCloudSDK.instance.createCloudUser(
|
||||
onError: (err) {
|
||||
AppLogger.error('err:${err}');
|
||||
hideLoading();
|
||||
},
|
||||
onSuccess: (userInfo) {
|
||||
SharedPreferencesUtils.setString(CacheKeys.starCloudUserName, userInfo.username);
|
||||
SharedPreferencesUtils.setString(CacheKeys.starCloudPassword, userInfo.password);
|
||||
SharedPreferencesUtils.setString(CacheKeys.starCloudUid, userInfo.uid.toString());
|
||||
},
|
||||
);
|
||||
}
|
||||
StarCloudSDK.instance.setCloudAccounts(
|
||||
[
|
||||
CloudUserInfo(
|
||||
username: cacheStarCloudUserName!,
|
||||
password: cacheStarCloudPassword!,
|
||||
uid: int.parse(cacheStarCloudUid!),
|
||||
)
|
||||
],
|
||||
// 先注册星云用户
|
||||
await StarCloudSDK.instance.createCloudUser(
|
||||
onSuccess: (CloudUserInfo userInfo) async {
|
||||
// 创建团队
|
||||
var createTeamResponse = await teamApi.requestCreateTeam(
|
||||
request: CreateTeamRequest(
|
||||
teamName: teamNameInputController.text,
|
||||
scene: selectedUseCase.value?.id ?? 0,
|
||||
),
|
||||
);
|
||||
if (createTeamResponse.isSuccess) {
|
||||
var teamNo = createTeamResponse.data?.teamNo;
|
||||
var teamId = createTeamResponse.data?.teamId;
|
||||
var username = userInfo.username;
|
||||
var cloudUid = userInfo.uid;
|
||||
var password = userInfo.password;
|
||||
if (teamNo != null && teamId != null) {
|
||||
var bindTeamStarCloudAccountResponse = await teamApi.requestBindTeamStarCloudAccount(
|
||||
request: BindTeamStarCloudAccountRequest(
|
||||
teamId: teamId,
|
||||
teamNo: teamNo,
|
||||
username: username,
|
||||
cloudUid: cloudUid,
|
||||
password: password,
|
||||
),
|
||||
);
|
||||
if (bindTeamStarCloudAccountResponse.isSuccess) {
|
||||
// 创建成功,使用 Get.back(result: true) 返回并传递结果
|
||||
showSuccess();
|
||||
// 返回添加成功结果
|
||||
Get.back(result: {'created': true});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 创建失败
|
||||
showError(message: createTeamResponse.errorMsg!);
|
||||
}
|
||||
},
|
||||
onError: (err) {},
|
||||
);
|
||||
|
||||
var createTeamResponse = await teamApi.requestCreateTeam(
|
||||
request: CreateTeamRequest(
|
||||
teamName: teamNameInputController.text,
|
||||
scene: selectedUseCase.value?.id ?? 0,
|
||||
),
|
||||
);
|
||||
if (createTeamResponse.isSuccess) {
|
||||
// 创建成功
|
||||
showSuccess();
|
||||
Get.back();
|
||||
} else {
|
||||
// 创建失败
|
||||
showError(message: createTeamResponse.errorMsg!);
|
||||
}
|
||||
}
|
||||
|
||||
/// 基于时间戳生成一个9位随机数
|
||||
|
||||
@ -121,6 +121,14 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
event_bus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: event_bus
|
||||
sha256: "1a55e97923769c286d295240048fc180e7b0768902c3c2e869fe059aafa15304"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@ -36,6 +36,8 @@ dependencies:
|
||||
carousel_slider: ^5.1.1
|
||||
# 气泡提示框
|
||||
super_tooltip: ^2.0.8
|
||||
# 事件总线
|
||||
event_bus: ^2.0.1
|
||||
# 星云sdk
|
||||
starcloud:
|
||||
path: ../starcloud-sdk-flutter
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user