1,门锁日志页面完善新增(未完成)
2,完善监视部分逻辑
This commit is contained in:
parent
c2fd318087
commit
5ef4f42b39
@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||||
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
|
||||||
|
import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_page.dart';
|
||||||
import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_state.dart';
|
import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_state.dart';
|
||||||
import 'package:star_lock/main/lockDetail/lockOperatingRecord/lockOperatingRecordGetLastRecordTime_entity.dart';
|
import 'package:star_lock/main/lockDetail/lockOperatingRecord/lockOperatingRecordGetLastRecordTime_entity.dart';
|
||||||
import 'package:star_lock/tools/toast.dart';
|
import 'package:star_lock/tools/toast.dart';
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
|
import 'package:cupertino_stepper/cupertino_stepper.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_advanced_calendar/flutter_advanced_calendar.dart';
|
import 'package:flutter_advanced_calendar/flutter_advanced_calendar.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:gzx_dropdown_menu/gzx_dropdown_menu.dart';
|
||||||
import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_logic.dart';
|
import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_logic.dart';
|
||||||
import 'package:star_lock/main/lockDetail/electronicKey/electronicKeyDetail/keyOperationRecordEntity.dart';
|
|
||||||
|
|
||||||
import '../../../app_settings/app_colors.dart';
|
import '../../../app_settings/app_colors.dart';
|
||||||
import '../../../tools/custom_bottom_sheet.dart';
|
|
||||||
import '../../../tools/noData.dart';
|
|
||||||
import '../../../tools/storage.dart';
|
import '../../../tools/storage.dart';
|
||||||
import '../../../tools/titleAppBar.dart';
|
import '../../../tools/titleAppBar.dart';
|
||||||
import '../../../tools/toast.dart';
|
import '../../../tools/toast.dart';
|
||||||
@ -24,8 +24,15 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> {
|
|||||||
final logic = Get.put(DoorLockLogLogic());
|
final logic = Get.put(DoorLockLogLogic());
|
||||||
final state = Get.find<DoorLockLogLogic>().state;
|
final state = Get.find<DoorLockLogLogic>().state;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: AppColors.mainBackgroundColor,
|
backgroundColor: AppColors.mainBackgroundColor,
|
||||||
appBar: TitleAppBar(
|
appBar: TitleAppBar(
|
||||||
@ -42,21 +49,6 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot);
|
var isDemoMode = await Storage.getBool(ifIsDemoModeOrNot);
|
||||||
if (isDemoMode == false) {
|
if (isDemoMode == false) {
|
||||||
// JhPopMenus.showLinePop(context, clickCallback: (index, selText) {
|
|
||||||
// print('选中index: $index');
|
|
||||||
// print('选中text: $selText');
|
|
||||||
// if (index == 0) {
|
|
||||||
// logic.mockNetworkDataRequest();
|
|
||||||
// } else if (index == 1) {
|
|
||||||
// logic.clearOperationRecordRequest();
|
|
||||||
// }
|
|
||||||
// }, listData: [
|
|
||||||
// {'text': '读取记录'},
|
|
||||||
// {'text': '清空记录'},
|
|
||||||
// {'text': '导出记录'},
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
_openModalBottomSheet();
|
|
||||||
} else {
|
} else {
|
||||||
// Get.toNamed(Routers.seletLockTypePage);
|
// Get.toNamed(Routers.seletLockTypePage);
|
||||||
Toast.show(msg: "演示模式");
|
Toast.show(msg: "演示模式");
|
||||||
@ -67,76 +59,268 @@ class _DoorLockLogPageState extends State<DoorLockLogPage> {
|
|||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
AdvancedCalendar(
|
Theme(
|
||||||
controller: state.calendarControllerCustom,
|
data: theme.copyWith(
|
||||||
events: state.events,
|
textTheme: theme.textTheme.copyWith(
|
||||||
weekLineHeight: 50.0.h,
|
titleMedium: theme.textTheme.titleMedium!.copyWith(
|
||||||
startWeekDay: 1,
|
fontSize: 16,
|
||||||
innerDot: true,
|
color: theme.colorScheme.secondary,
|
||||||
keepLineSize: true,
|
),
|
||||||
calendarTextStyle: TextStyle(
|
bodyLarge: theme.textTheme.bodyLarge!.copyWith(
|
||||||
fontSize: 22.sp,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
color: Colors.black54,
|
||||||
height: 1.3125,
|
),
|
||||||
letterSpacing: 0,
|
bodyMedium: theme.textTheme.bodyMedium!.copyWith(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black87,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
primaryColor: AppColors.mainColor,
|
||||||
|
highlightColor: Colors.yellow,
|
||||||
|
disabledColor: Colors.green,
|
||||||
),
|
),
|
||||||
headerStyle: TextStyle(
|
child: AdvancedCalendar(
|
||||||
fontSize: 22.sp,
|
controller: state.calendarControllerCustom,
|
||||||
fontWeight: FontWeight.w500,
|
events: state.events,
|
||||||
height: 1.3125,
|
weekLineHeight: 48.0,
|
||||||
letterSpacing: 0,
|
startWeekDay: 1,
|
||||||
|
innerDot: true,
|
||||||
|
keepLineSize: true,
|
||||||
|
calendarTextStyle: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
height: 1.3125,
|
||||||
|
letterSpacing: 0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Stack(
|
||||||
|
key: state.stackKey,
|
||||||
|
children: <Widget>[
|
||||||
|
Column(
|
||||||
|
children: <Widget>[
|
||||||
|
_buildHeaderView(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// 下拉菜单,注意GZXDropDownMenu目前只能在Stack内,后续有时间会改进,以及支持CustomScrollView和NestedScrollView
|
||||||
|
_buildDropDownMenu()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
OrientationBuilder(
|
||||||
|
builder: (BuildContext context, Orientation orientation) {
|
||||||
|
switch (orientation) {
|
||||||
|
case Orientation.portrait:
|
||||||
|
return _buildStepper(StepperType.vertical);
|
||||||
|
case Orientation.landscape:
|
||||||
|
return _buildStepper(StepperType.horizontal);
|
||||||
|
default:
|
||||||
|
throw UnimplementedError(orientation.toString());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String getTypeIcon(int type) {
|
//下拉头部控件GZXDropDownHeader
|
||||||
String title = 'images/controls_user.png';
|
Widget _buildHeaderView() {
|
||||||
switch (type) {
|
return GZXDropDownHeader(
|
||||||
case 1:
|
// 下拉的头部项,目前每一项,只能自定义显示的文字、图标、图标大小修改
|
||||||
// 蓝牙开锁
|
items: [
|
||||||
title = 'images/controls_user.png';
|
GZXDropDownHeaderItem(state.dropDownDoorLockItem[0], iconSize: 36),
|
||||||
break;
|
],
|
||||||
case 4:
|
// GZXDropDownHeader对应第一父级Stack的key
|
||||||
// 密码开锁
|
stackKey: state.stackKey,
|
||||||
title = 'images/icon_password.png';
|
// controller用于控制menu的显示或隐藏
|
||||||
break;
|
controller: state.dropdownMenuController,
|
||||||
case 7:
|
// 当点击头部项的事件,在这里可以进行页面跳转或openEndDrawer
|
||||||
// ic卡
|
onItemTap: (index) {},
|
||||||
title = 'images/icon_card.png';
|
// 头部的高度
|
||||||
break;
|
height: 46,
|
||||||
case 8:
|
// 头部背景颜色
|
||||||
// 指纹开锁
|
color: Colors.white,
|
||||||
title = 'images/icon_fingerprint.png';
|
// 文字样式
|
||||||
break;
|
style: TextStyle(
|
||||||
default:
|
color: AppColors.darkGrayTextColor, fontSize: ScreenUtil().setSp(24)),
|
||||||
break;
|
// 下拉时文字样式
|
||||||
}
|
dropDownStyle: TextStyle(
|
||||||
return title;
|
fontSize: ScreenUtil().setSp(24),
|
||||||
|
color: AppColors.darkGrayTextColor,
|
||||||
|
),
|
||||||
|
// 图标大小
|
||||||
|
iconSize: 20,
|
||||||
|
// 图标颜色
|
||||||
|
iconColor: AppColors.greyBackgroundColor,
|
||||||
|
// 下拉时图标颜色
|
||||||
|
iconDropDownColor: AppColors.mainColor,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _openModalBottomSheet() async {
|
//下拉菜单
|
||||||
showModalBottomSheet(
|
Widget _buildDropDownMenu() {
|
||||||
context: context,
|
return Obx(() => GZXDropDownMenu(
|
||||||
shape: RoundedRectangleBorder(
|
// controller用于控制menu的显示或隐藏
|
||||||
borderRadius: BorderRadiusDirectional.circular(10)),
|
controller: state.dropdownMenuController,
|
||||||
builder: (BuildContext context) {
|
// 下拉菜单显示或隐藏动画时长
|
||||||
return AlertBottomWidget(
|
animationMilliseconds: 300,
|
||||||
topTitle: '',
|
// 下拉后遮罩颜色
|
||||||
items: const ['读取记录', '清空记录', '导出记录'],
|
// maskColor: Theme.of(context).primaryColor.withOpacity(0.5),
|
||||||
chooseCallback: (value) {
|
// maskColor: Colors.red.withOpacity(0.5),
|
||||||
int getSelectIndex = value;
|
dropdownMenuChanging: (isShow, index) {},
|
||||||
if (getSelectIndex == 0) {
|
dropdownMenuChanged: (isShow, index) {},
|
||||||
logic.mockNetworkDataRequest();
|
// 下拉菜单,高度自定义,你想显示什么就显示什么,完全由你决定,你只需要在选择后调用_dropdownMenuController.hide();即可
|
||||||
} else if (getSelectIndex == 1) {
|
menus: [
|
||||||
logic.clearOperationRecordRequest();
|
GZXDropdownMenuBuilder(
|
||||||
}
|
dropDownHeight: 44.0.h * state.eventSortConditions.value.length,
|
||||||
},
|
dropDownWidget: _buildConditionListWidget(
|
||||||
);
|
state.eventSortConditions.value, (value) {
|
||||||
});
|
state.selectGroupSortCondition = value;
|
||||||
|
state.dropDownDoorLockItem[0] =
|
||||||
|
state.selectGroupSortCondition.name;
|
||||||
|
})),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildConditionListWidget(
|
||||||
|
items, void Function(SortCondition sortCondition) itemOnTap) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: ListView.separated(
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
shrinkWrap: true,
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
itemCount: items.length,
|
||||||
|
// item 的个数
|
||||||
|
separatorBuilder: (BuildContext context, int index) =>
|
||||||
|
const Divider(height: 1.0),
|
||||||
|
// 添加分割线
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return gestureDetector(items, index, itemOnTap, context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GestureDetector gestureDetector(
|
||||||
|
items,
|
||||||
|
int index,
|
||||||
|
void Function(SortCondition sortCondition) itemOnTap,
|
||||||
|
BuildContext context) {
|
||||||
|
SortCondition goodsSortCondition = items[index];
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
for (var value in items) {
|
||||||
|
value.isSelected = false;
|
||||||
|
}
|
||||||
|
goodsSortCondition.isSelected = true;
|
||||||
|
|
||||||
|
itemOnTap(goodsSortCondition);
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
height: 44.h,
|
||||||
|
child: Center(
|
||||||
|
child: Obx(() => Text(
|
||||||
|
goodsSortCondition.name,
|
||||||
|
style: TextStyle(
|
||||||
|
color: goodsSortCondition.isSelected
|
||||||
|
? AppColors.mainColor
|
||||||
|
: Colors.black,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
CupertinoStepper _buildStepper(StepperType type) {
|
||||||
|
final canCancel = state.currentStep.value > 0;
|
||||||
|
final canContinue = state.currentStep.value < 3;
|
||||||
|
return CupertinoStepper(
|
||||||
|
type: type,
|
||||||
|
currentStep: state.currentStep.value,
|
||||||
|
onStepTapped: (step) => setState(() => state.currentStep.value = step),
|
||||||
|
onStepCancel:
|
||||||
|
canCancel ? () => setState(() => --state.currentStep.value) : null,
|
||||||
|
onStepContinue:
|
||||||
|
canContinue ? () => setState(() => ++state.currentStep.value) : null,
|
||||||
|
steps: [
|
||||||
|
for (var i = 0; i < 3; ++i)
|
||||||
|
_buildStep(
|
||||||
|
title: const Text(''),
|
||||||
|
isActive: i == state.currentStep.value,
|
||||||
|
state: i == state.currentStep.value
|
||||||
|
? StepState.editing
|
||||||
|
: i < state.currentStep.value
|
||||||
|
? StepState.complete
|
||||||
|
: StepState.indexed,
|
||||||
|
),
|
||||||
|
// _buildStep(
|
||||||
|
// title: Text('Error'),
|
||||||
|
// state: StepState.error,
|
||||||
|
// ),
|
||||||
|
// _buildStep(
|
||||||
|
// title: Text('Disabled'),
|
||||||
|
// state: StepState.disabled,
|
||||||
|
// )
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Step _buildStep({
|
||||||
|
required Widget title,
|
||||||
|
StepState state = StepState.indexed,
|
||||||
|
bool isActive = false,
|
||||||
|
}) {
|
||||||
|
return Step(
|
||||||
|
title: title,
|
||||||
|
subtitle: const Text('10:45 有人出现在门口'),
|
||||||
|
state: state,
|
||||||
|
isActive: isActive,
|
||||||
|
content: LimitedBox(
|
||||||
|
maxWidth: 300,
|
||||||
|
maxHeight: 300,
|
||||||
|
child: Container(color: CupertinoColors.systemGrey),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getTypeIcon(int type) {
|
||||||
|
String title = 'images/controls_user.png';
|
||||||
|
switch (type) {
|
||||||
|
case 1:
|
||||||
|
// 蓝牙开锁
|
||||||
|
title = 'images/controls_user.png';
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
// 密码开锁
|
||||||
|
title = 'images/icon_password.png';
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
// ic卡
|
||||||
|
title = 'images/icon_card.png';
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
// 指纹开锁
|
||||||
|
title = 'images/icon_fingerprint.png';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SortCondition {
|
||||||
|
String name;
|
||||||
|
bool isSelected;
|
||||||
|
|
||||||
|
SortCondition({
|
||||||
|
required this.name,
|
||||||
|
required this.isSelected,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_advanced_calendar/flutter_advanced_calendar.dart';
|
import 'package:flutter_advanced_calendar/flutter_advanced_calendar.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:gzx_dropdown_menu/gzx_dropdown_menu.dart';
|
||||||
|
import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_page.dart';
|
||||||
|
|
||||||
import '../../lockMian/entity/lockListInfo_entity.dart';
|
import '../../lockMian/entity/lockListInfo_entity.dart';
|
||||||
import '../electronicKey/electronicKeyDetail/keyOperationRecordEntity.dart';
|
import '../electronicKey/electronicKeyDetail/keyOperationRecordEntity.dart';
|
||||||
@ -9,11 +12,25 @@ class DoorLockLogState {
|
|||||||
final lockOperatingRecordListData = <KeyRecordDataItem>[].obs;
|
final lockOperatingRecordListData = <KeyRecordDataItem>[].obs;
|
||||||
final calendarControllerToday = AdvancedCalendarController.today();
|
final calendarControllerToday = AdvancedCalendarController.today();
|
||||||
final calendarControllerCustom =
|
final calendarControllerCustom =
|
||||||
AdvancedCalendarController(DateTime(2024, 01, 09));
|
AdvancedCalendarController(DateTime(2024, 01, 10));
|
||||||
final events = <DateTime>[
|
final events = <DateTime>[
|
||||||
DateTime.now(),
|
DateTime.now(),
|
||||||
DateTime(2024, 10, 10),
|
DateTime(2024, 10, 10),
|
||||||
];
|
];
|
||||||
|
final eventSortConditions = [
|
||||||
|
SortCondition(name: '全部事件', isSelected: true),
|
||||||
|
SortCondition(name: '门锁异常', isSelected: false),
|
||||||
|
SortCondition(name: '有人出现', isSelected: false),
|
||||||
|
SortCondition(name: '有人按门铃', isSelected: false),
|
||||||
|
SortCondition(name: '一次性密码开门', isSelected: false)
|
||||||
|
].obs;
|
||||||
|
final List dropDownDoorLockItem = ['全部事件'];
|
||||||
|
final GZXDropdownMenuController dropdownMenuController =
|
||||||
|
GZXDropdownMenuController();
|
||||||
|
final scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
final GlobalKey stackKey = GlobalKey();
|
||||||
|
late SortCondition selectGroupSortCondition = eventSortConditions.value[0];
|
||||||
|
var currentStep = 0.obs;
|
||||||
|
|
||||||
DoorLockLogState() {
|
DoorLockLogState() {
|
||||||
keyInfos.value = Get.arguments["keyInfo"];
|
keyInfos.value = Get.arguments["keyInfo"];
|
||||||
|
|||||||
@ -27,6 +27,11 @@ class _RealTimePicturePageState extends State<RealTimePicturePage>
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
//写一个定时器,三十秒后页面自动返回
|
||||||
|
Timer(const Duration(seconds: 30), () {
|
||||||
|
Get.back();
|
||||||
|
});
|
||||||
|
|
||||||
state.animationController =
|
state.animationController =
|
||||||
AnimationController(duration: const Duration(seconds: 1), vsync: this);
|
AnimationController(duration: const Duration(seconds: 1), vsync: this);
|
||||||
state.animationController.repeat();
|
state.animationController.repeat();
|
||||||
@ -373,6 +378,7 @@ class _RealTimePicturePageState extends State<RealTimePicturePage>
|
|||||||
void _handleFailure() {
|
void _handleFailure() {
|
||||||
// 在这里处理失败的逻辑
|
// 在这里处理失败的逻辑
|
||||||
state.animationController.stop();
|
state.animationController.stop();
|
||||||
|
state.realTimePicTimer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -197,16 +197,16 @@ class CommandUDPReciverManager {
|
|||||||
// 对方结束监视
|
// 对方结束监视
|
||||||
print("对方结束监视");
|
print("对方结束监视");
|
||||||
} else {
|
} else {
|
||||||
//结束对讲反馈
|
//结束监视反馈
|
||||||
print("结束监视反馈");
|
print("结束监视反馈");
|
||||||
}
|
}
|
||||||
Toast.show(msg: "对方已结束监视");
|
// Toast.show(msg: "对方已结束监视");
|
||||||
UDPTalkClass().status = 0;
|
// UDPTalkClass().status = 0;
|
||||||
UDPTalkClass().isBeCall = false;
|
// UDPTalkClass().isBeCall = false;
|
||||||
UDPTalkClass().stopLocalAudio();
|
// UDPTalkClass().stopLocalAudio();
|
||||||
CallTalk().stopPcmSound();
|
// CallTalk().stopPcmSound();
|
||||||
eventBus.fire(GetUDPStatusRefreshUI(UDPTalkClass().status));
|
// eventBus.fire(GetUDPStatusRefreshUI(UDPTalkClass().status));
|
||||||
Get.back();
|
// Get.back();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -135,6 +135,9 @@ dependencies:
|
|||||||
#监听网络连接状态
|
#监听网络连接状态
|
||||||
connectivity_plus: ^5.0.2
|
connectivity_plus: ^5.0.2
|
||||||
flutter_advanced_calendar: ^1.4.1
|
flutter_advanced_calendar: ^1.4.1
|
||||||
|
#下拉选择菜单框
|
||||||
|
gzx_dropdown_menu: ^3.1.0
|
||||||
|
cupertino_stepper: ^0.2.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user