diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4039166 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.sourceDirectory": "D:/flutter/vbvs_app-1/linux" +} diff --git a/assets/images/active_bluetooth.png b/assets/images/active_bluetooth.png new file mode 100644 index 0000000..d2b37a7 Binary files /dev/null and b/assets/images/active_bluetooth.png differ diff --git a/assets/images/bar_control.svg b/assets/images/bar_control.svg new file mode 100644 index 0000000..a42c2d0 --- /dev/null +++ b/assets/images/bar_control.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/bar_heart.svg b/assets/images/bar_heart.svg new file mode 100644 index 0000000..1f2ea46 --- /dev/null +++ b/assets/images/bar_heart.svg @@ -0,0 +1,6 @@ + + + + diff --git a/assets/images/bar_home.svg b/assets/images/bar_home.svg new file mode 100644 index 0000000..0411b21 --- /dev/null +++ b/assets/images/bar_home.svg @@ -0,0 +1,13 @@ + + 资源 485 + + + + + + + diff --git a/assets/images/bar_mine.svg b/assets/images/bar_mine.svg new file mode 100644 index 0000000..3cc9e92 --- /dev/null +++ b/assets/images/bar_mine.svg @@ -0,0 +1,22 @@ + + 资源 486 + + + + + + + + + + diff --git a/assets/images/bed_control.png b/assets/images/bed_control.png new file mode 100644 index 0000000..7149ac7 Binary files /dev/null and b/assets/images/bed_control.png differ diff --git a/assets/images/bed_name.png b/assets/images/bed_name.png new file mode 100644 index 0000000..3a30c96 Binary files /dev/null and b/assets/images/bed_name.png differ diff --git a/assets/images/device_bed.png b/assets/images/device_bed.png new file mode 100644 index 0000000..7089767 Binary files /dev/null and b/assets/images/device_bed.png differ diff --git a/assets/images/edit.svg b/assets/images/edit.svg new file mode 100644 index 0000000..244e842 --- /dev/null +++ b/assets/images/edit.svg @@ -0,0 +1,11 @@ + + 资源 494 + + + + + + + diff --git a/assets/images/electric_bed.png b/assets/images/electric_bed.png new file mode 100644 index 0000000..670fe82 Binary files /dev/null and b/assets/images/electric_bed.png differ diff --git a/assets/images/new_background.png b/assets/images/new_background.png new file mode 100644 index 0000000..974ec90 Binary files /dev/null and b/assets/images/new_background.png differ diff --git a/assets/images/new_empty.png b/assets/images/new_empty.png new file mode 100644 index 0000000..47b9a23 Binary files /dev/null and b/assets/images/new_empty.png differ diff --git a/assets/images/people_avatar.png b/assets/images/people_avatar.png new file mode 100644 index 0000000..07122c8 Binary files /dev/null and b/assets/images/people_avatar.png differ diff --git a/assets/images/read_message.svg b/assets/images/read_message.svg new file mode 100644 index 0000000..5aa3c6b --- /dev/null +++ b/assets/images/read_message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/img/icon/bluetooth_edit.svg b/assets/img/icon/bluetooth_edit.svg new file mode 100644 index 0000000..36ed11f --- /dev/null +++ b/assets/img/icon/bluetooth_edit.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/assets/img/icon/expand.svg b/assets/img/icon/expand.svg new file mode 100644 index 0000000..a0eae77 --- /dev/null +++ b/assets/img/icon/expand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/img/icon/history_store.svg b/assets/img/icon/history_store.svg new file mode 100644 index 0000000..326df56 --- /dev/null +++ b/assets/img/icon/history_store.svg @@ -0,0 +1,10 @@ + + 资源 530 + + + + + + + + diff --git a/assets/img/icon/message.svg b/assets/img/icon/message.svg new file mode 100644 index 0000000..6956b9f --- /dev/null +++ b/assets/img/icon/message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/img/icon/people_info.svg b/assets/img/icon/people_info.svg new file mode 100644 index 0000000..860629a --- /dev/null +++ b/assets/img/icon/people_info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/img/icon/return_buttom.svg b/assets/img/icon/return_buttom.svg new file mode 100644 index 0000000..4788c77 --- /dev/null +++ b/assets/img/icon/return_buttom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/img/icon/xiaoe.svg b/assets/img/icon/xiaoe.svg new file mode 100644 index 0000000..f996a3d --- /dev/null +++ b/assets/img/icon/xiaoe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/lib/common/util/FitTool.dart b/lib/common/util/FitTool.dart index 212c2b0..3c83270 100644 --- a/lib/common/util/FitTool.dart +++ b/lib/common/util/FitTool.dart @@ -1,5 +1,3 @@ - - class FitTool { static double rpx = 0; static bool isInit = false; @@ -9,7 +7,8 @@ class FitTool { } if (isInit == false) { isInit = true; - rpx = v / 750.0; + // rpx = v / 750.0; + rpx=v/1624.0; } } diff --git a/lib/common/util/MyUtils.dart b/lib/common/util/MyUtils.dart index 76c1121..97620dc 100644 --- a/lib/common/util/MyUtils.dart +++ b/lib/common/util/MyUtils.dart @@ -2,10 +2,12 @@ import 'dart:async'; import 'package:ef/ef.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:intl/intl.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:vbvs_app/common/color/app_uri_status.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/controller/setting/language/language_controller.dart'; import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; import 'package:vbvs_app/language/AppLanguage.dart'; @@ -361,6 +363,37 @@ var returnIconButtom = IconButton( icon: Icon(Icons.navigate_before, size: 60.rpx), ); +var returnIconButtomNew = ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.transparent, + padding: EdgeInsets.only(right: 0), + onTap: () => Get.back(), + child: Container( + // height: 42.rpx, + // width: 42.rpx, + child: SvgPicture.asset( + 'assets/img/icon/return_buttom.svg', + width: 42.rpx, + height: 42.rpx, + ), + // SvgPicture.asset( + // 'assets/img/icon/expand.svg', + // color: Colors.white, + // ) + )); + +// IconButton( +// padding: EdgeInsets.zero, // 去除默认 padding +// constraints: BoxConstraints(), // 去除最小尺寸限制 +// onPressed: () => Get.back(), +// icon: SvgPicture.asset( +// 'assets/img/icon/return_buttom.svg', +// width: 42.rpx, +// height: 42.rpx, +// ), +// ); + +var returnIconButtomAddCallback = (returnCallBack) { var returnIconButtomAddCallback = ( VoidCallback? returnCallBack, { bool enableBack = true, diff --git a/lib/component/img/img_default_widget.dart b/lib/component/img/img_default_widget.dart new file mode 100644 index 0000000..e16d5a7 --- /dev/null +++ b/lib/component/img/img_default_widget.dart @@ -0,0 +1,77 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; + +import '../../controller/mh/apply_repair_controller.dart'; + + +class ImgPreviewDefaultWidget extends GetView { + ApplyRepairController applyRepairController; + + ImgPreviewDefaultWidget({required this.applyRepairController}) {} + + @override + Widget build(BuildContext context) { + return InkWell( + // onTap: applyRepairController.uploadImg, + onTap: ()async{}, + child: Container( + width: MediaQuery.sizeOf(context).width * 0.25, + height: MediaQuery.sizeOf(context).height * 0.15, + constraints: BoxConstraints( + minHeight: 152, + ), + decoration: BoxDecoration( + color: Colors.white, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.116, + constraints: BoxConstraints( + minHeight: 152, + ), + decoration: BoxDecoration( + color: Color(0xFFF3F5F6), + borderRadius: BorderRadius.circular(16), + ), + child: Align( + alignment: AlignmentDirectional(0, 0), + child: Container( + width: 35, + height: 35, + decoration: BoxDecoration( + image: DecorationImage( + fit: BoxFit.cover, + image: Image.asset( + 'assets/images/camera.png', + ).image, + ), + ), + ), + ), + ), + ), + Align( + alignment: AlignmentDirectional(0, 0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(0, 8, 0, 13), + child: Text( + ' ', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 11, + letterSpacing: 0, + ), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/component/img/img_preview_controller.dart b/lib/component/img/img_preview_controller.dart new file mode 100644 index 0000000..5652db0 --- /dev/null +++ b/lib/component/img/img_preview_controller.dart @@ -0,0 +1,23 @@ +import 'package:ef/ef.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'img_preview_controller.g.dart'; + +@JsonSerializable() +class ImgPreviewModel { + //版本id + String? url; //图片地址 + + + ImgPreviewModel(); + + static ImgPreviewModel fromJson(Map json) => + _$ImgPreviewModelFromJson(json); + Map toJson() => _$ImgPreviewModelToJson(this); +} + +class ImgPreviewController extends GetControllerEx { + ImgPreviewController() { + attr = GetModel(ImgPreviewModel()).obs; + } +} diff --git a/lib/component/img/img_preview_controller.g.dart b/lib/component/img/img_preview_controller.g.dart new file mode 100644 index 0000000..869e00e --- /dev/null +++ b/lib/component/img/img_preview_controller.g.dart @@ -0,0 +1,15 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'img_preview_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ImgPreviewModel _$ImgPreviewModelFromJson(Map json) => + ImgPreviewModel()..url = json['url'] as String?; + +Map _$ImgPreviewModelToJson(ImgPreviewModel instance) => + { + 'url': instance.url, + }; diff --git a/lib/component/img/img_preview_widget.dart b/lib/component/img/img_preview_widget.dart new file mode 100644 index 0000000..af5c52a --- /dev/null +++ b/lib/component/img/img_preview_widget.dart @@ -0,0 +1,80 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import '../../common/color/appFontsize.dart'; +import '../../controller/mh/apply_repair_controller.dart'; + +class ImgPreviewWidget extends GetView { + String imgUrl; + int index; + ApplyRepairController applyRepairController; + bool isDel; + + ImgPreviewWidget( + {required this.imgUrl, + required this.index, + required this.applyRepairController, + required this.isDel}) {} + + @override + Widget build(BuildContext context) { + return Container( + width: MediaQuery.sizeOf(context).width * 0.25, + height: MediaQuery.sizeOf(context).height * 0.15, + constraints: BoxConstraints( + minHeight: 140, + ), + decoration: BoxDecoration( + color: Colors.white, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.116, + decoration: BoxDecoration( + color: Color(0xFFF3F5F6), + borderRadius: BorderRadius.circular(8), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image.network( + 'https://picsum.photos/seed/73/600', + // applyRepairController.getPublicUrl(imgUrl), + + width: 300, + height: 200, + fit: BoxFit.cover, + ), + ), + ), + ), + Visibility( + visible: isDel, + child: Align( + alignment: AlignmentDirectional(0, 0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(0, 8, 0, 13), + child: InkWell( + onTap: () { + applyRepairController.model.issue_img!.removeAt(index); + applyRepairController.updateAll(); + }, + child: Text( + '删除', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: AppFontsize.small_text_size, + letterSpacing: 0, + ), + ), + )), + )), + ], + ), + ); + } +} diff --git a/lib/component/tool/CustomCard.dart b/lib/component/tool/CustomCard.dart index 69b649f..2da20f7 100644 --- a/lib/component/tool/CustomCard.dart +++ b/lib/component/tool/CustomCard.dart @@ -1,6 +1,102 @@ +// import 'package:flutter/material.dart'; +// import 'package:vbvs_app/common/util/FitTool.dart'; + +// class CustomCard extends StatefulWidget { +// final double borderRadius; // 圆角 +// final VoidCallback onTap; // 点击回调 +// final List colors; // 背景颜色列表 +// final Widget child; // 子组件 +// final bool enableAnimation; // 是否启用动画效果 +// final bool enableGradient; // 是否启用渐变 + +// const CustomCard({ +// Key? key, +// required this.borderRadius, +// required this.onTap, +// required this.colors, +// required this.child, +// this.enableAnimation = true, // 默认启用动画效果 +// this.enableGradient = true, // 默认启用渐变效果 +// }) : super(key: key); + +// @override +// State createState() => _CustomCardState(); +// } + +// class _CustomCardState extends State +// with SingleTickerProviderStateMixin { +// double _scale = 1.0; +// final Duration _animationDuration = const Duration(milliseconds: 50); + +// Future _handleTap() async { +// if (widget.enableAnimation) { +// setState(() { +// _scale = 0.95; +// }); + +// await Future.delayed(_animationDuration); + +// setState(() { +// _scale = 1.0; +// }); +// } + +// widget.onTap(); +// } + +// @override +// Widget build(BuildContext context) { +// final bool isGradient = widget.enableGradient && widget.colors.length > 1; +// final Color baseColor = widget.colors.first; + +// return Material( +// color: Colors.transparent, +// borderRadius: BorderRadius.circular(widget.borderRadius), +// child: InkWell( +// onTap: _handleTap, +// borderRadius: BorderRadius.circular(widget.borderRadius), +// splashColor: widget.colors.first.withOpacity(0.2), +// child: widget.enableAnimation +// ? AnimatedScale( +// scale: _scale, +// duration: _animationDuration, +// curve: Curves.easeInOut, +// child: _buildContent(isGradient, baseColor), +// ) +// : _buildContent(isGradient, baseColor), +// ), +// ); +// } + +// Widget _buildContent(bool isGradient, Color baseColor) { +// return Container( +// decoration: BoxDecoration( +// color: isGradient ? null : baseColor, +// gradient: isGradient +// ? LinearGradient( +// colors: widget.colors, +// begin: Alignment.topLeft, +// end: Alignment.bottomRight, +// ) +// : null, +// borderRadius: BorderRadius.circular(widget.borderRadius), +// ), +// child: Padding( +// padding: EdgeInsets.fromLTRB(0.rpx, 0.rpx, 0.rpx, 5.rpx), +// child: widget.child, +// ), +// ); +// } +// } import 'package:flutter/material.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; +/// 枚举控制渐变方向 +enum GradientDirection { + horizontal, + vertical, +} + class CustomCard extends StatefulWidget { final double borderRadius; // 圆角 final VoidCallback onTap; // 点击回调 @@ -8,6 +104,8 @@ class CustomCard extends StatefulWidget { final Widget child; // 子组件 final bool enableAnimation; // 是否启用动画效果 final bool enableGradient; // 是否启用渐变 + final GradientDirection gradientDirection; // 渐变方向 + final EdgeInsetsGeometry? margin; // 外部间距 const CustomCard({ Key? key, @@ -15,8 +113,10 @@ class CustomCard extends StatefulWidget { required this.onTap, required this.colors, required this.child, - this.enableAnimation = true, // 默认启用动画效果 - this.enableGradient = true, // 默认启用渐变效果 + this.enableAnimation = true, + this.enableGradient = true, + this.gradientDirection = GradientDirection.horizontal, + this.margin, }) : super(key: key); @override @@ -49,21 +149,24 @@ class _CustomCardState extends State final bool isGradient = widget.enableGradient && widget.colors.length > 1; final Color baseColor = widget.colors.first; - return Material( - color: Colors.transparent, - borderRadius: BorderRadius.circular(widget.borderRadius), - child: InkWell( - onTap: _handleTap, + return Container( + margin: widget.margin, // 应用外部间距 + child: Material( + color: Colors.transparent, borderRadius: BorderRadius.circular(widget.borderRadius), - splashColor: widget.colors.first.withOpacity(0.2), - child: widget.enableAnimation - ? AnimatedScale( - scale: _scale, - duration: _animationDuration, - curve: Curves.easeInOut, - child: _buildContent(isGradient, baseColor), - ) - : _buildContent(isGradient, baseColor), + child: InkWell( + onTap: _handleTap, + borderRadius: BorderRadius.circular(widget.borderRadius), + splashColor: widget.colors.first.withOpacity(0.2), + child: widget.enableAnimation + ? AnimatedScale( + scale: _scale, + duration: _animationDuration, + curve: Curves.easeInOut, + child: _buildContent(isGradient, baseColor), + ) + : _buildContent(isGradient, baseColor), + ), ), ); } @@ -75,14 +178,18 @@ class _CustomCardState extends State gradient: isGradient ? LinearGradient( colors: widget.colors, - begin: Alignment.topLeft, - end: Alignment.bottomRight, + begin: widget.gradientDirection == GradientDirection.vertical + ? Alignment.topCenter + : Alignment.centerLeft, + end: widget.gradientDirection == GradientDirection.vertical + ? Alignment.bottomCenter + : Alignment.centerRight, ) : null, borderRadius: BorderRadius.circular(widget.borderRadius), ), child: Padding( - padding: EdgeInsets.fromLTRB(0.rpx, 0.rpx, 0.rpx, 5.rpx), + padding: EdgeInsets.fromLTRB(0.rpx, 0.rpx, 0.rpx, 0.rpx), child: widget.child, ), ); diff --git a/lib/controller/main_bottom/main_page_b_controller.dart b/lib/controller/main_bottom/main_page_b_controller.dart new file mode 100644 index 0000000..ae22364 --- /dev/null +++ b/lib/controller/main_bottom/main_page_b_controller.dart @@ -0,0 +1,31 @@ +import 'package:ef/ef.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:vbvs_app/controller/main_bottom/main_page_controller.dart'; +part 'main_page_b_controller.g.dart'; + +@JsonSerializable() +class MainPageBModel { + int currentIndex = 0; + MainPageBModel(); + factory MainPageBModel.fromJson(Map json) { + try { + return _$MainPageBModelFromJson(json); + } catch (e) { + // 在实际应用中,应该有更细致的异常处理策略和错误日志 + return MainPageBModel(); // 或者返回一个带有错误信息的特定DeviceInfoModel实例 + } + } + + // 序列化为JSON时的异常处理 + Map toJson() => _$MainPageBModelToJson(this); +} + +class MainPageBController extends GetControllerEx { + MainPageBController() { + attr = GetModel(MainPageBModel()).obs; + } + + resetParm() { + model.currentIndex = 0; + } +} diff --git a/lib/controller/main_bottom/main_page_b_controller.g.dart b/lib/controller/main_bottom/main_page_b_controller.g.dart new file mode 100644 index 0000000..390ec91 --- /dev/null +++ b/lib/controller/main_bottom/main_page_b_controller.g.dart @@ -0,0 +1,15 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'main_page_b_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +MainPageBModel _$MainPageBModelFromJson(Map json) => + MainPageBModel()..currentIndex = (json['currentIndex'] as num).toInt(); + +Map _$MainPageBModelToJson(MainPageBModel instance) => + { + 'currentIndex': instance.currentIndex, + }; diff --git a/lib/controller/mh/address_controller.dart b/lib/controller/mh/address_controller.dart new file mode 100644 index 0000000..63b2f10 --- /dev/null +++ b/lib/controller/mh/address_controller.dart @@ -0,0 +1,155 @@ +import 'package:ef/ef.dart'; +import 'package:flutter_city_picker/model/address.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:vbvs_app/controller/mh/user_data.dart'; +import 'package:vbvs_app/controller/mh/muser_info_controller.dart'; + +part 'address_controller.g.dart'; + +@JsonSerializable() +class AddressModel { + //版本id + String? province; //省份 + String? city; //市 + String? county; //区 + String? street; //街道 + String? detail; //详细信息 + String? name; //名字 + String? phone; //手机号 + bool? ischecked = false; //是否默认 + + int currentType = 0; + String? all_address; + @JsonKey(ignore: true) + List? addressList = []; + + AddressModel(); + + static AddressModel fromJson(Map json) => + _$AddressModelFromJson(json); + Map toJson() => _$AddressModelToJson(this); +} + +class AddressController extends GetControllerEx { + AddressController() { + attr = GetModel(AddressModel()).obs; + } + + Future updateAddress( + Map address, AddressModel model) async { + if (model.addressList != null && model.addressList!.isNotEmpty) { + if (model.addressList!.length > 0) { + address["province"] = model.addressList![0].name; // 第一个元素为省 + } + if (model.addressList!.length > 1) { + address["city"] = model.addressList![1].name; // 第二个元素为市 + } + if (model.addressList!.length > 2) { + address["county"] = model.addressList![2].name; // 第三个元素为区 + } + if (model.addressList!.length > 3) { + address["street"] = model.addressList![3].name; // 第四个元素为街道 + } + } + address['detail'] = model.detail; + address['name'] = model.name; + address['phone'] = model.phone; + address['isChecked'] = model.ischecked; + + try { + final data = await ef.client.rpc("get_now_datetime"); + final response = await ef.client.from("app_user_address").update({ + 'province': address["province"], + 'city': address["city"], + 'county': address["county"], + 'street': address["street"], + 'detail': address["detail"], + 'name': address["name"], + 'phone': address["phone"], + 'ischecked': address['isChecked'] ? 1 : 0, + 'update_time': + DateFormat("yyyy-MM-dd HH:mm:ss").parse("$data").toString(), + }).eq("id", address['id']); + } catch (e) { + print('Error fetching repairs: $e'); + return e.toString(); + } + return ''; + } + + addAddress(AddressModel model) async { + try { + final MUserInfoController userInfoController = + Get.find(); + UserModel user = userInfoController.model.user!; + + // 设置省市区街道名称 + if (model.addressList != null && model.addressList!.isNotEmpty) { + if (model.addressList!.length > 0) + model.province = model.addressList![0].name; // 第一个元素为省 + if (model.addressList!.length > 1) + model.city = model.addressList![1].name; // 第二个元素为市 + if (model.addressList!.length > 2) + model.county = model.addressList![2].name; // 第三个元素为区 + if (model.addressList!.length > 3) + model.street = model.addressList![3].name; // 第四个元素为街道 + } + + // 查询数据库是否已有该用户的地址 + final existingAddresses = await ef.client + .from('app_user_address') + .select() + .eq('user_id', user.uid!); + + // 如果没有地址,将新增地址默认选中 + if (existingAddresses.isEmpty) { + model.ischecked = true; + } else if (model.ischecked == true) { + // 如果新地址被选中,将其他地址的 `ischecked` 字段设为 `0` + await ef.client + .from('app_user_address') + .update({'ischecked': 0}).eq('user_id', user.uid!); + } + + // 添加新地址 + final response = await ef.client.from('app_user_address').insert({ + 'province': model.province, + 'city': model.city, + 'county': model.county, + 'street': model.street, + 'detail': model.detail, + 'name': model.name, + 'phone': model.phone, + 'ischecked': model.ischecked! ? 1 : 0, + 'user_id': user.uid, + }); + } catch (e) { + print(e); + } + } + + Future> getData({int? level, int? pid}) async { + // 构建查询 + var query = ef.from("app_area_city").select(); + + // 如果 pid 不为 null,添加 pid 的条件 + if (pid != null) { + query = query.eq("pid", pid); + } + if (level != null) { + query = query.eq("deep", level); + } + List arr = await query; + + List addressNodes = arr.map((item) { + return AddressNode.fromJson({ + "name": item["ext_name"], // ext_name 对应 name + "code": item["id"], // id 对应 code + "letter": item["pinyin_prefix_upper"], // pinyin_prefix_upper 对应 letter + }); + }).toList(); + + return addressNodes; + } +} diff --git a/lib/controller/mh/address_controller.g.dart b/lib/controller/mh/address_controller.g.dart new file mode 100644 index 0000000..2e0927c --- /dev/null +++ b/lib/controller/mh/address_controller.g.dart @@ -0,0 +1,33 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'address_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +AddressModel _$AddressModelFromJson(Map json) => AddressModel() + ..province = json['province'] as String? + ..city = json['city'] as String? + ..county = json['county'] as String? + ..street = json['street'] as String? + ..detail = json['detail'] as String? + ..name = json['name'] as String? + ..phone = json['phone'] as String? + ..ischecked = json['ischecked'] as bool? + ..currentType = (json['currentType'] as num).toInt() + ..all_address = json['all_address'] as String?; + +Map _$AddressModelToJson(AddressModel instance) => + { + 'province': instance.province, + 'city': instance.city, + 'county': instance.county, + 'street': instance.street, + 'detail': instance.detail, + 'name': instance.name, + 'phone': instance.phone, + 'ischecked': instance.ischecked, + 'currentType': instance.currentType, + 'all_address': instance.all_address, + }; diff --git a/lib/controller/mh/address_list_controller.dart b/lib/controller/mh/address_list_controller.dart new file mode 100644 index 0000000..25b0456 --- /dev/null +++ b/lib/controller/mh/address_list_controller.dart @@ -0,0 +1,64 @@ +import 'package:ef/ef.dart'; +import 'package:json_annotation/json_annotation.dart'; + + +part 'address_list_controller.g.dart'; + +@JsonSerializable() +class AddressListModel { + List addressList = []; + Map address = {}; //之前控制的设备 + + int? type = 1; //1添加,2编辑 + + AddressListModel(); + + static AddressListModel fromJson(Map json) => + _$AddressListModelFromJson(json); + Map toJson() => _$AddressListModelToJson(this); +} + +class AddressListController extends GetControllerEx { + AddressListController() { + attr = GetModel(AddressListModel()).obs; + } + + // getAddressList() async { + // await ApiService.request.get("/api/address/info/list").then((d) { + // model.addressList = d.data["data"] ?? []; + // updateAll(); + // }).catchError((e) { + // print("$e"); + // }); + // } + + // //更新默认 + // Future updateDefault(address) async { + // var id = address['id']; + // var uid = address['userId']; + // try { + // await ef.client + // .from("app_user_address") + // .update({ + // 'ischecked': 0, + // }) + // .eq("user_id", address['userId']) + // .eq("ischecked", 1); + // await ef.client.from("app_user_address").update({ + // 'ischecked': 1, + // }).eq("id", address['id']); + // } catch (e) { + // print('Error fetching repairs: $e'); + // } + // } + + // // 删除地址 + // Future deleteAddress(String id) async { + // try { + // await ef.client.from("app_user_address").delete().eq("id", id); + // print("Address with ID $id has been successfully deleted."); + // } catch (e) { + // print("Error deleting address with ID $id: $e"); + // } + // } +} diff --git a/lib/controller/mh/address_list_controller.g.dart b/lib/controller/mh/address_list_controller.g.dart new file mode 100644 index 0000000..316d37c --- /dev/null +++ b/lib/controller/mh/address_list_controller.g.dart @@ -0,0 +1,20 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'address_list_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +AddressListModel _$AddressListModelFromJson(Map json) => + AddressListModel() + ..addressList = json['addressList'] as List + ..address = json['address'] as Map + ..type = (json['type'] as num?)?.toInt(); + +Map _$AddressListModelToJson(AddressListModel instance) => + { + 'addressList': instance.addressList, + 'address': instance.address, + 'type': instance.type, + }; diff --git a/lib/controller/mh/apply_repair_controller.dart b/lib/controller/mh/apply_repair_controller.dart new file mode 100644 index 0000000..f3e2acc --- /dev/null +++ b/lib/controller/mh/apply_repair_controller.dart @@ -0,0 +1,198 @@ +import 'dart:io'; + +import 'package:ef/ef.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:img_picker/img_picker.dart'; +import 'package:json_annotation/json_annotation.dart'; + +import 'package:path/path.dart' as p; +import 'package:uuid/uuid.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; + +import 'muser_info_controller.dart'; + +part 'apply_repair_controller.g.dart'; + +@JsonSerializable() +class ApplyRepairModel { + int? id; //报修id + String? apply_name; //申请人名称 + String? tel; //手机号 + String? address; //地址 + String? desc; //问题描述 + DateTime? create_time; //创建时间 + + String? device_type; //类型 床,床垫 不能为空 + String? device_category; //型号 不能为空 + String? device_id; //序列号 设备id 不能为空 + + String? device_name; //名称 可为空 + + List? issue_img = []; //图片 + int? imagesLImit = 3; //图片限制上传数量 + String? img_bucket = 'mianhuatang_repair'; + + String? status; //维修状态 + + String? select_device; + // String? select_type; + // List? device_list = ['床垫/BY-H/智能床垫', '床垫/BY-A/智能床垫', '床垫/BY-C/智能床垫']; + List? device_list = []; + int? score; + DateTime? score_time; //创建时间 + + int? messageType = 1; //消息类型 + int? repairId; //消息类型 + + ApplyRepairModel(); + static ApplyRepairModel fromJson(Map json) => + _$ApplyRepairModelFromJson(json); + Map toJson() => _$ApplyRepairModelToJson(this); +} + +class ApplyRepairController extends GetControllerEx { + // RepairRepository repairRepository = RepairRepository(); + ApplyRepairController() { + attr = GetModel(ApplyRepairModel()).obs; + } + + // //上传图片 + // Future uploadImg() async { + // final ImagePicker picker = ImagePicker(); + // final XFile? image = await picker.pickImage(source: ImageSource.gallery); + // final user = Supabase.instance.client.auth.currentUser; + // try { + // if (image != null) { + // int fileSize = await image.length(); // 获取图片大小,单位为字节 + // if (fileSize > 1024 * 1024 * 5) { + // // 1 MB = 1024 * 1024 bytes + // showToast("上传图片不能超过5MB"); + // return; + // } + // final filePath = image.path; // 获取文件路径 + // final fileExtension = p.extension(filePath); // 获取文件扩展名,包括点(.) + // // 获取当前日期并格式化为 yyyy-MM-dd + // final String folderName = + // DateFormat('yyyy-MM-dd').format(DateTime.now()); + // final file = File(image.path); + // // 构造文件路径,文件会被上传到 record_img 文件夹下的当天日期文件夹 + // var response = await ef.client.storage + // .from(model.img_bucket!) + // .upload('$folderName/${Uuid().v4()}$fileExtension', file); + // if (response != null) { + // String publicUrl = + // ef.client.storage.from(model.img_bucket!).getPublicUrl(response); + + // print('文件上传成功: $response'); + // print('文件上传成功: $publicUrl'); + // String prefixToRemove = 'mianhuatang_repair/'; + // model.issue_img!.add(response.startsWith(prefixToRemove) + // ? response.substring(prefixToRemove.length) + // : response); + // updateAll(); + // } + // print('/$model.img_bucket'); + // } else { + // print('未选择图片'); + // return; + // } + // } catch (e) { + // print('上传失败: $e'); + // } + // } + + // //提交 + // Future submitRepair(BuildContext context) async { + // //tmp + // // return ''; + // String message = ''; + // final MyDialogController myDialogController = + // Get.find(); + // if (model.device_type == null || model.device_type!.isEmpty) { + // message = '请选择设备类型!'; + // showToast(message); + // return message; + // } + // if (model.device_category == null || model.device_category!.isEmpty) { + // message = '请输入设备型号!'; + // showToast(message); + // return message; + // } + // if (model.device_id == null || model.device_id!.isEmpty) { + // message = '请输入设备序列号id!'; + // showToast(message); + // return message; + // } + // if (model.apply_name == null || model.apply_name!.isEmpty) { + // message = '请输入姓名!'; + // showToast(message); + // return message; + // } + // RegExp nameRegExp = RegExp(r'^[\u4e00-\u9fa5]{2,4}$'); + + // if (!nameRegExp.hasMatch(model.apply_name!)) { + // message = '姓名必须为2到4个汉字!'; + // showToast(message); + // return message; + // } + // if (model.tel == null || model.tel!.isEmpty) { + // message = '请输入手机号!'; + // showToast(message); + // return message; + // } + // if (!MyUtils.isValidPhoneNumber(model.tel!)) { + // message = '无效的手机号!'; + // showToast(message); + // return message; + // } + // if (model.address == null || model.address!.isEmpty) { + // message = '请输入地址!'; + // showToast(message); + // return message; + // } + // if (model.desc == null || model.desc!.isEmpty) { + // message = '请输入问题描述!'; + // showToast(message); + // return message; + // } + // if (model.issue_img == null || model.issue_img!.isEmpty) { + // message = '请至少上传一张问题图片!'; + // showToast(message); + // return message; + // } + // model.status = RepairStatus.pending; + // await repairRepository.saveRepair(model); + // return message; + // } + + // Future getDeviceList() async { + // final UserInfoController userInfoController = + // Get.find(); + // // UserModel loginUser = userInfoController.model.user!; + // DeviceListController deviceListController = Get.find(); + // await deviceListController.getDeviceList(); + // var aa = deviceListController.model.deviceListWyf; + // ApplyRepairController applyRepairController = Get.find(); + // applyRepairController.model.device_list = aa; + // } + + // String getPublicUrl(String path) { + // try { + // String bucketPath = '${model.img_bucket}/'; + // if (path.contains(bucketPath)) { + // int firstIndex = path.indexOf(bucketPath); + // // int secondIndex = + // // response.indexOf(bucketPath, firstIndex + bucketPath.length); + // if (firstIndex != -1) { + // // 去掉第一个存储桶路径 + // path = path.replaceFirst(bucketPath, '', firstIndex); + // } + // } + // String publicUrl = + // ef.client.storage.from(model.img_bucket!).getPublicUrl(path); + // return publicUrl; + // } catch (e) {} + // return ''; + // } +} diff --git a/lib/controller/mh/apply_repair_controller.g.dart b/lib/controller/mh/apply_repair_controller.g.dart new file mode 100644 index 0000000..8a5b4d0 --- /dev/null +++ b/lib/controller/mh/apply_repair_controller.g.dart @@ -0,0 +1,60 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'apply_repair_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ApplyRepairModel _$ApplyRepairModelFromJson(Map json) => + ApplyRepairModel() + ..id = (json['id'] as num?)?.toInt() + ..apply_name = json['apply_name'] as String? + ..tel = json['tel'] as String? + ..address = json['address'] as String? + ..desc = json['desc'] as String? + ..create_time = json['create_time'] == null + ? null + : DateTime.parse(json['create_time'] as String) + ..device_type = json['device_type'] as String? + ..device_category = json['device_category'] as String? + ..device_id = json['device_id'] as String? + ..device_name = json['device_name'] as String? + ..issue_img = (json['issue_img'] as List?) + ?.map((e) => e as String) + .toList() + ..imagesLImit = (json['imagesLImit'] as num?)?.toInt() + ..img_bucket = json['img_bucket'] as String? + ..status = json['status'] as String? + ..select_device = json['select_device'] as String? + ..device_list = json['device_list'] as List? + ..score = (json['score'] as num?)?.toInt() + ..score_time = json['score_time'] == null + ? null + : DateTime.parse(json['score_time'] as String) + ..messageType = (json['messageType'] as num?)?.toInt() + ..repairId = (json['repairId'] as num?)?.toInt(); + +Map _$ApplyRepairModelToJson(ApplyRepairModel instance) => + { + 'id': instance.id, + 'apply_name': instance.apply_name, + 'tel': instance.tel, + 'address': instance.address, + 'desc': instance.desc, + 'create_time': instance.create_time?.toIso8601String(), + 'device_type': instance.device_type, + 'device_category': instance.device_category, + 'device_id': instance.device_id, + 'device_name': instance.device_name, + 'issue_img': instance.issue_img, + 'imagesLImit': instance.imagesLImit, + 'img_bucket': instance.img_bucket, + 'status': instance.status, + 'select_device': instance.select_device, + 'device_list': instance.device_list, + 'score': instance.score, + 'score_time': instance.score_time?.toIso8601String(), + 'messageType': instance.messageType, + 'repairId': instance.repairId, + }; diff --git a/lib/controller/mh/book_info_controller.dart b/lib/controller/mh/book_info_controller.dart new file mode 100644 index 0000000..4b4420d --- /dev/null +++ b/lib/controller/mh/book_info_controller.dart @@ -0,0 +1,74 @@ +import 'dart:convert'; + +import 'package:ef/ef.dart'; + + +class BookInfoModel { + // DateTime? dateTime; //预约时间 + String? userName; //预约人 + String? userPhone; //预约电话 + List time_period = []; //预约时段 + // String? select_time; //选择时间 + int? select_time_index; //选择时间 + + List datetimes = []; + int? datetimes_index; + Map dataT = {}; + + BookInfoModel(); +} + +class BookInfoController extends GetControllerEx { + BookInfoController() { + attr = GetModel(BookInfoModel()).obs; + } + + // get userInfoController => Get.find(); + + // getData(id) { + // model.datetimes = []; + // model.datetimes_index = null; + // model.dataT = {}; + // updateAll(); + // ApiService.reservation.get("/agent/userBook/config/detailConfigByStore?storeId=$id") + // .then((d) { + // model.datetimes = d.data["dateList"]; + // model.datetimes_index = 0; + // model.dataT = d.data; + // time_periodChange(); + // }); + // } + + // time_periodChange() { + // if(model.datetimes_index == null) { + // return; + // } + // model.select_time_index = null; + // model.time_period = model.dataT[model.datetimes?[model.datetimes_index!]["day"]]; + // updateAll(); + // } + + // submitData(id) { + // String tel = userInfoController.model?.user?.tel ?? ""; + // if(tel.isEmpty) { + // showToast("用户未存在手机号"); + // return; + // } + // return ApiService.reservation.post("/agent/userBook/submitBook", data: { + // "extUserId": tel, + // "storeId": id, + // "realName": model.userName, + // "userPhone": model.userPhone, + // "bookDateId": model.time_period[model.select_time_index!]["id"] + // }); + // } + + // messageAdd(Map data) { + // return ApiService.request.post("/api/message/info", data: { + // "type": 0, + // "status": 1, + // "read": 1, + // "data": jsonEncode(data) + // }); + // } +} diff --git a/lib/controller/mh/experience_store_list_page.dart b/lib/controller/mh/experience_store_list_page.dart new file mode 100644 index 0000000..c856721 --- /dev/null +++ b/lib/controller/mh/experience_store_list_page.dart @@ -0,0 +1,125 @@ +import 'dart:ui'; + +import 'package:ef/ef.dart'; + + +import 'package:json_annotation/json_annotation.dart'; + +part 'experience_store_list_page.g.dart'; + +@JsonSerializable() +class ExperienceStoreListModel { + List experienceStoreModelList = []; //体验店列 + + @JsonKey(ignore: true) + String? keyword = ''; + @JsonKey(ignore: true) + Color? color = Color(0xFFFFFFFF); + + ExperienceStoreListModel(); + // static ExperienceStoreListModel fromJson(Map json) => + // _$ExperienceStoreListModelFromJson(json); + // Map toJson() => _$ExperienceStoreListModelToJson(this); +} + +class ExperienceStoreListController + extends GetControllerEx { + ExperienceStoreListController() { + attr = GetModel(ExperienceStoreListModel()).obs; + } + + // Position? position; + // double latitude = 31.8512; + // double longitude = 117.26061; + + // int total = 0; + // int page = 0; + // bool lock = false; + + + // resetParm() { + // position = null; + // total = 0; + // page = 0; + // lock = false; + // model.experienceStoreModelList = []; + // updateAll(); + // } + + // getData({int count = 10}) async { + // if (page != 0 && page * count > total) { + // return; + // } + // if (lock) { + // return; + // } + // if (page == 0) { + // position = await locationCheck(); + // } + // lock = true; + // int page_ = page; + // ApiService.reservation + // .get( + // "/agent/userBook/config/getBookStoreList?storeName=${"${model.keyword}".isNotEmpty ? model.keyword : ''}&latitude=${position == null ? latitude : position?.latitude}&longitude=${position == null ? longitude : position?.longitude}&page=$page&size=$count&sort=distance") + // .then((d) { + // lock = false; + // if (page == 0) { + // model.experienceStoreModelList = d.data["records"]; + // } else { + // int index = 0; + // d.data["records"]?.forEach((item) { + // if (model.experienceStoreModelList + // .indexWhere((item2) => item2["id"] == item["id"]) == + // -1) { + // model.experienceStoreModelList.add(item); + // } else { + // model.experienceStoreModelList[index] = item; + // } + // index++; + // }); + // } + // page = page_ + 1; + // total = d.data["total"]; + // updateAll(); + // }).catchError((d) { + // lock = false; + // }); + // } + + determinePosition() async { + // bool serviceEnabled; + // LocationPermission permission; + + // // Test if location services are enabled. + // serviceEnabled = await Geolocator.isLocationServiceEnabled(); + // if (!serviceEnabled) { + // // Location services are not enabled don't continue + // // accessing the position and request users of the + // // App to enable the location services. + // return Future.error('Location services are disabled.'); + // } + + // permission = await Geolocator.checkPermission(); + // if (permission == LocationPermission.denied) { + // permission = await Geolocator.requestPermission(); + // if (permission == LocationPermission.denied) { + // // Permissions are denied, next time you could try + // // requesting permissions again (this is also where + // // Android's shouldShowRequestPermissionRationale + // // returned true. According to Android guidelines + // // your App should show an explanatory UI now. + // return Future.error('Location permissions are denied'); + // } + // } + + // if (permission == LocationPermission.deniedForever) { + // // Permissions are denied forever, handle appropriately. + // return Future.error( + // 'Location permissions are permanently denied, we cannot request permissions.'); + // } + + // // When we reach here, permissions are granted and we can + // // continue accessing the position of the device. + // position = await Geolocator.getCurrentPosition(); + } +} diff --git a/lib/controller/mh/experience_store_list_page.g.dart b/lib/controller/mh/experience_store_list_page.g.dart new file mode 100644 index 0000000..6c658c4 --- /dev/null +++ b/lib/controller/mh/experience_store_list_page.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'experience_store_list_page.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ExperienceStoreListModel _$ExperienceStoreListModelFromJson( + Map json) => + ExperienceStoreListModel() + ..experienceStoreModelList = + json['experienceStoreModelList'] as List; + +Map _$ExperienceStoreListModelToJson( + ExperienceStoreListModel instance) => + { + 'experienceStoreModelList': instance.experienceStoreModelList, + }; diff --git a/lib/controller/mh/issue_controller.dart b/lib/controller/mh/issue_controller.dart new file mode 100644 index 0000000..222a666 --- /dev/null +++ b/lib/controller/mh/issue_controller.dart @@ -0,0 +1,55 @@ +import 'package:ef/ef.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; + +part 'issue_controller.g.dart'; + +@JsonSerializable() +class IssueListModel { + List issueList = []; + + int limit = AppConstants.limit; + int offset = 0; + bool isLoading = false; + bool hasMore = true; + + int? selectedIndex; + + IssueListModel(); + static IssueListModel fromJson(Map json) => + _$IssueListModelFromJson(json); + Map toJson() => _$IssueListModelToJson(this); +} + +class IssueListController extends GetControllerEx { + // HelpRepository helpRepository = HelpRepository(); + IssueListController() { + attr = GetModel(IssueListModel()).obs; + } + + + // //初始化列表数据 + // Future initData() async { + // if (model.isLoading) { + // return; + // } + // model.isLoading = true; + // final List fetchedRepairs = await helpRepository.findHelpInfos( + // limit: model.limit, offset: model.offset); + // if (fetchedRepairs != null) { + // List infos = []; + // List tmp = fetchedRepairs as List; + // try { + // // infos = tmp.map((repair) => IssueModel.fromJson(repair)).toList(); + // // model.issueList!.addAll(infos); + // model.issueList.addAll(tmp); + // } catch (e) { + // print('Error parsing JSON: $e'); + // } + // } + // model.offset += model.limit; // 更新 offset,下一次查询跳过当前已经加载的记录 + // model.hasMore = fetchedRepairs.length == model.limit; // 判断是否还有更多数据 + // model.isLoading = false; + // updateAll(); + // } +} diff --git a/lib/controller/mh/issue_controller.g.dart b/lib/controller/mh/issue_controller.g.dart new file mode 100644 index 0000000..ac15cea --- /dev/null +++ b/lib/controller/mh/issue_controller.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'issue_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +IssueListModel _$IssueListModelFromJson(Map json) => + IssueListModel() + ..issueList = json['issueList'] as List + ..limit = (json['limit'] as num).toInt() + ..offset = (json['offset'] as num).toInt() + ..isLoading = json['isLoading'] as bool + ..hasMore = json['hasMore'] as bool + ..selectedIndex = (json['selectedIndex'] as num?)?.toInt(); + +Map _$IssueListModelToJson(IssueListModel instance) => + { + 'issueList': instance.issueList, + 'limit': instance.limit, + 'offset': instance.offset, + 'isLoading': instance.isLoading, + 'hasMore': instance.hasMore, + 'selectedIndex': instance.selectedIndex, + }; diff --git a/lib/controller/mh/issue_preview_controller.dart b/lib/controller/mh/issue_preview_controller.dart new file mode 100644 index 0000000..c436572 --- /dev/null +++ b/lib/controller/mh/issue_preview_controller.dart @@ -0,0 +1,20 @@ +import 'package:ef/ef.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'issue_preview_controller.g.dart'; + +@JsonSerializable() +class IssuePreviewInfoModel { + + IssuePreviewInfoModel(); + + static IssuePreviewInfoModel fromJson(Map json) => + _$IssuePreviewInfoModelFromJson(json); + Map toJson() => _$IssuePreviewInfoModelToJson(this); +} + +class IssuePreviewInfoController extends GetControllerEx { + IssuePreviewInfoController() { + attr = GetModel(IssuePreviewInfoModel()).obs; + } +} diff --git a/lib/controller/mh/issue_preview_controller.g.dart b/lib/controller/mh/issue_preview_controller.g.dart new file mode 100644 index 0000000..c6cfbd1 --- /dev/null +++ b/lib/controller/mh/issue_preview_controller.g.dart @@ -0,0 +1,15 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'issue_preview_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +IssuePreviewInfoModel _$IssuePreviewInfoModelFromJson( + Map json) => + IssuePreviewInfoModel(); + +Map _$IssuePreviewInfoModelToJson( + IssuePreviewInfoModel instance) => + {}; diff --git a/lib/controller/mh/message_controller.dart b/lib/controller/mh/message_controller.dart new file mode 100644 index 0000000..f4389dd --- /dev/null +++ b/lib/controller/mh/message_controller.dart @@ -0,0 +1,198 @@ +import 'dart:convert'; + +import 'package:EasyDartModule/EasyDartModule.dart'; +import 'package:ef/ef.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:vbvs_app/common/color/ServiceConstant.dart'; +import 'package:vbvs_app/common/color/app_uri_status.dart'; +import 'package:vbvs_app/common/util/DailyLogUtils.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/model/api_response.dart'; + +part 'message_controller.g.dart'; // 由json_serializable自动生成的部分 + +@JsonSerializable() +class MhMessageModel { + int? type = 1; //设备类型 1:体征消息 2.系统消息 + int? body_message_read = 0; //体征消息 0:已读 1:未读 + int? system_message_read = 0; //系统消息 0:已读 1:未读 + + MhMessageModel(); + + // 从JSON反序列化时的异常处理 + + factory MhMessageModel.fromJson(Map json) { + try { + return _$MhMessageModelFromJson(json); + } catch (e) { + // 在实际应用中,应该有更细致的异常处理策略和错误日志 + return MhMessageModel(); // 或者返回一个带有错误信息的特定DeviceInfoModel实例 + } + } + + // 序列化为JSON时的异常处理 + Map toJson() => _$MhMessageModelToJson(this); +} + +class MhMessageController extends GetControllerEx { + MhMessageController() { + attr = GetModel(MhMessageModel()).obs; + } + + RxList messageList = [].obs; + + Future getMessageList({String? key}) async { + try { + ApiResponse apiResponse = ApiResponse(code: -1, msg: "请求失败".tr); + String serviceAddress = ServiceConstant.service_address; + String serviceName = ServiceConstant.server_service; + String serviceApi = ServiceConstant.message_list; + String messageType = "app_system"; + if (model.type == 1) { + messageType = "app_body"; + } else { + messageType = "app_system"; + } + String queryUrl = + "${serviceAddress}${serviceName}${serviceApi}?type=${messageType}"; + String? language = ""; + if (languageController.selectLanguage != null) { + language = languageController.selectLanguage.value!.language_code; + } + if (language != null && language.isNotEmpty) { + if (queryUrl.contains("?")) { + queryUrl += "&lang=$language"; + } else { + queryUrl += "?lang=$language"; + } + } + var response = await EasyDartModule.dio.get(queryUrl); + if (response != null) { + var responseData = + response.data is String ? jsonDecode(response.data) : response.data; + ApiResponse res = + ApiResponse.fromJson(responseData, (object) => object); + MyUtils.formatResponse(res, "请求成功".tr, "请求失败".tr); + if (res.code == HttpStatusCodes.ok) { + updateAll(); + messageList.value = res.data; + return res; + } + } else { + return ApiResponse(code: -1, msg: "服务器.失败".tr); + } + return apiResponse; + } catch (e) { + EasyDartModule.logger.info("设备请求列表: $e"); + DailyLogUtils.writeLog("设备请求列表: $e"); + } + return ApiResponse(code: -1, msg: "未知错误".tr); // Default return statement + } + + //获取消息已读未读 + Future getMessageStatus() async { + try { + ApiResponse apiResponse = ApiResponse(code: -1, msg: "请求失败".tr); + // return apiResponse; + String serviceAddress = ServiceConstant.service_address; + String serviceName = ServiceConstant.server_service; + String serviceApi = ServiceConstant.message_read; + + String queryUrl = "${serviceAddress}${serviceName}${serviceApi}"; + String? language = ""; + if (languageController.selectLanguage != null) { + language = languageController.selectLanguage.value!.language_code; + } + if (language != null && language.isNotEmpty) { + if (queryUrl.contains("?")) { + queryUrl += "&lang=$language"; + } else { + queryUrl += "?lang=$language"; + } + } + var response = await EasyDartModule.dio.get(queryUrl); + if (response != null) { + var responseData = + response.data is String ? jsonDecode(response.data) : response.data; + ApiResponse res = + ApiResponse.fromJson(responseData, (object) => object); + MyUtils.formatResponse(res, "请求成功".tr, "请求失败".tr); + if (res.code == HttpStatusCodes.ok) { + updateAll(); + List dataList = res.data; + + // 查找 type 为 app_vsm 的项 + var vsmItem = dataList.firstWhere( + (e) => e['type'] == 'app_vsm', + orElse: () => null, + ); + model.body_message_read = vsmItem?['count'] ?? 0; + + // 查找 type 为 app_system 的项 + var systemItem = dataList.firstWhere( + (e) => e['type'] == 'app_system', + orElse: () => null, + ); + model.system_message_read = systemItem?['count'] ?? 0; + + updateAll(); + return res; + } + } else { + return ApiResponse(code: -1, msg: "服务器.失败".tr); + } + return apiResponse; + } catch (e) { + EasyDartModule.logger.info("获取消息已读未读: $e"); + DailyLogUtils.writeLog("获取消息已读未读: $e"); + } + return ApiResponse(code: -1, msg: "未知错误".tr); // Default return statement + } + + //更新消息已读 + Future updateMessageStatus({String? type}) async { + EasyDartModule.logger.info("更新消息已读状态"); + DailyLogUtils.writeLog("更新消息已读状态"); + try { + ApiResponse apiResponse = ApiResponse(code: -1, msg: "操作失败".tr); + String serviceAddress = ServiceConstant.service_address; + String serviceName = ServiceConstant.server_service; + String serviceApi = ServiceConstant.message_read; + + // 拼接 URL,添加 type 参数 + String queryUrl = "$serviceAddress$serviceName$serviceApi"; + if (type != null && type.isNotEmpty) { + queryUrl += "?type=$type"; + } + + String? language = ""; + if (languageController.selectLanguage != null) { + language = languageController.selectLanguage.value!.language_code; + } + if (language != null && language.isNotEmpty) { + if (queryUrl.contains("?")) { + queryUrl += "&lang=$language"; + } else { + queryUrl += "?lang=$language"; + } + } + var response = await EasyDartModule.dio.post(queryUrl); + + if (response != null) { + var responseData = + response.data is String ? jsonDecode(response.data) : response.data; + ApiResponse res = + ApiResponse.fromJson(responseData, (object) => object); + MyUtils.formatResponse(res, "操作成功".tr, "操作成功".tr); + return res; + } else { + return ApiResponse(code: -1, msg: "服务器.失败".tr); + } + } catch (e) { + EasyDartModule.logger.info("更新消息已读状态->$e"); + DailyLogUtils.writeLog("更新消息已读状态->$e"); + return ApiResponse(code: -1, msg: "服务器.失败".tr); + } + } +} diff --git a/lib/controller/mh/message_controller.g.dart b/lib/controller/mh/message_controller.g.dart new file mode 100644 index 0000000..564e51f --- /dev/null +++ b/lib/controller/mh/message_controller.g.dart @@ -0,0 +1,20 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'message_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +MhMessageModel _$MhMessageModelFromJson(Map json) => + MhMessageModel() + ..type = (json['type'] as num?)?.toInt() + ..body_message_read = (json['body_message_read'] as num?)?.toInt() + ..system_message_read = (json['system_message_read'] as num?)?.toInt(); + +Map _$MhMessageModelToJson(MhMessageModel instance) => + { + 'type': instance.type, + 'body_message_read': instance.body_message_read, + 'system_message_read': instance.system_message_read, + }; diff --git a/lib/controller/mh/muser_info_controller.dart b/lib/controller/mh/muser_info_controller.dart new file mode 100644 index 0000000..96fb747 --- /dev/null +++ b/lib/controller/mh/muser_info_controller.dart @@ -0,0 +1,177 @@ +import 'dart:io'; + +import 'package:ef/ef.dart'; +import 'package:fluwx/fluwx.dart'; +import 'package:json_annotation/json_annotation.dart'; + +import 'package:path/path.dart' as p; + +import 'package:vbvs_app/controller/mh/user_data.dart'; +part 'muser_info_controller.g.dart'; + +@JsonSerializable() +class MUserInfoModel { + int? message = 0; //消息数量 + + UserModel? user; //用户信息 + String? token; //token值 + String? runSystem; //运行系统 + String? phoneVersion; //手机版本 + String? deviceId; //手机唯一 + String? deviceModel; //设备可见型号(如 "iPhone","iPad") + String? appVersion; //app版本信息 + + @JsonKey(ignore: true) + Session? superbase_session; + @JsonKey(ignore: true) + User? superbase_user; + + String? img_bucket = 'user'; + int? login = 0; //是否登录0:未登录 1:已登录 + + MUserInfoModel(); + static MUserInfoModel fromJson(Map json) => + _$MUserInfoModelFromJson(json); + Map toJson() => _$MUserInfoModelToJson(this); +} + +class MUserInfoController extends GetControllerEx { + // 初始化实例 + final Fluwx fluwx = Fluwx(); + + MUserInfoController() { + attr = GetModel(MUserInfoModel()).obs; + } + + // Future uploadImg() async { + // final ImagePicker picker = ImagePicker(); + // final XFile? image = await picker.pickImage(source: ImageSource.gallery); + // final user = Supabase.instance.client.auth.currentUser; + // try { + // if (image != null) { + // int fileSize = await image.length(); // 获取图片大小,单位为字节 + // if (fileSize > 1048576) { + // // 1 MB = 1024 * 1024 bytes + // showToast("头像图片不能超过1MB"); + // return; + // } + // final filePath = image.path; // 获取文件路径 + // final fileExtension = p.extension(filePath); // 获取文件扩展名,包括点(.) + // // 获取当前日期并格式化为 yyyy-MM-dd + // final String folderName = + // DateFormat('yyyy-MM-dd').format(DateTime.now()); + // final file = File(image.path); + // // 构造文件路径,文件会被上传到 record_img 文件夹下的当天日期文件夹 + // var response = await ef.client.storage + // .from(model.img_bucket!) + // .upload('$folderName/${Uuid().v4()}$fileExtension', file); + // if (response != null) { + // String publicUrl = + // ef.client.storage.from(model.img_bucket!).getPublicUrl(response); + + // print('文件上传成功: $response'); + // print('文件上传成功: $publicUrl'); + // String prefixToRemove = 'user/'; + // // model.user!.tmpHead = model.user!.head; + // model.user!.tmpHead = publicUrl.startsWith(prefixToRemove) + // ? response.substring(prefixToRemove.length) + // : response; + // updateAll(); + // } + // print('/$model.img_bucket'); + // } else { + // print('未选择图片'); + // return; + // } + // } catch (e) { + // print('上传失败: $e'); + // } + // } + + // updateData() { + // UserInfoController controller = Get.find(); + // UserRepository userRepository = UserRepository(); + // return userRepository.updateInfo(controller.model.user!); + // } + + // autoLogin(String token) async { + // final UserInfoController userInfoController = Get.find(); + // try { + // final Map requestBody = { + // 'token': token, + // }; + + // var response = await ApiService.request + // .post("/api/auth/account/info/autoLogin", data: requestBody); + // if (response.statusCode == 200) { + // if (response.data != null) { + // ApiResponse apiResponse = ApiResponse.fromJson( + // response.data, + // (json) => UserModel.fromJson(json as Map)); + // if (apiResponse.code == HttpStatusCodes.ok) { + // userInfoController.model.user = apiResponse.data; + // userInfoController.model.token = response.headers['token']!.first; + // userInfoController.model.login = 1; + + // final box = GetStorage(); + // box.write( + // 'user', userInfoController.model.user!.toJson()); // 存储用户信息 + // box.write('token', userInfoController.model.token); // 存储 token + // String efPd = await getValueBySysConfigKey(CommonVariables.efKey); + // if (efPd != null && efPd.isNotEmpty) { + // await initDataEf(key: efPd); + // } else { + // print("efPD为空,无法初始化"); + // // 清除本地缓存 + // final box = GetStorage(); + // box.remove('user'); + // box.remove('token'); + // userInfoController.model.token = null; + // userInfoController.model.user = null; + // // 设置成未登录 + // userInfoController.model.login = 0; + // return; + // } + + // final AuthResponse res = await ef.client.auth.signInWithPassword( + // phone: userInfoController.model.user!.tel, + // password: userInfoController.model.user!.exp1!, + // ); + // userInfoController.model.superbase_session = res.session; + // userInfoController.model.superbase_user = res.user; + // userInfoController.updateAll(); + // // 登录成功移出网络检查监听 + // Checknetwork.subscription?.cancel(); + // } + // } + // } else { + // // 处理非 200 响应 + // print('Failed to sign in. Status code: ${response.statusCode}'); + // print('Response data: ${response.data}'); + // } + // } catch (e) { + // e.printError(); + // // 清除本地缓存 + // final box = GetStorage(); + // box.remove('user'); + // box.remove('token'); + // userInfoController.model.token = null; + // userInfoController.model.user = null; + // // 设置成未登录 + // userInfoController.model.login = 0; + // } + // } + + // // 拉起微信企业客服 + // Future openWeChatCustomerService() async { + // bool isWeChatInstalled = await fluwx.isWeChatInstalled; + // if (!isWeChatInstalled) { + // showToast("请先安装微信APP,再联系客服", color: color_error); + // return; + // } + // showToast('正在打开微信客服...', color: color_success); + // await fluwx.open( + // target: CustomerServiceChat( + // corpId: CommonVariables.wxCorpId, url: CommonVariables.wxKfUrl)); + // } +} diff --git a/lib/controller/mh/muser_info_controller.g.dart b/lib/controller/mh/muser_info_controller.g.dart new file mode 100644 index 0000000..1dc29be --- /dev/null +++ b/lib/controller/mh/muser_info_controller.g.dart @@ -0,0 +1,36 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'muser_info_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +MUserInfoModel _$MUserInfoModelFromJson(Map json) => + MUserInfoModel() + ..message = (json['message'] as num?)?.toInt() + ..user = json['user'] == null + ? null + : UserModel.fromJson(json['user'] as Map) + ..token = json['token'] as String? + ..runSystem = json['runSystem'] as String? + ..phoneVersion = json['phoneVersion'] as String? + ..deviceId = json['deviceId'] as String? + ..deviceModel = json['deviceModel'] as String? + ..appVersion = json['appVersion'] as String? + ..img_bucket = json['img_bucket'] as String? + ..login = (json['login'] as num?)?.toInt(); + +Map _$MUserInfoModelToJson(MUserInfoModel instance) => + { + 'message': instance.message, + 'user': instance.user, + 'token': instance.token, + 'runSystem': instance.runSystem, + 'phoneVersion': instance.phoneVersion, + 'deviceId': instance.deviceId, + 'deviceModel': instance.deviceModel, + 'appVersion': instance.appVersion, + 'img_bucket': instance.img_bucket, + 'login': instance.login, + }; diff --git a/lib/controller/mh/my_experience_list_controller.dart b/lib/controller/mh/my_experience_list_controller.dart new file mode 100644 index 0000000..b4b7c41 --- /dev/null +++ b/lib/controller/mh/my_experience_list_controller.dart @@ -0,0 +1,115 @@ +import 'dart:convert'; + +import 'package:ef/ef.dart'; + + +class BookExperienceListModel { + List bookInfoList = []; //预约列表 + List experienceStoreModelList = []; +} + +class BookExperienceListController + extends GetControllerEx { + BookExperienceListController() { + attr = GetModel(BookExperienceListModel()).obs; + } + + // resetParm() { + // model.bookInfoList = []; + // model.experienceStoreModelList = []; + // total = 0; + // page = 0; + // lock = false; + // updateAll(); + // } + + // getAllBook() { + // ApiService.reservation + // .get( + // "/agent/userBook/config/getBookStoreList?storeName=&latitude=31.8512&longitude=117.26061&page=0&size=20000&sort=distance") + // .then((d) { + // model.experienceStoreModelList = d.data["records"]; + // updateAll(); + // }); + // } + + // int total = 0; + // int page = 0; + // bool lock = false; + + // getData({int count = 10, Function? finished}) { + // if (page != 0 && page * count > total) { + // finished?.call(); + // return; + // } + // if (lock) { + // finished?.call(); + // return; + // } + // lock = true; + // int page_ = page; + // String tel = Get.find().model.user?.tel ?? ""; + // if (tel.isEmpty) { + // showToast("用户未存在手机号"); + // finished?.call(); + // return; + // } + // ApiService.reservation + // .get( + // "/agent/userBook/list?extUserId=$tel&page=$page_&size=$count&sort=create_time,desc") + // .then((d) { + // lock = false; + // finished?.call(); + // if (page == 0) { + // model.bookInfoList = d.data["records"]; + // } else { + // int index = 0; + // d.data["records"]?.forEach((item) { + // if (model.bookInfoList + // .indexWhere((item2) => item2["id"] == item["id"]) == + // -1) { + // model.bookInfoList.add(item); + // } else { + // model.bookInfoList[index] = item; + // } + // index++; + // }); + // } + // page = page_ + 1; + // total = d.data["total"]; + // updateAll(); + // }).catchError((d) { + // lock = false; + // finished?.call(); + // }); + // } + + // cancelBook(id, {Function? success}) { + // String tel = Get.find().model.user?.tel ?? ""; + // if (tel.isEmpty) { + // showToast("用户未存在手机号"); + // return; + // } + // LoadingDialog.show("提交中..."); + // ApiService.reservation + // .post("/agent/userBook/cancel?extUserId=$tel&id=$id") + // .then((d) { + // page = 0; + // getData(finished: () { + // LoadingDialog.hide(); + // }); + // success?.call(); + // }).catchError((d) { + // LoadingDialog.hide(); + // }); + // } + + // messageAdd(Map data) { + // return ApiService.request.post("/api/message/info", data: { + // "type": 0, + // "status": 1, + // "read": 1, + // "data": jsonEncode(data) + // }); + // } +} diff --git a/lib/controller/mh/people_info_controller.dart b/lib/controller/mh/people_info_controller.dart new file mode 100644 index 0000000..14a36be --- /dev/null +++ b/lib/controller/mh/people_info_controller.dart @@ -0,0 +1,111 @@ +import 'package:ef/ef.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; + +part 'people_info_controller.g.dart'; // 由json_serializable自动生成的部分 + +class PeopleInfoModel { + List peopleList = [PeopleInfoPojo(), PeopleInfoPojo()]; +} + +@JsonSerializable() +class PeopleInfoPojo { + String? name; + String sex = "男"; + String? height; + String? weight; + DateTime? birthday; + String? tel; + String? emergencyContact; + + PeopleInfoPojo(); + + // // 从JSON反序列化时的异常处理 + + factory PeopleInfoPojo.fromJson(Map json) { + try { + return _$PeopleInfoPojoFromJson(json); + } catch (e) { + // 在实际应用中,应该有更细致的异常处理策略和错误日志 + return PeopleInfoPojo(); // 或者返回一个带有错误信息的特定PeopleInfoModel实例 + } + } + + // 序列化为JSON时的异常处理 + Map toJson() => _$PeopleInfoPojoToJson(this); +} + +class PeopleInfoController extends GetControllerEx { + PeopleInfoController() { + attr = GetModel(PeopleInfoModel()).obs; + } + + GlobalController get glcontroller => Get.find(); + + // getPeoples() async { + // var arr = []; + // String bindMacA = + // glcontroller.getUpperCaseMac(glcontroller.model.deviceMain["bindMacA"]); + // String bindMacB = + // glcontroller.getUpperCaseMac(glcontroller.model.deviceMain["bindMacB"]); + // arr.add(bindMacA); + // if (bindMacB.length > 6) { + // arr.add(bindMacB); + // } else { + // model.peopleList[1] = PeopleInfoPojo(); + // } + // model.peopleList[0] = PeopleInfoPojo(); + // print("getuser $arr"); + // var data = await ef.from("app_personnel").select().inFilter("mac", arr); + // print("getuser $data"); + // data?.forEach((d) { + // PeopleInfoPojo peopleInfoPojo = PeopleInfoPojo(); + // peopleInfoPojo.name = d["name"]; + // peopleInfoPojo.sex = d["gender"] == 1 ? "男" : "女"; + // peopleInfoPojo.height = d["height"] == null ? null : "${d["height"]}"; + // peopleInfoPojo.weight = d["weight"] == null ? null : "${d["weight"]}"; + // if (d["birthday"] != null) { + // peopleInfoPojo.birthday = DateTime.parse(d["birthday"]).toLocal(); + // } + // peopleInfoPojo.tel = d["tel"]; + // peopleInfoPojo.emergencyContact = d["contact"]; + // if (glcontroller.getUpperCaseMac(d['mac']) == bindMacA) { + // model.peopleList[0] = peopleInfoPojo; + // } + // if (glcontroller.getUpperCaseMac(d['mac']) == bindMacB) { + // model.peopleList[1] = peopleInfoPojo; + // } + // }); + // updateAll(); + // attr.value.updateAll(); + // } + + // savePeoples() async { + // String bindMacA = + // glcontroller.getUpperCaseMac(glcontroller.model.deviceMain["bindMacA"]); + // String bindMacB = + // glcontroller.getUpperCaseMac(glcontroller.model.deviceMain["bindMacB"]); + // List arr = []; + // for (var i = 0; i < 2; i++) { + // if (i == 1 && bindMacB.length < 6) { + // break; + // } + // arr.add(ef.from("app_personnel").update({ + // "name": model.peopleList[i].name, + // "gender": model.peopleList[i].sex == "男" ? 1 : 0, + // "height": int.tryParse("${model.peopleList[i].height}"), + // "weight": int.tryParse("${model.peopleList[i].weight}"), + // "birthday": model.peopleList[i].birthday == null + // ? null + // : model.peopleList[i].birthday.toString(), + // "tel": model.peopleList[i].tel, + // "contact": model.peopleList[i].emergencyContact + // }).eq("mac", i == 0 ? bindMacA : bindMacB)); + // } + // return Future.wait(arr); + // } + + // Future saveOnePeople(mac, data) async { + // return ef.from("app_personnel").update(data).eq("mac", mac); + // } +} diff --git a/lib/controller/mh/people_info_controller.g.dart b/lib/controller/mh/people_info_controller.g.dart new file mode 100644 index 0000000..1c66eb4 --- /dev/null +++ b/lib/controller/mh/people_info_controller.g.dart @@ -0,0 +1,30 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'people_info_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +PeopleInfoPojo _$PeopleInfoPojoFromJson(Map json) => + PeopleInfoPojo() + ..name = json['name'] as String? + ..sex = json['sex'] as String + ..height = json['height'] as String? + ..weight = json['weight'] as String? + ..birthday = json['birthday'] == null + ? null + : DateTime.parse(json['birthday'] as String) + ..tel = json['tel'] as String? + ..emergencyContact = json['emergencyContact'] as String?; + +Map _$PeopleInfoPojoToJson(PeopleInfoPojo instance) => + { + 'name': instance.name, + 'sex': instance.sex, + 'height': instance.height, + 'weight': instance.weight, + 'birthday': instance.birthday?.toIso8601String(), + 'tel': instance.tel, + 'emergencyContact': instance.emergencyContact, + }; diff --git a/lib/controller/mh/repair_info_controller.dart b/lib/controller/mh/repair_info_controller.dart new file mode 100644 index 0000000..b21eae7 --- /dev/null +++ b/lib/controller/mh/repair_info_controller.dart @@ -0,0 +1,68 @@ +import 'package:ef/ef.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:vbvs_app/controller/mh/apply_repair_controller.dart'; +import 'package:vbvs_app/controller/mh/repair_process.dart'; + +part 'repair_info_controller.g.dart'; + +@JsonSerializable() +class RepairInfoModel { + String? id; //记录id + DateTime? create_time; //提交时间 + String? status; //状态 + String? desc; //描述 + int? record_id; //归属记录id + + List repairProcessList = []; //审核流程 + String? device_name; + ApplyRepairModel? applyRepairModel; + + RepairInfoModel(); + + static RepairInfoModel fromJson(Map json) => + _$RepairInfoModelFromJson(json); + Map toJson() => _$RepairInfoModelToJson(this); +} + +class RepairInfoController extends GetControllerEx { + // RepairRepository repairRepository = RepairRepository(); + RepairInfoController() { + attr = GetModel(RepairInfoModel()).obs; + } + + // Future initData(ApplyRepairModel applyRepairModel) async { + // if (applyRepairModel != null) { + // final List fetchedRepairs = + // await repairRepository.findData(applyRepairModel.id!); + // RepairListController repairListController = Get.find(); + // final List info = await repairListController.repairRepository + // .findRecordData(applyRepairModel.id!); + // if (info.isNotEmpty) { + // List infos = []; + // List tmp = info as List; + // try { + // infos = + // tmp.map((repair) => ApplyRepairModel.fromJson(repair)).toList(); + // model.applyRepairModel = infos.first; + // updateAll(); + // } catch (e) { + // print('Error parsing JSON: $e'); + // } + // // model.applyRepairModel = applyRepairModel; + // } + + // if (fetchedRepairs != null) { + // List infos = []; + // List tmp = fetchedRepairs as List; + // try { + // infos = + // tmp.map((repair) => RepairProcessModel.fromJson(repair)).toList(); + // model.repairProcessList = infos; + // updateAll(); + // } catch (e) { + // print('Error parsing JSON: $e'); + // } + // } + // } + // } +} diff --git a/lib/controller/mh/repair_info_controller.g.dart b/lib/controller/mh/repair_info_controller.g.dart new file mode 100644 index 0000000..0ef35b6 --- /dev/null +++ b/lib/controller/mh/repair_info_controller.g.dart @@ -0,0 +1,37 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'repair_info_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +RepairInfoModel _$RepairInfoModelFromJson(Map json) => + RepairInfoModel() + ..id = json['id'] as String? + ..create_time = json['create_time'] == null + ? null + : DateTime.parse(json['create_time'] as String) + ..status = json['status'] as String? + ..desc = json['desc'] as String? + ..record_id = (json['record_id'] as num?)?.toInt() + ..repairProcessList = (json['repairProcessList'] as List) + .map((e) => RepairProcessModel.fromJson(e as Map)) + .toList() + ..device_name = json['device_name'] as String? + ..applyRepairModel = json['applyRepairModel'] == null + ? null + : ApplyRepairModel.fromJson( + json['applyRepairModel'] as Map); + +Map _$RepairInfoModelToJson(RepairInfoModel instance) => + { + 'id': instance.id, + 'create_time': instance.create_time?.toIso8601String(), + 'status': instance.status, + 'desc': instance.desc, + 'record_id': instance.record_id, + 'repairProcessList': instance.repairProcessList, + 'device_name': instance.device_name, + 'applyRepairModel': instance.applyRepairModel, + }; diff --git a/lib/controller/mh/repair_list_controller.dart b/lib/controller/mh/repair_list_controller.dart new file mode 100644 index 0000000..edd58ce --- /dev/null +++ b/lib/controller/mh/repair_list_controller.dart @@ -0,0 +1,83 @@ +import 'package:ef/ef.dart'; +import 'package:json_annotation/json_annotation.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'apply_repair_controller.dart'; +part 'repair_list_controller.g.dart'; + +@JsonSerializable() +class RepairListModel { + int limit = AppConstants.limit; + int offset = 0; + bool isLoading = false; + bool hasMore = true; + + List repairList = []; + + RepairListModel(); + static RepairListModel fromJson(Map json) => + _$RepairListModelFromJson(json); + Map toJson() => _$RepairListModelToJson(this); +} + +class RepairListController extends GetControllerEx { + // RepairRepository repairRepository = RepairRepository(); + // RepairListController() { + // attr = GetModel(RepairListModel()).obs; + // } + + // //初始化列表数据 + // Future initData() async { + // if (model.isLoading) { + // return; + // } + // model.isLoading = true; + // final List fetchedRepairs = await repairRepository.fetchRepairs( + // limit: model.limit, offset: model.offset); + // if (fetchedRepairs != null) { + // List infos = []; + // List tmp = fetchedRepairs as List; + // try { + // infos = tmp.map((repair) => ApplyRepairModel.fromJson(repair)).toList(); + // model.repairList.addAll(infos); + // } catch (e) { + // print('Error parsing JSON: $e'); + // } + // } + // model.offset += model.limit; // 更新 offset,下一次查询跳过当前已经加载的记录 + // model.hasMore = fetchedRepairs.length == model.limit; // 判断是否还有更多数据 + // model.isLoading = false; + // updateAll(); + // } + + // Future addScore(int id, int score) async { + // return await repairRepository.addScore(id, score); + // } + @override + void onInit() { + super.onInit(); + loadMockRepairList(); + } + + void loadMockRepairList() { + model.repairList = [ + ApplyRepairModel() + ..id = 1001 + ..device_category = '智能床垫 BY-H' + ..status = '待维修' + ..create_time = DateTime.now().subtract(Duration(days: 1)) + ..device_id = 'BYH-001', + ApplyRepairModel() + ..id = 1002 + ..device_category = '智能床垫 BY-A' + ..status = '维修中' + ..create_time = DateTime.now().subtract(Duration(days: 2)) + ..device_id = 'BYA-002', + ApplyRepairModel() + ..id = 1003 + ..device_category = '智能床垫 BY-C' + ..status = '已完成' + ..create_time = DateTime.now().subtract(Duration(days: 3)) + ..device_id = 'BYC-003', + ]; + } +} diff --git a/lib/controller/mh/repair_list_controller.g.dart b/lib/controller/mh/repair_list_controller.g.dart new file mode 100644 index 0000000..0e260c6 --- /dev/null +++ b/lib/controller/mh/repair_list_controller.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'repair_list_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +RepairListModel _$RepairListModelFromJson(Map json) => + RepairListModel() + ..limit = (json['limit'] as num).toInt() + ..offset = (json['offset'] as num).toInt() + ..isLoading = json['isLoading'] as bool + ..hasMore = json['hasMore'] as bool + ..repairList = (json['repairList'] as List) + .map((e) => ApplyRepairModel.fromJson(e as Map)) + .toList(); + +Map _$RepairListModelToJson(RepairListModel instance) => + { + 'limit': instance.limit, + 'offset': instance.offset, + 'isLoading': instance.isLoading, + 'hasMore': instance.hasMore, + 'repairList': instance.repairList, + }; diff --git a/lib/controller/mh/repair_process.dart b/lib/controller/mh/repair_process.dart new file mode 100644 index 0000000..de3e16d --- /dev/null +++ b/lib/controller/mh/repair_process.dart @@ -0,0 +1,18 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'repair_process.g.dart'; + +@JsonSerializable() +class RepairProcessModel { + String? status; //审核状态 + DateTime? create_time; //审核时间 + String? desc; //审核意见 + int? record_id; //归属记录 + + int? deal_user; //处理人 + + RepairProcessModel(); + static RepairProcessModel fromJson(Map json) => + _$RepairProcessModelFromJson(json); + Map toJson() => _$RepairProcessModelToJson(this); +} diff --git a/lib/controller/mh/repair_process.g.dart b/lib/controller/mh/repair_process.g.dart new file mode 100644 index 0000000..d55573e --- /dev/null +++ b/lib/controller/mh/repair_process.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'repair_process.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +RepairProcessModel _$RepairProcessModelFromJson(Map json) => + RepairProcessModel() + ..status = json['status'] as String? + ..create_time = json['create_time'] == null + ? null + : DateTime.parse(json['create_time'] as String) + ..desc = json['desc'] as String? + ..record_id = (json['record_id'] as num?)?.toInt() + ..deal_user = (json['deal_user'] as num?)?.toInt(); + +Map _$RepairProcessModelToJson(RepairProcessModel instance) => + { + 'status': instance.status, + 'create_time': instance.create_time?.toIso8601String(), + 'desc': instance.desc, + 'record_id': instance.record_id, + 'deal_user': instance.deal_user, + }; diff --git a/lib/controller/mh/score_controller.dart b/lib/controller/mh/score_controller.dart new file mode 100644 index 0000000..f804a70 --- /dev/null +++ b/lib/controller/mh/score_controller.dart @@ -0,0 +1,20 @@ +import 'package:ef/ef.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'score_controller.g.dart'; + +@JsonSerializable() +class ScoreModel { + int? score = 5; + + ScoreModel(); + static ScoreModel fromJson(Map json) => + _$ScoreModelFromJson(json); + Map toJson() => _$ScoreModelToJson(this); +} + +class ScoreController extends GetControllerEx { + ScoreController() { + attr = GetModel(ScoreModel()).obs; + } +} diff --git a/lib/controller/mh/score_controller.g.dart b/lib/controller/mh/score_controller.g.dart new file mode 100644 index 0000000..fb345f6 --- /dev/null +++ b/lib/controller/mh/score_controller.g.dart @@ -0,0 +1,15 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'score_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ScoreModel _$ScoreModelFromJson(Map json) => + ScoreModel()..score = (json['score'] as num?)?.toInt(); + +Map _$ScoreModelToJson(ScoreModel instance) => + { + 'score': instance.score, + }; diff --git a/lib/controller/mh/sleeping_habit_controller.dart b/lib/controller/mh/sleeping_habit_controller.dart new file mode 100644 index 0000000..85e590b --- /dev/null +++ b/lib/controller/mh/sleeping_habit_controller.dart @@ -0,0 +1,94 @@ +import 'dart:convert'; + +import 'package:dio/src/form_data.dart' as formdata; +import 'package:ef/ef.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'sleeping_habit_controller.g.dart'; // 由json_serializable自动生成的部分 + +@JsonSerializable() +class SleepingHabitModel { + bool rxhxIsStart = false; + List rxhxWakeTime = [0, 0]; + bool rxhxIsBell = false; + bool rxhxIsAnMo = false; + int rxhxLocation = 0; + List rxhxWeeks = [0, 0, 0, 0, 0, 0, 0]; + + bool dhgyIsStart = false; + + bool smysIsStart = false; + List smysStartTime = [20, 0]; + List smysEndTime = [9, 0]; + + String get rxhxWakeTimeToString { + return '${rxhxWakeTime[0]}'.padLeft(2, "0") + + ":" + + '${rxhxWakeTime[1]}'.padLeft(2, "0"); + } + + String get smysStartTimeToString { + return '${smysStartTime[0]}'.padLeft(2, "0") + + ":" + + '${smysStartTime[1]}'.padLeft(2, "0"); + } + + String get smysEndTimeToString { + return '${smysEndTime[0]}'.padLeft(2, "0") + + ":" + + '${smysEndTime[1]}'.padLeft(2, "0"); + } + + SleepingHabitModel(); + + factory SleepingHabitModel.fromJson(Map json) { + try { + return _$SleepingHabitModelFromJson(json); + } catch (e) { + print("$e"); + // 在实际应用中,应该有更细致的异常处理策略和错误日志 + return SleepingHabitModel(); // 或者返回一个带有错误信息的特定AboutModel实例 + } + } + Map toJson() => _$SleepingHabitModelToJson(this); +} + +class SleepingHabitController extends GetControllerEx { + SleepingHabitController() { + attr = GetModel(SleepingHabitModel()).obs; + } + + // saveDataApi() { + // String mac = Get.find().model.deviceMain["mac"]; + // ApiService.request.post("/api/device/info/config", + // data: formdata.FormData.fromMap({ + // "mac": mac, + // "type": "sleepHabit", + // "data": jsonEncode(model.toJson()) + // })); + // } + + // loadDataApi({int time = 3}) { + // String mac = Get.find().model.deviceMain["mac"]; + + // ApiService.request + // .get("/api/device/info/config?type=sleepHabit&mac=${mac}") + // .then((d) async { + // if (d.data["data"] != null && d.data["data"]["data"] != null) { + // attr.value.model = + // SleepingHabitModel.fromJson(jsonDecode(d.data["data"]["data"])); + // print("load ${model.toJson()}"); + // } else { + // attr.value.model = SleepingHabitModel(); + // print("load error"); + // } + // updateAll(); + // }).catchError((d) { + // if (time > 0) { + // loadDataApi(time: time - 1); + // } else { + // attr.value.model = SleepingHabitModel(); + // } + // }); + // } +} diff --git a/lib/controller/mh/sleeping_habit_controller.g.dart b/lib/controller/mh/sleeping_habit_controller.g.dart new file mode 100644 index 0000000..2cde832 --- /dev/null +++ b/lib/controller/mh/sleeping_habit_controller.g.dart @@ -0,0 +1,40 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'sleeping_habit_controller.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +SleepingHabitModel _$SleepingHabitModelFromJson(Map json) => + SleepingHabitModel() + ..rxhxIsStart = json['rxhxIsStart'] as bool + ..rxhxWakeTime = (json['rxhxWakeTime'] as List) + .map((e) => (e as num).toInt()) + .toList() + ..rxhxIsBell = json['rxhxIsBell'] as bool + ..rxhxIsAnMo = json['rxhxIsAnMo'] as bool + ..rxhxLocation = (json['rxhxLocation'] as num).toInt() + ..rxhxWeeks = json['rxhxWeeks'] as List + ..dhgyIsStart = json['dhgyIsStart'] as bool + ..smysIsStart = json['smysIsStart'] as bool + ..smysStartTime = (json['smysStartTime'] as List) + .map((e) => (e as num).toInt()) + .toList() + ..smysEndTime = (json['smysEndTime'] as List) + .map((e) => (e as num).toInt()) + .toList(); + +Map _$SleepingHabitModelToJson(SleepingHabitModel instance) => + { + 'rxhxIsStart': instance.rxhxIsStart, + 'rxhxWakeTime': instance.rxhxWakeTime, + 'rxhxIsBell': instance.rxhxIsBell, + 'rxhxIsAnMo': instance.rxhxIsAnMo, + 'rxhxLocation': instance.rxhxLocation, + 'rxhxWeeks': instance.rxhxWeeks, + 'dhgyIsStart': instance.dhgyIsStart, + 'smysIsStart': instance.smysIsStart, + 'smysStartTime': instance.smysStartTime, + 'smysEndTime': instance.smysEndTime, + }; diff --git a/lib/controller/mh/user_data.dart b/lib/controller/mh/user_data.dart new file mode 100644 index 0000000..ea76499 --- /dev/null +++ b/lib/controller/mh/user_data.dart @@ -0,0 +1,22 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'user_data.g.dart'; + +@JsonSerializable() +class UserModel { + String? uid; + String? userName; + String? nickName; + String? tel; + String? avatar; + String? exp1; + String? exp2; + String? head; + String? tmpHead; + String? tmpNickName; + + UserModel(); + static UserModel fromJson(Map json) => + _$UserModelFromJson(json); + Map toJson() => _$UserModelToJson(this); +} diff --git a/lib/controller/mh/user_data.g.dart b/lib/controller/mh/user_data.g.dart new file mode 100644 index 0000000..89d1e4c --- /dev/null +++ b/lib/controller/mh/user_data.g.dart @@ -0,0 +1,32 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_data.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserModel _$UserModelFromJson(Map json) => UserModel() + ..uid = json['uid'] as String? + ..userName = json['userName'] as String? + ..nickName = json['nickName'] as String? + ..tel = json['tel'] as String? + ..avatar = json['avatar'] as String? + ..exp1 = json['exp1'] as String? + ..exp2 = json['exp2'] as String? + ..head = json['head'] as String? + ..tmpHead = json['tmpHead'] as String? + ..tmpNickName = json['tmpNickName'] as String?; + +Map _$UserModelToJson(UserModel instance) => { + 'uid': instance.uid, + 'userName': instance.userName, + 'nickName': instance.nickName, + 'tel': instance.tel, + 'avatar': instance.avatar, + 'exp1': instance.exp1, + 'exp2': instance.exp2, + 'head': instance.head, + 'tmpHead': instance.tmpHead, + 'tmpNickName': instance.tmpNickName, + }; diff --git a/lib/main.dart b/lib/main.dart index fa8d3d4..6f33c56 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -31,6 +31,20 @@ import 'package:vbvs_app/controller/message/common_message_setting_controller.da import 'package:vbvs_app/controller/message/message_controller.dart'; import 'package:vbvs_app/controller/message/message_review_controller.dart'; import 'package:vbvs_app/controller/message/message_setting_controller.dart'; +import 'package:vbvs_app/controller/mh/address_controller.dart'; +import 'package:vbvs_app/controller/mh/address_list_controller.dart'; +import 'package:vbvs_app/controller/mh/book_info_controller.dart'; +import 'package:vbvs_app/controller/mh/experience_store_list_page.dart'; +import 'package:vbvs_app/controller/mh/issue_controller.dart'; +import 'package:vbvs_app/controller/mh/issue_preview_controller.dart'; +import 'package:vbvs_app/controller/mh/message_controller.dart'; +import 'package:vbvs_app/controller/mh/muser_info_controller.dart'; +import 'package:vbvs_app/controller/mh/my_experience_list_controller.dart'; +import 'package:vbvs_app/controller/mh/people_info_controller.dart'; +import 'package:vbvs_app/controller/mh/repair_info_controller.dart'; +import 'package:vbvs_app/controller/mh/repair_list_controller.dart'; +import 'package:vbvs_app/controller/mh/score_controller.dart'; +import 'package:vbvs_app/controller/mh/sleeping_habit_controller.dart'; import 'package:vbvs_app/controller/person/person_controller.dart'; import 'package:vbvs_app/controller/repair/repair_controller.dart'; import 'package:vbvs_app/controller/setting/language/language_controller.dart'; @@ -43,7 +57,13 @@ import 'package:vbvs_app/controller/weather/weather_controller.dart'; import 'package:vbvs_app/language/AppLanguage.dart'; import 'package:vbvs_app/model/CustomThemeColor.dart'; import 'package:vbvs_app/model/user_data.dart'; +import 'package:vbvs_app/pages/device_control/BackMovement.dart'; +import 'package:vbvs_app/pages/device_control/MattressControl.dart'; +import 'package:vbvs_app/pages/device_control/people_info.dart'; +import 'package:vbvs_app/pages/main_bottom/component/main_page_b_bottom_change.dart'; +import 'package:vbvs_app/routers/mh_routers.dart'; +import 'controller/mh/apply_repair_controller.dart'; import 'controller/user_info_controller.dart'; import 'routers/routers.dart'; @@ -198,55 +218,87 @@ class MyApp extends StatelessWidget { MyApp({super.key}); final ThemeController themeController = Get.put(ThemeController()); - // This widget is the root of your application. - @override - Widget build(BuildContext context) { - themeController.changeTheme(CustomThemeColor.dark); - UserInfoController userInfoController = Get.find(); - return LayoutBuilder(builder: (contxt, cons) { - double width = cons.maxWidth; - double height = cons.maxHeight; - if (width < 1) { - return Container(); - } - FitTool.init(width < height ? width : height); - return GetMaterialApp( - translations: AppLanguage(), - // locale: const Locale("zh", "CN"), - locale: AppLanguage().currentLocale, // ✅ 动态读取当前语言 - fallbackLocale: const Locale("zh", "CN"), - localizationsDelegates: [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - SfGlobalLocalizations.delegate, - ], - supportedLocales: [ - const Locale('zh', 'CN'), // 中文 - const Locale('en', 'US'), // ⚠️ 添加你支持的语言 - ], - debugShowCheckedModeBanner: false, - title: '', - theme: themeController.currentTheme, - // home: const MyHomePage(title: '智慧眠花糖 Home Page'), - initialRoute: "/mianPageBottomChange", - onGenerateRoute: onGenerateRoute, - initialBinding: BindingsBuilder(() => [ - // Get.lazyPut(() => UserInfoController()), - Get.put(GlobalController()), + Widget buildmht(BuildContext context, BoxConstraints cons) { + return GetMaterialApp( + translations: AppLanguage(), + debugShowCheckedModeBanner: false, + title: '', + theme: themeController.currentTheme, + home: MainPageBBottomChange(), + onGenerateRoute: mhonGenerateRoute, + initialBinding: BindingsBuilder(() => [ + // Get.lazyPut(() => UserInfoController()), + Get.put(GlobalController()), + Get.lazyPut(() => ControlCardController()), + Get.lazyPut(() => RepairListController()), + Get.lazyPut(() => RepairInfoController()), + Get.lazyPut(() => MUserInfoController()), + Get.lazyPut(() => MhMessageController()), + Get.lazyPut(() => ScoreController()), + Get.lazyPut(() => ExperienceStoreListController()), + Get.lazyPut(() => BookExperienceListController()), + Get.lazyPut(() => IssuePreviewInfoController()), + Get.lazyPut(() => IssueListController()), + Get.lazyPut(() => ApplyRepairController()), + Get.lazyPut(() => SleepingHabitController()), + Get.lazyPut(() => PeopleInfoController()), + Get.lazyPut(() => MainPageController()), + Get.lazyPut(() => AddressListController()), + Get.lazyPut(() => AddressController()), + Get.lazyPut(() => BlueteethBindController()), + Get.lazyPut(() => BookInfoController()), + Get.lazyPut(() => PersonController()), + Get.lazyPut(() => CountdownController()), + Get.lazyPut(() => LoginController()), + Get.lazyPut(() => DeviceTypeController()), + Get.lazyPut(() => BodyDeviceController()), + Get.lazyPut(() => HomeController()), + Get.lazyPut(() => DeviceShareController()), + Get.lazyPut(() => DeviceShareListController()), + Get.lazyPut(() => DeviceCalibrationController()), + Get.lazyPut(() => RepairController()), + Get.lazyPut(() => PdfController()), + ])); + } + + Widget buildth(BuildContext context, BoxConstraints cons) { + return GetMaterialApp( + translations: AppLanguage(), + // locale: const Locale("zh", "CN"), + locale: AppLanguage().currentLocale, // ✅ 动态读取当前语言 + fallbackLocale: const Locale("zh", "CN"), + localizationsDelegates: [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + SfGlobalLocalizations.delegate, + ], + supportedLocales: [ + const Locale('zh', 'CN'), // 中文 + const Locale('en', 'US'), // ⚠️ 添加你支持的语言 + ], + debugShowCheckedModeBanner: false, + title: '', + theme: themeController.currentTheme, + // home: const MyHomePage(title: '智慧眠花糖 Home Page'), + initialRoute: "/mianPageBottomChange", + onGenerateRoute: onGenerateRoute, + initialBinding: BindingsBuilder(() => [ + // Get.lazyPut(() => UserInfoController()), + Get.put(GlobalController()), Get.put(WeatherModelController()), - Get.lazyPut(() => MainPageController()), - Get.lazyPut(() => BlueteethBindController()), - Get.lazyPut(() => PersonController()), - Get.lazyPut(() => CountdownController()), - Get.lazyPut(() => LoginController()), - Get.lazyPut(() => DeviceTypeController()), - Get.lazyPut(() => BodyDeviceController()), - Get.lazyPut(() => HomeController()), - Get.lazyPut(() => DeviceShareController()), - Get.lazyPut(() => DeviceShareListController()), - Get.lazyPut(() => DeviceCalibrationController()), - Get.lazyPut(() => RepairController()), + Get.lazyPut(() => MainPageController()), + Get.lazyPut(() => BlueteethBindController()), + Get.lazyPut(() => PersonController()), + Get.lazyPut(() => CountdownController()), + Get.lazyPut(() => LoginController()), + Get.lazyPut(() => DeviceTypeController()), + Get.lazyPut(() => BodyDeviceController()), + Get.lazyPut(() => HomeController()), + Get.lazyPut(() => DeviceShareController()), + Get.lazyPut(() => DeviceShareListController()), + Get.lazyPut(() => DeviceCalibrationController()), + Get.lazyPut(() => RepairController()), Get.lazyPut(() => UserPdfController()), Get.lazyPut(() => PrivacyPdfController()), Get.lazyPut(() => CalendarController()), @@ -254,7 +306,25 @@ class MyApp extends StatelessWidget { Get.lazyPut(() => MessageReviewController()), Get.lazyPut(() => MessageSettingController()), Get.lazyPut(() => CommonMessageSettingController()), - ])); + ])); + } + + final selectapp = "mht"; + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + var co = MediaQuery.sizeOf(context); + FitTool.init(co.height); + themeController.changeTheme(CustomThemeColor.dark); + return LayoutBuilder(builder: (contxt, cons) { + switch (selectapp) { + case "th": + return buildth(context, cons); + case "mht": + return buildmht(contxt, cons); + default: + return buildth(context, cons); + } }); } } diff --git a/lib/pages/common/bezier_bottom_navigation_bar.dart b/lib/pages/common/bezier_bottom_navigation_bar.dart new file mode 100644 index 0000000..77672be --- /dev/null +++ b/lib/pages/common/bezier_bottom_navigation_bar.dart @@ -0,0 +1,151 @@ +// bezier_bottom_navigation_bar.dart +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; + +class BezierBottomNavigationBar extends StatelessWidget { + final int selectedIndex; + final double animatedPosition; + final ValueChanged onTap; + final List path; + final List titles; + + const BezierBottomNavigationBar({ + Key? key, + required this.selectedIndex, + required this.animatedPosition, + required this.onTap, + required this.path, + required this.titles, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + final itemCount = path.length; + return SizedBox( + height: 130.rpx, + child: Stack( + children: [ + Positioned.fill( + child: CustomPaint( + size: Size(MediaQuery.of(context).size.width, 130.rpx), + painter: BezierPainter( + position: animatedPosition, + itemCount: itemCount, + ), + ), + ), + Row( + children: path.asMap().entries.map((entry) { + final i = entry.key; + final icon = entry.value; + return Expanded( + child: GestureDetector( + // 用 InkWell 替换 GestureDetector,支持点击反馈 + onTap: () => onTap(i), + // splashColor: Colors.transparent, // 可选:关闭 splash 效果 + // highlightColor: Colors.transparent, // 可选:关闭高亮效果 + child: SizedBox.expand( + child: Padding( + padding: EdgeInsets.only(top: 14.rpx), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(top: 11.rpx), + child: SvgPicture.asset(icon, + width: 42.rpx, + height: 42.rpx, + color: selectedIndex == i + ? Colors.white + : Color(0XFF929699)), + ), + SizedBox(height: 3), + Text( + titles[i], + style: TextStyle( + fontSize: 22.rpx, + color: selectedIndex == i + ? Colors.white + : Colors.grey.shade400, + ), + ), + ], + ), + ) + // 关键点:撑满 Expanded 区域 + + ), + ), + ); + }).toList(), + ), + ], + ), + ); + } +} + +class BezierPainter extends CustomPainter { + final double position; + final int itemCount; + + BezierPainter({required this.position, required this.itemCount}); + + @override + void paint(Canvas canvas, Size size) { + final paint = Paint() + ..color = Colors.white + ..style = PaintingStyle.stroke + ..strokeWidth = 1.0; + + final path = Path(); + final itemWidth = size.width / itemCount; + final curveWidth = itemWidth * 0.8; + double curveHeight = 8.5; + + final centerX = itemWidth * position + itemWidth / 2; + final left = centerX - curveWidth / 2; + final right = centerX + curveWidth / 2; + + // 控制点偏移比例(越小越平滑) + final controlOffsetX = curveWidth * 0.2; + final controlOffsetY = curveHeight * 0.9; + + // 起点 + path.moveTo(0, 0); + + // 到左侧前的一段直线 + path.lineTo(left, 0); + + // 凸起贝塞尔曲线 + path.cubicTo( + left + controlOffsetX, + 0, + centerX - controlOffsetX, + -controlOffsetY, + centerX, + -controlOffsetY, + ); + path.cubicTo( + centerX + controlOffsetX, + -controlOffsetY, + right - controlOffsetX, + 0, + right, + 0, + ); + + // 右边剩余直线 + path.lineTo(size.width, 0); + + // 向下平移,保证凸起在容器内部 + canvas.translate(0, controlOffsetY); + canvas.drawPath(path, paint); + } + + @override + bool shouldRepaint(covariant BezierPainter oldDelegate) { + return oldDelegate.position != position; + } +} diff --git a/lib/pages/device_control/BackMovement.dart b/lib/pages/device_control/BackMovement.dart new file mode 100644 index 0000000..1c6432f --- /dev/null +++ b/lib/pages/device_control/BackMovement.dart @@ -0,0 +1,228 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'dart:math' as math; +import 'package:vbvs_app/common/util/MyUtils.dart'; + +class BackMovementPage extends StatefulWidget { + const BackMovementPage({super.key}); + + @override + State createState() => _BackMovementPageState(); +} + +class _BackMovementPageState extends State { + double intensity = 4; + int selectedTime = 10; + + final List timeOptions = [10, 20, 30]; + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, bodysize) { + final double totalWidth = bodysize.maxWidth - 40.rpx * 2; // 减去左右 padding + final double spacing = 34.rpx; + final double buttonHeight = 101.rpx; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + child: Scaffold( + appBar: AppBar( + iconTheme: IconThemeData(color: themeController.currentColor.sc3), + backgroundColor: const Color(0xFF011C33), // 统一背景色 + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '背部律动', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + backgroundColor: const Color(0xFF011C33), + body: Padding( + padding: EdgeInsets.fromLTRB(0.rpx, 0, 0.rpx, 0), + child: Column( + // crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SingleChildScrollView( + child: Column( + children: [ + SizedBox(height: 30.rpx), + Text( + '力度调节', + style: TextStyle(color: Colors.grey, fontSize: 30.rpx), + ), + SizedBox(height: 148.rpx), + Text( + intensity.toInt().toString(), + style: + TextStyle(color: Colors.white, fontSize: 160.rpx), + ), + SizedBox(height: 41.rpx), + SizedBox( + height: 451.rpx, // 外部容器高度固定 + child: Stack( + children: [ + // 左边的 强/弱 文本 + Positioned( + left: 0, + top: 0, + bottom: 0, + child: SizedBox( + width: 60.rpx, + child: Column( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text('强', + style: TextStyle( + color: Colors.grey, + fontSize: 30.rpx)), + Text('弱', + style: TextStyle( + color: Colors.grey, + fontSize: 30.rpx)), + ], + ), + ), + ), + + // 右侧 slider,27.rpx 后居中 + Positioned( + left: 60.rpx - 27.rpx, // 60 是文字宽度,27 是间隔 + right: 0, + top: 0, + bottom: 0, + child: Center( + child: Transform.rotate( + angle: -math.pi / 2, + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: 451.rpx, + maxHeight: 451.rpx, + ), + child: SliderTheme( + data: SliderTheme.of(context).copyWith( + trackHeight: 60.rpx, + thumbShape: RoundSliderThumbShape( + enabledThumbRadius: 45.rpx), + overlayShape: + const RoundSliderOverlayShape( + overlayRadius: 20), + ), + child: Slider( + value: intensity, + min: 1, + max: 6, + divisions: 7, + activeColor: Colors.cyanAccent, + inactiveColor: Colors.blue.shade900, + onChanged: (value) { + setState(() { + intensity = value; + }); + }, + ), + ), + ), + ), + ), + ), + ], + ), + ), + SizedBox(height: 118.rpx), + Padding( + padding: EdgeInsets.only( + left: 47.rpx), // 👈 控制间隔大小(也可以是 all / symmetric) + child: Align( + alignment: Alignment.centerLeft, + child: Text( + '按摩定时', + style: TextStyle( + color: Colors.white70, fontSize: 30.rpx), + ), + ), + ), + SizedBox(height: 74.rpx), + Padding( + padding: EdgeInsets.fromLTRB(40.rpx, 0, 40.rpx, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: + List.generate(timeOptions.length, (index) { + final min = timeOptions[index]; + final isSelected = selectedTime == min; + return SizedBox( + height: buttonHeight, + child: ElevatedButton( + onPressed: () { + setState(() { + selectedTime = min; + }); + }, + style: ElevatedButton.styleFrom( + backgroundColor: isSelected + ? Colors.cyanAccent + : Colors.blue.shade900, + foregroundColor: isSelected + ? Colors.black + : Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + ), + child: Text('$min分钟'), + )); + }), + )), + ], + )), + Padding( + padding: EdgeInsets.fromLTRB(30.rpx, 0, 30.rpx, + 81.rpx), // 👈 控制上方间隔(也可以用 all / symmetric) + child: OutlinedButton( + onPressed: () { + setState(() { + intensity = 4; + selectedTime = 10; + }); + }, + style: OutlinedButton.styleFrom( + side: const BorderSide(color: Color(0XFF74DAE5)), + foregroundColor: Colors.cyanAccent, + minimumSize: Size(bodysize.maxWidth, 92.rpx), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + ), + child: const Text('恢复到默认设置'), + ), + ), + ], + ), + ), + ))); + }); + } +} diff --git a/lib/pages/device_control/ColorChangeOnTap.dart b/lib/pages/device_control/ColorChangeOnTap.dart new file mode 100644 index 0000000..8af73e6 --- /dev/null +++ b/lib/pages/device_control/ColorChangeOnTap.dart @@ -0,0 +1,94 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; + +class ColorChangeOnPress extends StatefulWidget { + final Color? initialColor; // 初始颜色 + final Color pressColor; // 按下时的颜色 + final bool shouldNavigate; // 是否需要跳转 + final String? routeName; // 路由名称 + final Widget child; // 子组件 + final String? toastMessage; // Toast 消息 + final ToastColor? toastColor; // Toast 颜色 + final double topLeft; // 左上圆角 + final double topRight; // 右上圆角 + final double bottomRight; // 右下圆角 + final double bottomLeft; // 左下圆角 + final VoidCallback? onTap; // 点击回调 + + const ColorChangeOnPress({ + Key? key, + this.initialColor = Colors.white, // 默认初始颜色为白色 + this.pressColor = Colors.grey, // 默认按下颜色为灰色 + this.shouldNavigate = false, // 默认不跳转 + this.routeName, + required this.child, + this.toastMessage, // Toast 消息 + this.toastColor, // Toast 颜色 + this.topLeft = 0.0, // 左上圆角 + this.topRight = 0.0, // 右上圆角 + this.bottomRight = 0.0, // 右下圆角 + this.bottomLeft = 0.0, // 左下圆角 + this.onTap, // 点击回调 + }) : super(key: key); + + @override + _ColorChangeOnPressState createState() => _ColorChangeOnPressState(); +} + +class _ColorChangeOnPressState extends State { + Color? _currentColor; + + @override + void initState() { + super.initState(); + _currentColor = widget.initialColor; // 初始化为初始颜色 + } + + void _handleTap() { + // 如果提供了 onTap 回调,调用它 + if (widget.onTap != null) { + widget.onTap!(); // 执行自定义逻辑 + } + + setState(() { + _currentColor = widget.pressColor; // 改变为按下的颜色 + }); + + // 显示 Toast 消息 + if (widget.toastMessage != null) { + showToast(widget.toastMessage!, color: widget.toastColor!); + } + + // 在0.5秒后恢复颜色 + Future.delayed(const Duration(milliseconds: 100), () { + setState(() { + _currentColor = widget.initialColor; // 恢复为初始颜色 + }); + + // 如果需要跳转,则执行路由跳转 + if (widget.shouldNavigate && widget.routeName != null) { + Get.toNamed(widget.routeName!); // 在颜色恢复后执行跳转 + } + }); + } + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: _currentColor, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(widget.topLeft), // 左上圆角 + topRight: Radius.circular(widget.topRight), // 右上圆角 + bottomRight: Radius.circular(widget.bottomRight), // 右下圆角 + bottomLeft: Radius.circular(widget.bottomLeft), // 左下圆角 + ), + ), + child: InkWell( + onTap: _handleTap, + child: widget.child, + ), + ); + } +} diff --git a/lib/pages/device_control/Empty.dart b/lib/pages/device_control/Empty.dart new file mode 100644 index 0000000..311a512 --- /dev/null +++ b/lib/pages/device_control/Empty.dart @@ -0,0 +1,54 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; + +class Empty extends StatefulWidget { + Empty({super.key}); + + @override + State createState() => _EmptyState(); +} + +class _EmptyState extends State { + String empty = ""; + bool closepage = false; + + @override + void initState() { + // TODO: implement initState + super.initState(); + Timer(const Duration(milliseconds: 1200), () { + if (empty.isEmpty && closepage == false) { + setState(() { + empty = "assets/images/new_empty.png"; + }); + } + }); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + closepage = true; + } + + @override + Widget build(BuildContext context) { + if (empty.isEmpty) { + return Container(); + } else { + return Container( + width: double.infinity, + margin: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.3), + alignment: Alignment.center, + child: Container( + width: 164.rpx, + height: 230.rpx, + child: Image.asset(empty), + ), + ); + } + } +} diff --git a/lib/pages/device_control/EmptyMessageWidget.dart b/lib/pages/device_control/EmptyMessageWidget.dart new file mode 100644 index 0000000..e62d9f4 --- /dev/null +++ b/lib/pages/device_control/EmptyMessageWidget.dart @@ -0,0 +1,37 @@ +import 'dart:async'; + +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; + +class EmptyMessageWidget extends StatelessWidget { + final String imagePath; + final double width; + final double height; + var empty = "".obs; + + EmptyMessageWidget({ + Key? key, + this.imagePath = 'assets/images/new_empty.png', // 默认图片路径 + double? width, // 默认宽度 + double? height, // 默认高度 + }) : width = 164.rpx, // 初始化宽度 + height = 230.rpx, // 初始化高度变为原来的三分之二 + super(key: key); + + @override + Widget build(BuildContext context) { + Timer(Duration(milliseconds: 5000), () { + empty.value = "assets/images/new_empty.png"; + }); + return Center( + child: Image.asset( + imagePath, + width: width, + height: height, + color: Colors.white, + ), + + ); + } +} diff --git a/lib/pages/device_control/HomeDeviceType.dart b/lib/pages/device_control/HomeDeviceType.dart new file mode 100644 index 0000000..91a66aa --- /dev/null +++ b/lib/pages/device_control/HomeDeviceType.dart @@ -0,0 +1,245 @@ +import 'dart:async'; + +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; + + +class HomeDeviceType extends StatefulWidget { + HomeDeviceType({super.key}); + @override + State createState() => _HomeDeviceTypeState(); +} + +class _HomeDeviceTypeState extends State { + bool isExec = false; + + @override + Widget build(BuildContext context) { + // if (isExec == false) { + // Timer(const Duration(milliseconds: 10), () { + // controller.getDeviceType(); + // }); + // isExec = true; + // } + return LayoutBuilder( + builder: (context, boxConstraints) => GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: const IconThemeData(color: Colors.white), + titleSpacing: 0, + // leading: returnIconButtom, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '添加设备', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtom, + ), + ], + ), + ), + + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 1.123, + // decoration: const BoxDecoration( + // image: DecorationImage( + // image: AssetImage("assets/images/new_background.png"), + // fit: BoxFit.cover, + // ), + // ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 48.rpx, 24.rpx, 0, 0), + child: Text( + '选择类型', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + ), + _buildControlCard(context), + ], + ), + ), + ), + ), + ), + )), + ); + } +} + +Widget _buildControlCard(BuildContext context) { + final List> deviceTypeList = [ + { + "id": 1, + "name": "智能床垫", + "desc": "SWES01 MHT01 SWES01 MHT01 SWES01 MHT01 ", + "img": "assets/images/device_bed.png", + "page": 1, + }, + { + "id": 2, + "name": "智能电动床", + "desc": "M300", + "img": "assets/images/electric_bed.png", + "page": 2, + }, + ]; + + return SizedBox( + // height: 221.rpx, + child: Padding( + padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx, top: 7.rpx), + child: Column( + children: List.generate( + deviceTypeList.length, + (index) => _buildDeviceItem(context, deviceTypeList[index]), + ), + ))); +} + +Widget _buildDeviceItem(BuildContext context, Map dtype) { + return Padding( + padding: EdgeInsetsDirectional.fromSTEB(0, 25.rpx, 0, 0), + child: InkWell( + onTap: () { + // Get.offAndToNamed("/bindDevice", arguments: dtype["id"]); + }, + child: Container( + height: 221.rpx, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).secondaryBackground, + borderRadius: BorderRadius.circular(6), + ), + constraints: BoxConstraints(minHeight: 221.rpx), + child: Row( + children: [ + Padding( + padding: EdgeInsetsDirectional.only(start: 59.rpx), + child: Container( + child: ClipRRect( + borderRadius: BorderRadius.circular(6.rpx), + child: Image.asset( + dtype["img"], + width: 180.rpx, + height: 109.rpx, + fit: BoxFit.cover, + ), + ), + ), + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.fromLTRB(0, 59.rpx, 0, 0), + child: Text( + dtype["name"], + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + fontSize: 30.rpx, + fontWeight: FontWeight.bold, + ), + ), + ), + SizedBox(height: 35.rpx), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 80.rpx, right: 80.rpx), + child: SizedBox( + height: 40.rpx, // 固定高度(两行高度 + 行间距) + child: LayoutBuilder( + builder: (context, constraints) { + final items = (dtype["desc"] as String) + .split(RegExp(r'\s+')) + .where((e) => e.trim().isNotEmpty) + .toList(); + final limitedItems = items.take(6).toList(); + + final isSingleLine = limitedItems.length <= 3; + + return Align( + alignment: isSingleLine + ? Alignment.topCenter + : Alignment.topLeft, + child: Wrap( + spacing: 20.rpx, + runSpacing: 10.rpx, + alignment: isSingleLine + ? WrapAlignment.center + : WrapAlignment.start, + children: limitedItems.map((item) { + return Container( + width: 75.rpx, + // height: 40.rpx, + alignment: Alignment.center, + child: Text( + item, + style: TextStyle( + fontSize: 20.rpx, + color: const Color(0xFF9AA0B3), + height: 1, + ), + // overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + ); + }).toList(), + ), + ); + }, + ), + ), + )) + ], + ), + ), + ], + ), + ), + ), + ); +} diff --git a/lib/pages/device_control/LanguagePage.dart b/lib/pages/device_control/LanguagePage.dart new file mode 100644 index 0000000..d51684b --- /dev/null +++ b/lib/pages/device_control/LanguagePage.dart @@ -0,0 +1,158 @@ +import 'package:ef/base/widget/flutterflow/FlutterFlowTheme.dart'; +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; + +class LanguagePage extends StatefulWidget { + @override + _LanguagePageState createState() => _LanguagePageState(); +} + +BoxConstraints? bodysize; +List languageList = [ + '简体中文', + '繁體中文', + 'English', +]; +final Map languageMap = { + '简体中文': 'zh_CN', + '繁體中文': 'zh_TW', + 'English': 'en_US', +}; + +class _LanguagePageState extends State { + RxBool checkboxValue = false.obs; + RxString? selectLanguage = ''.obs; + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () { + FocusScope.of(context).requestFocus(FocusNode()); + }, + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '切换语言', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Padding( + padding: EdgeInsets.only( + top: 30.rpx, left: 30.rpx, right: 30.rpx), + child: Container( + decoration: BoxDecoration( + color: Color(0XFF003058), + borderRadius: BorderRadius.circular(16.rpx)), + child: Padding( + padding: EdgeInsets.only( + left: 40.rpx, + top: 20.rpx, + bottom: 20.rpx, + right: 30.rpx), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListView.builder( + padding: EdgeInsets.zero, + shrinkWrap: true, + scrollDirection: Axis.vertical, + itemCount: languageList.length, + itemBuilder: + (BuildContext context, int index) { + return _buildItem( + context, index, languageList[index]); + }, + ), + Container(height: bodysize!.maxHeight * 0.12) + ], + ), + ))))), + )); + }); + } + + Widget _buildItem(BuildContext context, int index, String text) { + return Container( + // width: bodysize!.maxWidth * 1, + height: bodysize!.maxHeight * 0.055, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + text, + style: TextStyle(color: Colors.white, fontSize: 30.rpx), + ), + Theme( + data: ThemeData( + checkboxTheme: CheckboxThemeData( + visualDensity: VisualDensity.compact, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + ), + ), + unselectedWidgetColor: FlutterFlowTheme.of(context).alternate, + ), + child: Obx(() { + return Checkbox( + value: selectLanguage!.value == languageMap[text], + onChanged: (newValue) async { + if (newValue!) { + selectLanguage!.value = languageMap[ + text]!; // Set selectLanguage to the current text value + } else { + selectLanguage!.value = + ''; // Clear selection if unchecked + } + }, + shape: CircleBorder(), + side: BorderSide( + width: 2, + color: FlutterFlowTheme.of(context).alternate, + ), + activeColor: Color(0XFF6BFDAC), + checkColor: FlutterFlowTheme.of(context).info, + ); + })), + ], + ), + ); + } +} diff --git a/lib/pages/device_control/MattressControl.dart b/lib/pages/device_control/MattressControl.dart new file mode 100644 index 0000000..3eeda78 --- /dev/null +++ b/lib/pages/device_control/MattressControl.dart @@ -0,0 +1,352 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:flutter_switch/flutter_switch.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; + +class MattressControlPage extends StatefulWidget { + const MattressControlPage({super.key}); + + @override + State createState() => _MattressControlPageState(); +} + +class _MattressControlPageState extends State { + final controller = Get.put(ControlCardController()); + + int selectedIndex = 1; // 当前选中的tab索引 + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, bodySize) => GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: + AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + // 顶部返回 + 设备选择 + 蓝牙图标 + 设置按钮 + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + titleSpacing: 0, + elevation: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + SizedBox(width: 20.rpx), + returnIconButtomNew, + SizedBox(width: 26.rpx), + Container( + decoration: BoxDecoration( + color: Color(0xFF003058), + borderRadius: BorderRadius.circular(30.rpx), + ), + constraints: BoxConstraints( + minHeight: 60.rpx, + maxHeight: 60.rpx, + maxWidth: 260.rpx, + minWidth: 260.rpx), + padding: EdgeInsets.symmetric( + horizontal: 20.rpx), // 加左右边距 + child: DropdownButton( + value: 'Eason Chan', + underline: const SizedBox(), + dropdownColor: Colors.blueGrey, + iconEnabledColor: Colors.white, + style: const TextStyle(color: Colors.white), + isExpanded: true, + items: const [ + DropdownMenuItem( + value: 'Eason Chan', + child: Text('Eason Chan'), + ), + DropdownMenuItem( + value: 'Anna', + child: Text('Anna'), + ), + ], + onChanged: (_) {}, + ), + ), + ], + )), + actions: [ + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.transparent, + padding: EdgeInsets.only(right: 69.rpx), + onTap: () {}, + child: Icon( + Icons.bluetooth, + color: Colors.white, + size: 42.rpx, + ), + ), + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.transparent, + padding: EdgeInsets.only(right: 38.rpx), + onTap: () { + Get.toNamed('/bluetoothPage'); + }, + child: Icon(Icons.tune, + color: Colors.white, size: 42.rpx)) + ], + centerTitle: false, + ), + body: SafeArea( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _buildBedImageSection(context), + _buildModeSelector(context), + Expanded(child: _buildControlCards(context)), + ], + ), + ), + )))); + } + + // 床体图示 + Widget _buildBedImageSection(BuildContext context) { + return Padding( + padding: EdgeInsets.fromLTRB(0, 38.rpx, 0, 63.rpx), + child: Image.asset( + 'assets/images/bed_control.png', + width: MediaQuery.of(context).size.width * 0.7, // 你需要准备这个图像资源 + height: 193.rpx, + ), + ); + } + + Widget _buildModeSelector(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width - 60.rpx; // 左右各30 + final spacing = 20.0.rpx; + final thirdWidth = 215.rpx; // 三个卡片两个间距 + final tabCount = 3; + final tabWidth = screenWidth / tabCount; + final sideMargin = (tabWidth - thirdWidth) / 2; + + final labels = ['左', '全局', '右']; + + return Padding( + padding: EdgeInsets.symmetric(horizontal: 30.rpx), + child: Stack( + children: [ + Row( + children: List.generate(tabCount, (index) { + return Expanded( + child: GestureDetector( + onTap: () { + selectedIndex = index; + }, + child: _selectorTab( + labels[index], + isSelected: selectedIndex == index, + sideMargin: sideMargin, + ), + ), + ); + }), + ), + // 白线指示器 + Positioned( + bottom: 0, + left: selectedIndex * tabWidth + sideMargin, + child: AnimatedContainer( + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + width: thirdWidth, + height: 3.rpx, + color: Colors.white, + ), + ), + ], + ), + ); + } + + Widget _selectorTab(String label, + {bool isSelected = false, double sideMargin = 0}) { + return Container( + margin: EdgeInsets.symmetric(horizontal: sideMargin), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Center( + child: Text( + label, + style: TextStyle( + color: isSelected ? Colors.white : Colors.grey, + fontSize: 30.rpx, + fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, + ), + ), + ), + if (isSelected) SizedBox(height: 15.rpx), // 保留间距,避免文字和线重叠 + ], + ), + ); + } + + Widget _buildControlCards(BuildContext context) { + final spacing = 20.0.rpx; + + final List> allCards = [ + {'title': '一键助眠', 'time': '30:00'}, + {'title': '疲劳缓解', 'time': '20:00'}, + {'title': '全身放松', 'time': '20:00'}, + {'title': '背部律动', 'time': '10:00'}, + {'title': '腿部律动', 'time': '30:00'}, + {'title': '垂直律动', 'time': ''}, + {'title': '加热', 'time': '30:00'}, + {'title': '柔性唤醒', 'time': 'PM 08:00'}, + {'title': '记忆', 'time': ''}, + ]; + + final firstRow = allCards.sublist(0, 3); + final restCards = allCards.sublist(3); + + // 后续每行两个 + List>> chunkedRows = []; + for (int i = 0; i < restCards.length; i += 2) { + int end = (i + 2 < restCards.length) ? i + 2 : restCards.length; + chunkedRows.add(restCards.sublist(i, end)); + } + + return SingleChildScrollView( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 30.rpx, vertical: 30.rpx), + child: Column( + children: [ + // 第一行:三个卡片 + Row( + children: List.generate(firstRow.length * 2 - 1, (index) { + if (index.isOdd) { + return SizedBox(width: spacing); // 卡片间距 + } else { + final item = firstRow[index ~/ 2]; + return Expanded( + flex: 1, + child: _buildControlCard( + index ~/ 2, + item['title'], + item['time'], + // null, // 不再使用固定宽度 + ), + ); + } + }), + ), + SizedBox(height: spacing), + // 其余每行两个卡片 + ...chunkedRows.map((row) { + return Padding( + padding: EdgeInsets.only(bottom: spacing), + child: Row( + children: List.generate(row.length * 2 - 1, (index) { + if (index.isOdd) { + return SizedBox(width: spacing); + } else { + final item = row[index ~/ 2]; + return Expanded( + flex: 1, + child: _buildControlCard( + index ~/ 2, + item['title'], + item['time'], + // null, + ), + ); + } + }), + ), + ); + }).toList(), + ], + ), + ), + ); + } + + Widget _buildControlCard( + int index, + String title, + String time, + // double width, + ) { + final controller = Get.find(); + + return Container( + // width: width, + height: 241.rpx, + decoration: BoxDecoration( + color: const Color(0xFF003058), + borderRadius: BorderRadius.circular(8), + ), + padding: EdgeInsets.all(15.rpx), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + children: [ + SvgPicture.asset( + 'assets/img/icon/group.svg', + width: 60.rpx, + height: 60.rpx, + color: Colors.white, + ), + SizedBox(height: 22.rpx), + Text( + title, + style: TextStyle(color: Colors.white, fontSize: 30.rpx), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + time, + style: TextStyle( + color: const Color(0XFF929699), + fontSize: 26.rpx, + fontFamily: 'PingFang SC', + ), + ), + Obx(() => FlutterSwitch( + width: 71.rpx, + height: 36.rpx, + toggleSize: 30.rpx, + activeColor: const Color(0XFF6BFDAC), + inactiveColor: const Color(0XFF011D33), + value: controller.switchStates[index].value, + onToggle: (val) { + controller.switchStates[index].value = val; + }, + )), + ], + ), + ], + ), + ); + } +} + +class ControlCardController extends GetxController { + // 共9个卡片,每个卡片有自己的开关状态 + final List switchStates = List.generate(9, (index) => false.obs); +} diff --git a/lib/pages/device_control/address_list_page.dart b/lib/pages/device_control/address_list_page.dart new file mode 100644 index 0000000..cb40322 --- /dev/null +++ b/lib/pages/device_control/address_list_page.dart @@ -0,0 +1,206 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/color/appFontsize.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/controller/mh/address_list_controller.dart'; +import 'package:vbvs_app/pages/device_control/EmptyMessageWidget.dart'; +import 'package:vbvs_app/pages/device_control/address_module_widget.dart'; + +class AddressListPage extends GetView { + final scaffoldKey = GlobalKey(); + BoxConstraints? bodysize; + + // AddressListPage() { + // controller.getAddressList(); + // } + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: Colors.white), + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '地址管理', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + body: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Obx(() { + if (controller.model.addressList!.isEmpty) { + // 如果地址列表为空,显示 EmptyMessageWidget + return Expanded( + child: EmptyMessageWidget(), + ); + } else { + // 如果地址列表不为空,显示地址列表 + return Expanded( + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + decoration: BoxDecoration( + color: Color(0xFFF6F6F6), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: AlignmentDirectional(-1, 0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 31, 27, 0, 26), + child: Text( + '我的地址', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + fontSize: AppFontsize.title_size, + letterSpacing: 0, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + Expanded( + child: Obx(() => ListView( + shrinkWrap: true, + scrollDirection: Axis.vertical, + children: (controller.model.addressList! + .asMap() + .entries + .map((e) => AddressModuleWidget( + index: e.key, + addressListController: + controller, + )) + .toList() as List) + .divide(const SizedBox(height: 10)) + .addToEnd(const SizedBox( + height: AppConstants + .list_end_height)), + )), + ), + ], + ), + ), + ); + } + }), + Align( + alignment: AlignmentDirectional(0, 1), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(15, 15, 15, + AppConstants.page_button_bottom_padding), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 0.056, + decoration: BoxDecoration( + // color: Color(0xFFF6F6F6), + border: + Border.all(width: 0, color: Color(0XFF85F5FF)), + borderRadius: BorderRadius.circular(12), + ), + child: TextButton( + onPressed: () { + controller.model.address = {'isChecked': false}; + controller.model.type = 1; + Get.toNamed("/editAddressPage"); + }, + style: TextButton.styleFrom( + backgroundColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + padding: + EdgeInsets.symmetric(horizontal: 24), // 按钮内边距 + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Baseline( + baselineType: TextBaseline.alphabetic, + baseline: AppFontsize.normal_text_size * + 1.6, // 调整基线位置 + child: Text( + '+', + style: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF85F5FF), + fontSize: + AppFontsize.normal_text_size + + 12, // 让加号比文字稍大 + letterSpacing: 0, + ), + ), + ), + SizedBox(width: 10), // 加号和文字间距 + Text( + '添加新地址', + style: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF85F5FF), + fontSize: AppFontsize.normal_text_size, + letterSpacing: 0, + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + ), + )); + }); + } +} diff --git a/lib/pages/device_control/address_module_widget.dart b/lib/pages/device_control/address_module_widget.dart new file mode 100644 index 0000000..462bf62 --- /dev/null +++ b/lib/pages/device_control/address_module_widget.dart @@ -0,0 +1,264 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; +import 'package:vbvs_app/controller/mh/address_list_controller.dart'; + +import '../../common/color/appFontsize.dart'; + +class AddressModuleWidget extends GetView { + final int index; + final AddressListController addressListController; + + AddressModuleWidget({ + required this.index, + required this.addressListController, + }) {} + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: SlidableAutoCloseBehavior( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(15, 0, 15, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + constraints: BoxConstraints( + minHeight: 100, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + ), + child: Slidable( + endActionPane: ActionPane( + extentRatio: 0.26, + motion: ScrollMotion(), + children: [ + Expanded( + child: InkWell( + onTap: () async { + // await addressListController.deleteAddress( + // addressListController.model.addressList[index] + // ['id']); + // addressListController.model.addressList.removeAt(index); + + // addressListController.updateAll(); + }, + child: Container( + margin: EdgeInsets.only(left: 30), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.red, + ), + alignment: Alignment.center, + child: Icon( + Icons.delete, + color: Colors.white, + ), + ), + ), + ) + ], + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(15, 13, 15, 10), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.123, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.08, + constraints: BoxConstraints( + minHeight: 112, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: MediaQuery.sizeOf(context).width * 0.7, + height: + MediaQuery.sizeOf(context).height * 0.08, + constraints: BoxConstraints( + minHeight: 112, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: Align( + alignment: AlignmentDirectional(-1, 0), + child: Text( + [ + addressListController.model + .addressList[index]['province'], + addressListController.model + .addressList[index]['city'], + addressListController.model + .addressList[index]['county'], + addressListController.model + .addressList[index]['street'] + ] + .where((element) => + element != null && + element.isNotEmpty) + .join(' '), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF333333), + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + ), + ), + ), + ), + Flexible( + child: Align( + alignment: AlignmentDirectional(-1, 0), + child: Text( + addressListController + .model + .addressList[index] + ['detail'] + ?.isEmpty ?? + true + ? '无详细地址' + : addressListController.model + .addressList[index]['detail'], + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF333333), + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + ), + ), + ), + ), + Flexible( + child: Align( + alignment: AlignmentDirectional(-1, 0), + child: Text( + '${addressListController.model.addressList[index]['name']} ' + + '${addressListController.model.addressList[index]['phone']} ', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF333333), + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + ), + ), + ), + ), + ].divide(SizedBox(height: 5)), + ), + ), + Align( + alignment: AlignmentDirectional(1, -1), + child: Theme( + data: ThemeData( + checkboxTheme: CheckboxThemeData( + visualDensity: VisualDensity.compact, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(64), + ), + ), + unselectedWidgetColor: Color(0xFFD3D3D3), + ), + child: Obx(() { + return Checkbox( + value: addressListController + .model.addressList[index] + ['isChecked'] ?? + false, + onChanged: (newValue) async { + // if (newValue == true) { + // for (var i = 0; + // i < + // addressListController + // .model.addressList.length; + // i++) { + // addressListController + // .model.addressList[i] + // ['isChecked'] = false; + // } + // addressListController + // .model.addressList[index] + // ['isChecked'] = newValue; + // addressListController.updateDefault( + // addressListController + // .model.addressList[index]); + // } + // addressListController.updateAll(); + }, + side: BorderSide( + width: 1.5, + color: FlutterFlowTheme.of(context) + .secondaryText, + ), + activeColor: const Color(0xFFd3b684), + checkColor: + FlutterFlowTheme.of(context).info, + ); + }), + ), + ) + ], + ), + ), + ), + Align( + alignment: AlignmentDirectional(1, 0), + child: InkWell( + onTap: () { + addressListController.model.address = + addressListController.model.addressList[index]; + addressListController.model.type = 2; + Get.toNamed("/editAddressPage"); + }, + child: Container( + width: 100, + height: MediaQuery.sizeOf(context).height * 0.03, + child: Align( + alignment: AlignmentDirectional(1, 0), + child: Text( + '编辑', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: AppFontsize.small_text_size, + letterSpacing: 0, + ), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/device_control/app_map_location.dart b/lib/pages/device_control/app_map_location.dart new file mode 100644 index 0000000..93a38ac --- /dev/null +++ b/lib/pages/device_control/app_map_location.dart @@ -0,0 +1,46 @@ +// import 'package:map_launcher/map_launcher.dart'; + +// class AppMapLocation { +// static List availableMaps = []; +// static List availableMapsToNames = []; + +// static Future checkInstalledApps() async { +// availableMaps = await MapLauncher.installedMaps; +// availableMapsToNames = availableMaps.map((AvailableMap m) { +// String v = ""; +// switch (m.mapType) { +// case MapType.baidu: +// v = '百度地图'; +// break; +// case MapType.tencent: +// v = '腾讯地图'; +// break; +// case MapType.amap: +// v = '高德地图'; +// break; +// case MapType.apple: +// v = 'Apple地图'; +// break; +// case MapType.google: +// v = 'Google地图'; +// break; +// case MapType.googleGo: +// v = 'Google地图Go'; +// break; +// case MapType.petal: +// v = 'Petal地图'; +// break; +// default: +// v = m.mapName; +// } +// return v; +// }).toList(); +// } + +// static void launchMap(index, title, double latitude, double longitude) async { +// await availableMaps[index].showMarker( +// coords: Coords(latitude, longitude), +// title: title, +// ); +// } +// } diff --git a/lib/pages/device_control/apply_repair_page.dart b/lib/pages/device_control/apply_repair_page.dart new file mode 100644 index 0000000..b110517 --- /dev/null +++ b/lib/pages/device_control/apply_repair_page.dart @@ -0,0 +1,1936 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/color/appFontsize.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/img/img_default_widget.dart'; +import 'package:vbvs_app/component/img/img_preview_widget.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; +import 'package:vbvs_app/controller/mh/apply_repair_controller.dart'; + +class ApplyRepairPage extends GetView { + final scaffoldKey = GlobalKey(); + BoxConstraints? bodysize; + + // ApplyRepairPage() { + // controller.attr.value.listenlists.clear(); + // controller.getDeviceList(); + // controller.model.device_type = ""; + // controller.model.select_device = ""; + // controller.model.device_category = ""; + // controller.model.device_name = ""; + // controller.model.device_id = ""; + // } + + @override + Widget build(BuildContext context) { + var tmpcontroller = + FormFieldController(controller.model.select_device); + var typecontroller = + FormFieldController(controller.model.device_type); + controller.model.address; + List deviceTypeNames = ['床', '床垫']; + List deviceTypeIds = ['床', '床垫']; + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '申请报修', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + body: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + // TitleComponentWidget( + // titleName: '申请保修', + // ), + Flexible( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 30.rpx, 0, 30.rpx, 30.rpx), + child: Container( + width: bodysize!.maxWidth, + height: 1000, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0, 27.rpx, 0, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * + 0.247, + constraints: BoxConstraints( + minHeight: 500.rpx, + maxHeight: 500.rpx, + ), + decoration: BoxDecoration( + color: Color(0XFF003058), + borderRadius: + BorderRadius.circular(16.rpx), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 25.rpx, 27.rpx, 34.rpx, 0), + child: Container( + width: 100, + height: 100, + child: Container( + width: 100, + height: 100, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional( + 0, 0), + child: Container( + width: + MediaQuery.sizeOf(context) + .width, + height: 44, + child: Align( + alignment: + const AlignmentDirectional( + 0, -1), + child: Text( + '选择需要报修的设备', + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: 0, + fontSize: + AppFontsize + .title_size, + fontWeight: + FontWeight + .bold, + color: Colors + .white // 加粗文字 + ), + ), + ), + ), + ), + Expanded( + child: Column( + mainAxisSize: + MainAxisSize.max, + children: [ + Flexible( + child: Container( + width: + MediaQuery.sizeOf( + context) + .width, + height: 10, + constraints: + BoxConstraints( + minHeight: 60.rpx, + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Container( + width: 105.rpx, + height: MediaQuery + .sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minWidth: 60, + ), + child: Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '已绑设备', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize + .normal_text_size, + letterSpacing: + 0, + color: Colors + .white), + ), + ), + ), + Expanded( + child: + Container( + width: + 300, // 可以根据需要调整宽度 + height: + 56, // 可以根据需要调整高度 + decoration: + BoxDecoration( + borderRadius: + BorderRadius.circular(8), + color: + Colors.white, + ), + child: Obx( + () { + List> deviceOptions = controller + .model + .device_list! + .map((device) => { + 'id': device['id'].toString(), // 提取设备 ID + 'name': device['name'].toString(), // 提取设备名称 + }) + .toList(); + + // 提取 optionsLabel 和 optionsValue + List deviceNames = deviceOptions + .map((device) => device['name']!) // 用于显示的名称列表 + .toList(); + + List deviceIds = deviceOptions + .map((device) => device['id']!) // 用于匹配的 ID 列表 + .toList(); + + return FlutterFlowDropDown< + String>( + controller: + tmpcontroller, + options: + deviceIds, // 下拉菜单选项为设备的 ID + optionLabels: + deviceNames, // 下拉菜单显示的内容为设备名称 + onChanged: + (val) { + var selectedDevice = controller.model.device_list!.firstWhere((device) => device['id'].toString() == val); + controller.model.select_device = val; + controller.model.device_type = selectedDevice['type'] == 1 ? '床' : '床垫'; + controller.model.device_category = selectedDevice['deviceSeries']['name'] ?? '未知型号'; // 获取设备型号 + controller.model.device_id = selectedDevice['mac'] ?? '未知设备ID'; // 获取设备ID + controller.model.device_name = selectedDevice['name'] ?? '未知设备'; // 获取设备名称 + controller.updateAll(); + }, + width: + 300, + height: + 56, + searchHintTextStyle: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + searchTextStyle: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + textStyle: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + hintText: + '请选择绑定设备', + searchHintText: + '查找', + icon: + Icon( + Icons.keyboard_arrow_down_rounded, + color: FlutterFlowTheme.of(context).secondaryText, + size: 24, + ), + // fillColor: + // FlutterFlowTheme.of(context).secondaryBackground, + elevation: + 2, + borderColor: + FlutterFlowTheme.of(context).alternate, + borderWidth: + 0, + borderRadius: + 8, + margin: const EdgeInsetsDirectional.fromSTEB( + 10, + 4, + 10, + 4), + hidesUnderline: + true, + isOverButton: + false, + isSearchable: + false, + isMultiSelect: + false, + ); + }))), + ].divide(SizedBox( + width: 26.rpx)), + ), + ), + ), + Flexible( + child: Container( + width: + MediaQuery.sizeOf( + context) + .width, + height: 10, + constraints: + BoxConstraints( + minHeight: 60.rpx, + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Container( + width: 105.rpx, + height: MediaQuery + .sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minWidth: 60, + ), + child: Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '设备系列', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize + .normal_text_size, + letterSpacing: + 0, + color: Colors + .white), + ), + ), + ), + Expanded( + child: Container( + width: 100, + height: 100, + decoration: + BoxDecoration( + color: Colors + .white, + borderRadius: + BorderRadius + .circular(8), + ), + child: + Obx(() { + return TextFormField( + // autofocus: true, + controller: + controller + .onReDraw( + TextEditingController( + text: + controller.model.device_category ?? ""), + (value) => + { + value.text = + controller.model.device_category ?? "" + }, + ), + onChanged: + (value) { + controller + .model + .device_category = value; + }, + // initialValue: + // controller + // .model + // .device_category, + obscureText: + false, + decoration: + InputDecoration( + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + contentPadding: const EdgeInsetsDirectional + .fromSTEB( + 10, + 0, + 10, + 18), + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + ); + })), + ), + ].divide(SizedBox( + width: 26.rpx)), + ), + ), + ), + Flexible( + child: Container( + width: + MediaQuery.sizeOf( + context) + .width, + height: 10, + constraints: + BoxConstraints( + minHeight: 60.rpx, + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Container( + width: 105.rpx, + height: MediaQuery + .sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minWidth: 60, + ), + child: Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '产品型号', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize + .normal_text_size, + letterSpacing: + 0, + color: Colors + .white), + ), + ), + ), + Expanded( + child: Container( + width: 100, + height: 100, + decoration: + BoxDecoration( + color: Colors + .white, + borderRadius: + BorderRadius + .circular(8), + ), + child: + Obx(() { + return TextFormField( + // autofocus: true, + controller: + controller + .onReDraw( + TextEditingController( + text: + controller.model.device_category ?? ""), + (value) => + { + value.text = + controller.model.device_category ?? "" + }, + ), + onChanged: + (value) { + controller + .model + .device_category = value; + }, + // initialValue: + // controller + // .model + // .device_category, + obscureText: + false, + decoration: + InputDecoration( + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + contentPadding: const EdgeInsetsDirectional + .fromSTEB( + 10, + 0, + 10, + 18), + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + ); + })), + ), + ].divide(SizedBox( + width: 26.rpx)), + ), + ), + ), + Flexible( + child: Container( + width: + MediaQuery.sizeOf( + context) + .width, + height: 10, + constraints: + BoxConstraints( + minHeight: 60.rpx, + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Container( + width: 105.rpx, + height: MediaQuery + .sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minWidth: 60, + ), + child: Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '序列号', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize + .normal_text_size, + letterSpacing: + 0, + color: Colors + .white), + ), + ), + ), + Expanded( + child: Container( + width: 100, + height: 100, + decoration: + BoxDecoration( + color: const Color( + 0xFFF3F5F6), + borderRadius: + BorderRadius + .circular(8), + ), + child: + Obx(() { + return TextFormField( + // autofocus: true, + controller: + controller + .onReDraw( + TextEditingController( + text: + controller.model.device_id ?? ""), + (value) => + { + value.text = + controller.model.device_id ?? "" + }, + ), + onChanged: + (value) { + controller + .model + .device_id = value; + }, + // initialValue: + // controller + // .model + // .device_id, + obscureText: + false, + decoration: + InputDecoration( + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + contentPadding: const EdgeInsetsDirectional + .fromSTEB( + 10, + 0, + 10, + 18), + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + ); + })), + ), + ].divide(SizedBox( + width: 26.rpx)), + ), + ), + ), + ].divide( + SizedBox(height: 30.rpx)), + ), + ) + ], + ), + ), + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0, 26.rpx, 0, 0), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 0.17, + constraints: BoxConstraints( + minHeight: 345.rpx, + ), + decoration: BoxDecoration( + color: Color(0XFF003058), + borderRadius: + BorderRadius.circular(16.rpx), + ), + child: Obx(() { + return Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 0.17, + decoration: BoxDecoration( + color: Color(0XFF003058), + borderRadius: + BorderRadius.circular(16.rpx), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + if (controller.model.issue_img == + null || + controller + .model.issue_img!.isEmpty) + Flexible( + child: InkWell( + onTap: () { + // controller.uploadImg(); + }, + child: Container( + width: + MediaQuery.sizeOf(context) + .width, + height: + MediaQuery.sizeOf(context) + .height * + 0.186, + child: Column( + mainAxisSize: + MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .center, + children: [ + Flexible( + child: Align( + alignment: + const AlignmentDirectional( + 0, 0), + // child: Icon( + // Icons + // .linked_camera_outlined, + // color: + // Color(0xFF9EA4B7), + // size: 40, + // ), + child: Container( + width: 50, + height: 50, + decoration: + BoxDecoration( + image: + DecorationImage( + fit: BoxFit + .cover, + image: + Image.asset( + 'assets/images/camera.png', + ).image, + ), + ), + ), + ), + ), + Flexible( + child: Container( + width: 138, + height: 31, + decoration: + BoxDecoration( + borderRadius: + BorderRadius + .circular( + 50), + border: Border.all( + color: const Color( + 0xFF9EA4B7), + ), + ), + child: Align( + alignment: + const AlignmentDirectional( + 0, 0), + child: Text( + '上传设备故障照片', + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: const Color( + 0xFF9EA4B7), + fontSize: + AppFontsize + .normal_text_size, + letterSpacing: + 0, + ), + ), + ), + ), + ), + ], + ), + ), + )), + if (controller.model.issue_img != + null && + controller.model.issue_img! + .isNotEmpty) + Flexible( + child: Container( + width: + MediaQuery.sizeOf(context) + .width, + height: + MediaQuery.sizeOf(context) + .height * + 0.186, + constraints: + const BoxConstraints( + minHeight: 250, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of( + context) + .secondaryBackground, + ), + child: Column( + mainAxisSize: + MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional( + 1, 0), + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0, 7, 21, 7), + child: Container( + width: MediaQuery + .sizeOf( + context) + .width * + 0.2, + height: 21, + decoration: + BoxDecoration( + color: FlutterFlowTheme + .of(context) + .secondaryBackground, + ), + child: Container( + width: MediaQuery + .sizeOf( + context) + .width * + 0.2, + height: 21, + decoration: + BoxDecoration( + color: FlutterFlowTheme.of( + context) + .secondaryBackground, + ), + child: Row( + mainAxisSize: + MainAxisSize + .max, + mainAxisAlignment: + MainAxisAlignment + .end, + children: [ + Text( + // '2', + controller + .model + .issue_img! + .length + .toString(), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize.normal_text_size, + letterSpacing: + 0, + ), + ), + Text( + '/', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize.normal_text_size, + letterSpacing: + 0, + ), + ), + Text( + '3', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize.normal_text_size, + letterSpacing: + 0, + ), + ), + ], + ), + ), + ), + ), + ), + Flexible( + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0, 0, 21, 0), + child: Container( + width: MediaQuery + .sizeOf( + context) + .width, + height: MediaQuery + .sizeOf( + context) + .height * + 0.15, + constraints: + const BoxConstraints( + minHeight: 152, + ), + decoration: + BoxDecoration( + color: FlutterFlowTheme + .of(context) + .secondaryBackground, + ), + child: Container( + width: 100, + height: 100, + decoration: + BoxDecoration( + color: FlutterFlowTheme.of( + context) + .secondaryBackground, + ), + child: Obx(() => ListView( + shrinkWrap: true, + scrollDirection: Axis.horizontal, + children: getImage() + .divide(const SizedBox( + width: + 12, + )) + .addToStart(const SizedBox( + width: + 21, + ))))), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ); + }), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0, 25.rpx, 0, 0), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 0.17, + constraints: BoxConstraints( + minHeight: 345.rpx, + ), + decoration: BoxDecoration( + color: Color(0xFF003058), + borderRadius: + BorderRadius.circular(16.rpx), + ), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 0.19, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(16.rpx), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional( + 0, 0), + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB(0, 15, 0, 16), + child: Text( + '请描述一下您的问题', + style: + FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: Colors.white, + fontSize: 30.rpx, + letterSpacing: 0, + fontWeight: + FontWeight.w600, + ), + ), + ), + ), + Expanded( + child: Padding( + padding: EdgeInsetsDirectional + .fromSTEB(34.rpx, 0, 34.rpx, + 34.rpx), + child: Container( + width: + MediaQuery.sizeOf(context) + .width, + height: + MediaQuery.sizeOf(context) + .height * + 1, + constraints: BoxConstraints( + minHeight: 181.rpx, + ), + decoration: BoxDecoration( + color: + const Color(0xFFF3F5F6), + borderRadius: + BorderRadius.circular(8), + ), + child: TextFormField( + // autofocus: true, + onChanged: (value) { + controller.model.desc = + value; + }, + initialValue: + controller.model.desc, + obscureText: false, + + decoration: InputDecoration( + hintText: '问题描述(100个字以内)', + labelStyle: FlutterFlowTheme + .of(context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + color: Color( + 0XFF929699)), + hintStyle: FlutterFlowTheme + .of(context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + color: Color( + 0XFF929699)), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + // contentPadding: + // EdgeInsetsDirectional + // .fromSTEB(0, 0, 0, 12), + contentPadding: + const EdgeInsetsDirectional + .fromSTEB( + 10, 5, 10, 5), + ), + maxLines: 4, + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0, 26.rpx, 0, 0), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 0.17, + constraints: const BoxConstraints( + minHeight: 222, + ), + decoration: BoxDecoration( + color: Color(0XFF003058), + borderRadius: BorderRadius.circular(16), + ), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional( + 0, 0), + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB(0, 15, 0, 15), + child: Text( + '联系方式', + style: + FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: Colors.white, + fontSize: 30.rpx, + letterSpacing: 0, + fontWeight: + FontWeight.w600, + ), + ), + ), + ), + Expanded( + child: Padding( + padding: EdgeInsetsDirectional + .fromSTEB( + 25.rpx, 0, 34.rpx, 0), + child: Container( + width: + MediaQuery.sizeOf(context) + .width, + height: + MediaQuery.sizeOf(context) + .height * + 1, + child: Column( + mainAxisSize: + MainAxisSize.max, + children: [ + Flexible( + child: Container( + width: + MediaQuery.sizeOf( + context) + .width, + height: + MediaQuery.sizeOf( + context) + .height * + 0.038, + constraints: + BoxConstraints( + minHeight: 61.rpx, + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Container( + width: 105.rpx, + height: MediaQuery + .sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minWidth: 60, + ), + // decoration: + // BoxDecoration( + // color: FlutterFlowTheme.of( + // context) + // .secondaryBackground, + // ), + child: Row( + mainAxisSize: + MainAxisSize + .max, + children: [ + Text( + '联系人', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize + .small_text_size, + letterSpacing: + 0, + color: Colors + .white), + ), + ], + ), + ), + Expanded( + child: Container( + width: MediaQuery + .sizeOf( + context) + .width, + height: 100, + decoration: + BoxDecoration( + color: Colors + .white, + borderRadius: + BorderRadius + .circular( + 8), + ), + child: + TextFormField( + // autofocus: true, + onChanged: + (value) { + controller + .model + .apply_name = + value; + }, + initialValue: + controller + .model + .apply_name, + obscureText: + false, + decoration: + InputDecoration( + contentPadding: + const EdgeInsetsDirectional + .fromSTEB( + 10, + 10, + 10, + 14), + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + ), + ), + ), + ].divide( + const SizedBox( + width: 13)), + ), + ), + ), + Flexible( + child: Container( + width: + MediaQuery.sizeOf( + context) + .width, + height: + MediaQuery.sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minHeight: 31, + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Container( + width: 105.rpx, + height: MediaQuery + .sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minWidth: 60, + ), + child: Row( + mainAxisSize: + MainAxisSize + .max, + children: [ + Text( + '手机号码', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize + .small_text_size, + letterSpacing: + 0, + color: Colors + .white), + ), + ], + ), + ), + Expanded( + child: Container( + width: 100, + height: 100, + decoration: + BoxDecoration( + color: Colors + .white, + borderRadius: + BorderRadius + .circular( + 8), + ), + child: + TextFormField( + // autofocus: true, + onChanged: + (value) { + controller + .model + .tel = + value; + }, + initialValue: + controller + .model + .tel, + obscureText: + false, + decoration: + InputDecoration( + contentPadding: + const EdgeInsetsDirectional + .fromSTEB( + 10, + 10, + 10, + 14), + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + ), + ), + ), + ].divide( + const SizedBox( + width: 13)), + ), + ), + ), + ].divide(const SizedBox( + height: 15)), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 15, 15, 15, AppConstants.page_button_bottom_padding), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 0.056, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + borderRadius: BorderRadius.circular(16.rpx), + ), + child: CustomCard( + borderRadius: 10, + gradientDirection: GradientDirection.vertical, + onTap: () { + // print('Button pressed ...'); + // controller.submitRepair(context).then((msg) { + // if (msg.isEmpty) { + // MessageListController messageListController = + // Get.find(); + // messageListController.addMessage(); + // Get.to(() => ApplyRepairSuccessPage(), + // arguments: {'model': controller.model}); + // controller.model = + // ApplyRepairModel(); // 在 submitRepair 完成后执行 + // controller.updateAll(); + // } + // }).catchError((error) { + // // 错误处理 + // print('Error: $error'); + // }); + }, + colors: const [ + Color(0xFFFCFCFC), + Color(0xFFF8FAF9), + Color(0XFFECF6F3), + Color(0XFFD9F0E9), + Color(0xFFCEECE3) + ], + child: Container( + width: double.infinity, + height: 90.rpx, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + ), + child: Text( + "提交申请", + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: stringToColor("#011D33"), + letterSpacing: 0, + fontSize: 30.rpx, + ), + ), + ), + ) + + // Container( + // width: bodysize!.maxWidth, + // height: bodysize!.maxHeight * 0.056, + // decoration: BoxDecoration( + // color: FlutterFlowTheme.of(context) + // .secondaryBackground, + // borderRadius: BorderRadius.circular(16.rpx), + // ), + // child: FFButtonWidget( + // onPressed: () { + // print('Button pressed ...'); + // controller.submitRepair(context).then((msg) { + // if (msg.isEmpty) { + // MessageListController messageListController = + // Get.find(); + // messageListController.addMessage(); + // Get.to(() => ApplyRepairSuccessPage(), + // arguments: {'model': controller.model}); + // controller.model = + // ApplyRepairModel(); // 在 submitRepair 完成后执行 + // controller.updateAll(); + // } + // }).catchError((error) { + // // 错误处理 + // print('Error: $error'); + // }); + // }, + // text: '提交申请', + // options: FFButtonOptions( + // height: 40, + // padding: const EdgeInsetsDirectional.fromSTEB( + // 24, 0, 24, 0), + // iconPadding: const EdgeInsetsDirectional.fromSTEB( + // 0, 0, 0, 0), + // color: const Color(0xFFD3B684), + // textStyle: FlutterFlowTheme.of(context) + // .titleSmall + // .override( + // fontFamily: 'Readex Pro', + // color: Colors.white, + // fontSize: AppFontsize.normal_text_size, + // letterSpacing: 0, + // ), + // elevation: 0, + // borderSide: const BorderSide( + // color: Colors.transparent, + // width: 1, + // ), + // borderRadius: BorderRadius.circular(8), + // ), + // ), + // ), + ), + ), + ], + ), + ), + ), + )); + }); + } + + List getImage() { + List images = []; + controller.model.issue_img!.forEach((element) async { + images.add(ImgPreviewWidget( + imgUrl: element, + index: controller.model.issue_img!.indexOf(element), + applyRepairController: controller, + isDel: true, + )); + }); + if (images.length < controller.model.imagesLImit!) { + images.add(ImgPreviewDefaultWidget( + applyRepairController: controller, + )); + } + return images; + } + + List> _getDropdownItems() { + List options = [ + '智能床垫AH-2型', + '智能床垫BY-H型', + '智能床垫BY-C型', + // 可以在这里添加更多选项 + ]; + + return options.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(); + } +} diff --git a/lib/pages/device_control/bluetooth.dart b/lib/pages/device_control/bluetooth.dart new file mode 100644 index 0000000..7ccc51c --- /dev/null +++ b/lib/pages/device_control/bluetooth.dart @@ -0,0 +1,188 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; + +class BluetoothPage extends StatefulWidget { + BluetoothPage({super.key}); + + @override + State createState() => _BluetoothState(); +} + +BoxConstraints? bodysize; + +class _BluetoothState extends State { + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '设置', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Padding( + padding: EdgeInsets.fromLTRB(0.rpx, 115.rpx, 0.rpx, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('TomFayer', + style: TextStyle( + color: Colors.white, + fontSize: 40.rpx, + )), + SizedBox(width: 27.rpx), + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: const Color(0xFF055466), + padding: EdgeInsets.only(left: 0), + onTap: () { + Get.toNamed("/editBedPage"); + }, + child: Container( + width: 42.rpx, + height: 42.rpx, + child: SvgPicture.asset( + "assets/img/icon/bluetooth_edit.svg", + color: Colors.white, + ))) + ], + ), + + const SizedBox(height: 4), + Text('MAC:4645146546', + style: TextStyle( + color: Colors.white70, fontSize: 26.rpx)), + + const SizedBox(height: 16), + + // 蓝牙连接状态 + Column( + children: [ + Image.asset( + 'assets/images/active_bluetooth.png', + width: 42.rpx, + height: 42.rpx, + ), + SizedBox(height: 4), + Text('已连接', + style: TextStyle( + color: Colors.green, + fontSize: 26.rpx)), + ], + ), + ], + ), + + const SizedBox(height: 24), + + // 按钮列表 + Expanded( + child: ListView( + padding: EdgeInsets.symmetric(horizontal: 30.rpx), + children: [ + _buildMenuButton( + context, '详情', "/devicePeopleInfo"), + _buildMenuButton( + context, '人员资料', "/devicePeopleInfo"), + _buildMenuButton( + context, '房间选择', "/roomPickerPage"), + _buildMenuButton( + context, '设备校准', "/devicePeopleInfo"), + _buildMenuButton( + context, '体征传感器', "/devicePeopleInfo"), + _buildMenuButton( + context, 'WIFI配置', "/devicePeopleInfo"), + _buildMenuButton( + context, '睡眠习惯', "/sleepHabitPage"), + _buildMenuButton( + context, '分享设备', "/devicePeopleInfo"), + _buildMenuButton( + context, '解绑', "/devicePeopleInfo"), + ], + ), + ), + ], + ), + )), + ))); + }); + } + + Widget _buildMenuButton(BuildContext context, String title, String? path) { + return Padding( + padding: EdgeInsets.only(bottom: 19.rpx), // 将 margin 外移 + child: ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Color(0XFF055466), + padding: EdgeInsets.only(left: 0), + onTap: () { + if (path?.isNotEmpty == true) { + Get.toNamed(path!); + } + }, + child: Container( + height: MediaQuery.sizeOf(context).height * 0.0566, + decoration: BoxDecoration( + color: const Color(0xFF003058), + borderRadius: BorderRadius.circular(16.rpx), + ), + child: Center( + child: Text( + title, + style: const TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/device_control/book_date_widget.dart b/lib/pages/device_control/book_date_widget.dart new file mode 100644 index 0000000..f8335c3 --- /dev/null +++ b/lib/pages/device_control/book_date_widget.dart @@ -0,0 +1,87 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/controller/mh/book_info_controller.dart'; + +class BookDateWidget extends GetView { + // final String week; + // final String date; + + // const BookDateWidget({ + // super.key, + // String? week, + // String? date, + // }) : this.week = week ?? '周一', + // this.date = date ?? '07/10'; + + int index; + BookInfoController bookInfoController; + + BookDateWidget({required this.index, required this.bookInfoController}) {} + + @override + Widget build(BuildContext context) { + return InkWell(onTap: () { + // if(index == controller.model.datetimes_index) { + // return; + // } + // controller.model.datetimes_index = index; + // controller.time_periodChange(); + // controller.updateAll(); + }, child: Obx(() { + return Container( + width: 71.5, + height: 71.5, + constraints: BoxConstraints( + minHeight: 70, + ), + decoration: BoxDecoration( + // color: FlutterFlowTheme.of(context).secondaryBackground, + color: controller.model.datetimes_index == index + ? stringToColor('#D3B684') + : FlutterFlowTheme.of(context).secondaryBackground, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Flexible( + child: Text( + "${bookInfoController.model.datetimes![index]?['dayName']}", + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + color: controller.model.datetimes_index == index + ? stringToColor('#FFFFFF') + : stringToColor('#333333'), + ), + ), + ), + Flexible( + child: Text( + "${bookInfoController.model.datetimes![index]?['day']}", + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + color: controller.model.datetimes_index == index + ? stringToColor('#FFFFFF') + : stringToColor('#333333'), + ), + ), + ), + Flexible( + child: Icon( + Icons.keyboard_arrow_down_rounded, + color: controller.model.datetimes_index == index + ? stringToColor('#FFFFFF') + : stringToColor('#333333'), + size: 12, + ), + ), + ], + ), + ); + })); + } +} diff --git a/lib/pages/device_control/book_info_page.dart b/lib/pages/device_control/book_info_page.dart new file mode 100644 index 0000000..46c23e0 --- /dev/null +++ b/lib/pages/device_control/book_info_page.dart @@ -0,0 +1,796 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/appColors.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/color/appFontsize.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; +import 'package:vbvs_app/controller/mh/book_info_controller.dart'; +import 'package:vbvs_app/pages/common/selectDialog.dart'; +import 'package:vbvs_app/pages/device_control/book_date_widget.dart'; + +class BookInfoPage extends GetView { + final scaffoldKey = GlobalKey(); + Map data; + + BookInfoPage({required this.data}) { + // controller.getData(data["id"]); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + // key: scaffoldKey, + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: const IconThemeData(color: Colors.white), + titleSpacing: 0, + title: Container( + width: double.infinity, + height: 70.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '我要预约', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + actions: [], + centerTitle: false, + ), + body: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 1, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + // TitleComponentWidget( + // titleName: '我要预约', + // ), + Expanded( + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(28, 27, 28, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 1, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0, 0, 0, 10), + child: Container( + width: MediaQuery.sizeOf(context).width, + constraints: const BoxConstraints( + minHeight: 50, + ), + child: Container( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + '${data["name"]}', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + fontSize: + AppFontsize.title_size, + letterSpacing: 0, + fontWeight: FontWeight.w600, + color: Colors.white), + ), + Text( + '地址:${data["addressDetail"]}', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + color: Colors.white), + ), + ], + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0, 0, 0, 20), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: + MediaQuery.sizeOf(context).height * 0.01, + constraints: const BoxConstraints( + maxHeight: 1, + ), + decoration: const BoxDecoration( + color: Color(0xFF929699), + ), + ), + ), + Align( + alignment: const AlignmentDirectional(-1, 0), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0, 0, 0, 16), + child: Text( + '体验日期', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + fontSize: AppFontsize.title_size, + letterSpacing: 0, + fontWeight: FontWeight.w600, + color: Color(0xFF929699)), + ), + ), + ), + Obx(() { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: getBuildItems(context), + ); + }), + + // Obx(() => ListView( + // shrinkWrap: true, + // scrollDirection: Axis.horizontal, + // children: getBuildItems(context))), + // Padding( + // padding: + // EdgeInsetsDirectional.fromSTEB(0, 59, 0, 0), + // child: Row( + // mainAxisSize: MainAxisSize.max, + // mainAxisAlignment: + // MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // '体验时段', + // style: FlutterFlowTheme.of(context) + // .bodyMedium + // .override( + // fontFamily: 'Readex Pro', + // fontSize: AppFontsize.title_size, + // letterSpacing: 0, + // ), + // ), + // Row( + // mainAxisSize: MainAxisSize.max, + // children: [ + // Padding( + // padding: EdgeInsetsDirectional.fromSTEB( + // 0, 0, 17, 0), + // child: Text( + // '09:30', + // style: FlutterFlowTheme.of(context) + // .bodyMedium + // .override( + // fontFamily: 'Readex Pro', + // fontSize: + // AppFontsize.title_size, + // letterSpacing: 0, + // ), + // ), + // ), + // Icon( + // Icons.keyboard_arrow_down_sharp, + // color: FlutterFlowTheme.of(context) + // .secondaryText, + // size: 12, + // ), + // ], + // ), + // ], + // ), + // ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0, 59, 0, 0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '体验时段', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + fontSize: AppFontsize.title_size, + letterSpacing: 0, + color: Color(0xFF929699), + // 设置加粗 + ), + ), + Flexible(child: Obx(() { + return InkWell( + onTap: () { + showOneSelectionDialog(context, + arr: controller.model.time_period + .map((d) => + "${d['timeStr']} (${d['unBookAmount']}/${d['amount']})") + .toList()!, + checkIndex: controller.model + .select_time_index ?? + 0, checkChange: (index) { + controller.model.select_time_index = + index; + + controller.updateAll(); + }, title: '请选择时间'); + }, + child: Container( + width: 140, + height: 30, + child: Row( + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment + .center, // 确保图标和文本垂直居中 + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB(0, 3, 17, 0), + child: Text( + controller.model + .select_time_index != + null + ? "${controller.model.time_period?[controller.model.select_time_index!]?["timeStr"]}" + : '请选择时间', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + color: (controller + .model + .select_time_index == + null) + ? stringToColor( + '#D0D0D0') + : stringToColor( + '#333333')), + ), + ), + Icon( + Icons.keyboard_arrow_down_sharp, + color: + FlutterFlowTheme.of(context) + .secondaryText, + size: 16, + ), + ], + ), + ), + ); + })), + ], + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0, 25, 0, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: + MediaQuery.sizeOf(context).height * 0.03, + constraints: BoxConstraints( + minHeight: 76.rpx, + ), + decoration: const BoxDecoration(), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * + 0.02, + decoration: const BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '体验人员', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + fontSize: + AppFontsize.title_size, + letterSpacing: 0, + color: Color(0xFF929699), + // 设置加粗 + ), + ), + Flexible( + child: Align( + alignment: + const AlignmentDirectional( + 1, 0), + child: Container( + width: MediaQuery.sizeOf(context) + .width * + 0.3, + height: MediaQuery.sizeOf(context) + .height * + 1, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(0), + ), + child: Align( + alignment: + const AlignmentDirectional( + 1, 0), + child: TextFormField( + // autofocus: true, + controller: + TextEditingController( + text: controller.model + .userName ?? + ""), + onChanged: (d) { + controller.model.userName = + d; + }, + obscureText: false, + decoration: InputDecoration( + labelStyle: + FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + ), + hintText: '输入姓名', + hintStyle: FlutterFlowTheme + .of(context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + color: Color( + 0xFF929699)), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + contentPadding: + const EdgeInsetsDirectional + .fromSTEB( + 0, 0, 0, 12), + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + ), + textAlign: TextAlign.end, + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 0, 25, 0, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: + MediaQuery.sizeOf(context).height * 0.03, + constraints: BoxConstraints( + minHeight: 76.rpx, + ), + decoration: const BoxDecoration(), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * + 0.02, + decoration: const BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '手机号', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + fontSize: + AppFontsize.title_size, + letterSpacing: 0, + color: Color(0xFF929699), + // 设置加粗 + ), + ), + Flexible( + child: Align( + alignment: + const AlignmentDirectional( + 1, 0), + child: Container( + width: MediaQuery.sizeOf(context) + .width * + 0.3, + height: MediaQuery.sizeOf(context) + .height * + 1, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(0), + ), + child: Align( + alignment: + const AlignmentDirectional( + 1, 0), + child: TextFormField( + // autofocus: true, + controller: + TextEditingController( + text: controller.model + .userPhone ?? + ""), + onChanged: (d) { + controller.model.userPhone = + d; + }, + obscureText: false, + keyboardType: + TextInputType.phone, + decoration: InputDecoration( + labelStyle: + FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + ), + hintText: '输入手机号', + hintStyle: FlutterFlowTheme + .of(context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + color: Color( + 0xFF929699)), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular( + 8), + ), + contentPadding: + const EdgeInsetsDirectional + .fromSTEB( + 0, 0, 0, 12), + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: AppFontsize + .normal_text_size, + letterSpacing: 0, + ), + textAlign: TextAlign.end, + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ], + ), + )), + ), + ), + + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 15, 0, 15, AppConstants.page_button_bottom_padding), + child: CustomCard( + borderRadius: 10, + gradientDirection: GradientDirection.vertical, + onTap: () { + // if (controller.model.select_time_index == null) { + // showToast("请选择体验时间"); + // return; + // } + // if (controller.model.userName == null || + // controller.model.userName == "") { + // showToast("请输入姓名"); + // return; + // } + // if (controller.model.userPhone == null || + // controller.model.userPhone == "") { + // showToast("请输入手机号"); + // return; + // } + // if (MyUtils.isValidPhoneNumber( + // controller.model.userPhone!) == + // false) { + // showToast("请输入正确的手机号"); + // return; + // } + // controller.submitData(data["id"]).then((d) { + // if (d.data["status"] == 2) { + // d.data["addressDetail"] = data['addressDetail']; + // d.data["name"] = data["name"]; + // controller.messageAdd(d.data); + // Get.offAndToNamed("/bookSuccessPage", + // arguments: {"data": d.data}); + // } else { + // showToast("预约失败"); + // } + // }).catchError((d) { + // showToast("预约失败"); + // }); + Get.toNamed("/bookSuccessPage", arguments: { + "data": { + "id": "7fbfbd614ef5befa3d8a84730f666853", + "code": "10000114", + "orderSn": "2025051411302980610000114", + "userId": "09db8134288e8fb716c7acfdcca9f763", + "extUserId": null, + "deptId": 35, + "storeId": "962df2043ba06c99e6490616b37a60d4", + "customerId": "531ba6efe42d5e2cc3c8f219ebed4cee", + "idCard": null, + "realName": "江有龙", + "userPhone": "18956025450", + "province": "", + "city": "", + "district": "", + "addressDetail": "", + "bookType": 2, + "bookDateId": 104167, + "bookRoomNo": null, + "bookTimeStart": 1747281600000, + "bookTimeEnd": 1747303200000, + "payAmount": 0, + "transactionId": null, + "paid": 0, + "payTime": null, + "payType": null, + "status": 2, + "isVerify": false, + "verifyAdminId": null, + "verifyTime": null, + "giftAdminId": null, + "giftTime": null, + "createTime": 1747193430000, + "refundTime": null, + "isDel": false, + "audienceId": null, + "store": { + "id": "962df2043ba06c99e6490616b37a60d4", + "code": "55102", + "name": "合肥眠花糖共享会议华润大厦B座", + "deptId": 35, + "kingdeeId": "" + }, + "dateStr": "2025年05月15日周四", + "timeStr": "12:00~18:00", + "qrCode": "", + "payName": "未付款", + "statusName": "待体验", + "user": { + "id": "09db8134288e8fb716c7acfdcca9f763", + "nickName": "生陌", + "avatar": null, + "mobile": "18956025450" + }, + "verifyAdmin": null, + "giftAdmin": null, + "storeName": "合肥眠花糖共享会议华润大厦B座", + "storeAddress": null + }, + }); + }, + colors: const [ + Color(0xFFFCFCFC), + Color(0xFFF8FAF9), + Color(0XFFECF6F3), + Color(0XFFD9F0E9), + Color(0xFFCEECE3) + ], + child: Container( + width: double.infinity, + height: 90.rpx, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + ), + child: Text( + "提交预约", + style: + FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: stringToColor("#011D33"), + letterSpacing: 0, + fontSize: 30.rpx, + ), + ), + ), + )), + ], + ), + ), + ), + ), + ); + } + + List getBuildItems(BuildContext context) { + List images = []; + controller.model.datetimes!.forEach((element) async { + images.add(BookDateWidget( + index: controller.model.datetimes!.indexOf(element), + bookInfoController: controller, + )); + }); + return images; + } +} diff --git a/lib/pages/device_control/book_success_page.dart b/lib/pages/device_control/book_success_page.dart new file mode 100644 index 0000000..7c207e3 --- /dev/null +++ b/lib/pages/device_control/book_success_page.dart @@ -0,0 +1,210 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/appColors.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; + +class BookSuccessPage extends GetView { + final scaffoldKey = GlobalKey(); + BoxConstraints? bodysize; + Map data; + BookSuccessPage({required this.data}); + final infoList = [ + {"label": "预约编号:", "value": "54648614654646"}, + {"label": "预约人员:", "value": "张大大"}, + {"label": "手机号码:", "value": "139****5699"}, + {"label": "体验时间:", "value": "2024-02-15 07:30"}, + {"label": "预约门店:", "value": "SWES眠花糖杭州南星桥旗舰店"}, + {"label": "门店地址:", "value": "浙江省杭州市上城区飞云江路45号一层"}, + ]; + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + // key: scaffoldKey, + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: Colors.white), + titleSpacing: 0, + // leading: returnIconButtomAddCallback(() { + // controller.saveDataApi(); + // updateParm(isShowToast: false); + // }), + // leading: returnIconButtomNew, + title: Container( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '我要预约', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + + actions: [], + centerTitle: false, + ), + + body: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + width: bodysize!.maxWidth, + margin: EdgeInsets.only(top: 90.rpx), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + width: 148.rpx, + height: 148.rpx, + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Image.asset( + 'assets/images/success.png', + fit: BoxFit.contain, + color: Color(0xFF84F5FF), + ), + ), + Align( + alignment: const AlignmentDirectional(0, 0), + child: Text( + '预约成功!', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + fontSize: 30.rpx, + color: Colors.white, + letterSpacing: 0, + fontWeight: FontWeight.w600, + ), + ), + ), + ].divide(SizedBox(height: 30.rpx)), + ), + ), + Container( + margin: EdgeInsets.only( + left: 30.rpx, right: 30.rpx, top: 55.rpx), + width: bodysize!.maxWidth, + decoration: BoxDecoration( + color: Color(0xFF003058), + borderRadius: BorderRadius.circular(16.rpx), + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 20), // 上间距 + for (var item in infoList) + Container( + height: 60.rpx, + padding: EdgeInsets.symmetric(horizontal: 35), + alignment: Alignment.centerLeft, + child: Row( + children: [ + Text( + item['label']!, + style: TextStyle( + color: Color(0XFF929699), + fontSize: 26.rpx, + ), + ), + SizedBox(width: 35.rpx), + Text( + item['value']!, + style: TextStyle( + color: Colors.white, + fontSize: 26.rpx, + ), + ), + ], + ), + ), + + SizedBox(height: 60.rpx), // 空间隔断 + Padding( + padding: EdgeInsets.symmetric(horizontal: 35), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: 200.rpx, + height: 60.rpx, + child: ElevatedButton( + onPressed: () {}, + child: Text("关闭", + style: TextStyle( + color: Color(0XFF011D33), + fontSize: 26.rpx)), + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF84F5FF), + // minimumSize: Size(0, 60), + ), + ), + ), + SizedBox(width: 60.rpx), + SizedBox( + width: 200.rpx, + height: 60.rpx, + child: ElevatedButton( + onPressed: () {}, + child: Text("我的预约", + style: TextStyle( + color: Color(0XFF011D33), + fontSize: 26.rpx)), + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF84F5FF), + // minimumSize: Size(0, 60), + ), + ), + ) + ], + ), + ), + + SizedBox(height: 80), // 下间距 + ], + )), + ), + ], + ), + ), + ), + )); + }); + } +} diff --git a/lib/pages/device_control/delete_account.dart b/lib/pages/device_control/delete_account.dart new file mode 100644 index 0000000..84b7e29 --- /dev/null +++ b/lib/pages/device_control/delete_account.dart @@ -0,0 +1,328 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; + +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/color/appFontsize.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; + +class DeletedAccountPage extends GetView { + BoxConstraints? bodysize; + final scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: const IconThemeData(color: Colors.white), + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '注销账号', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + key: scaffoldKey, + backgroundColor: Colors.transparent, + body: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + decoration: const BoxDecoration(), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Container( + width: MediaQuery.sizeOf(context).width, + height: 100, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB( + 15, 33, 15, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + ), + child: Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 21, 0, 22, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Container( + width: 50, + height: 50, + child: Image.asset( + 'assets/images/delete_account.png', + fit: BoxFit.cover, + color: Color(0XFF84F5FF), + ), + ), + const Text( + "注销智慧眠花糖账号", + style: TextStyle( + fontSize: 20, // 设置字体大小 + color: Color(0xFFFFFFFF), + // decoration: TextDecoration.underline, // 添加下划线 + ), + ), + Container( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + RichText( + text: TextSpan( + text: "账号注销后,你将无法使用以下功能,", + style: TextStyle( + fontSize: AppFontsize + .normal_text_size, // 设置字体大小 + color: Color( + 0xFF9AA0B3), // 默认颜色 + ), + children: [ + TextSpan( + text: + "并且当前有绑定以及被分享的智能床、智能床垫等设备的账号不能注销", + style: TextStyle( + fontSize: AppFontsize + .normal_text_size, + color: const Color( + 0xFFFF7159), // 设置为#E45E91的颜色 + ), + ), + TextSpan( + text: + ",可先进行解绑后再进行注销操作。", + style: TextStyle( + fontSize: AppFontsize + .normal_text_size, + color: + Color(0xFF9AA0B3), + ), + ), + ], + ), + ), + const SizedBox( + height: 24, + ), + Text( + "无法控制智能床、智能床垫等设备", + style: TextStyle( + fontSize: AppFontsize + .title_size, // 设置字体大小 + color: + const Color(0xFFFFFFFF), + ), + ), + const SizedBox( + height: 6, + ), + Text( + "你将无法控制你的智能床、智能床垫等设备,以及与其相关的各种操作。", + style: TextStyle( + fontSize: AppFontsize + .normal_text_size, // 设置字体大小 + color: Color(0xFF9AA0B3), + ), + ), + const SizedBox( + height: 24, + ), + Text( + "无法查询睡眠报告和体征数据", + style: TextStyle( + fontSize: AppFontsize + .title_size, // 设置字体大小 + color: + const Color(0xFFFFFFFF), + ), + ), + const SizedBox( + height: 6, + ), + Text( + "注销账号后你将查询不到你以前的睡眠报告和实时数据。", + style: TextStyle( + fontSize: AppFontsize + .normal_text_size, // 设置字体大小 + color: Color(0xFF9AA0B3), + ), + ), + const SizedBox( + height: 24, + ), + Text( + "无法使用的其他功能", + style: TextStyle( + fontSize: AppFontsize + .title_size, // 设置字体大小 + color: + const Color(0xFFFFFFFF), + ), + ), + const SizedBox( + height: 6, + ), + Text( + "包含设备报修、门店体验预约等。", + style: TextStyle( + fontSize: AppFontsize + .normal_text_size, // 设置字体大小 + color: Color(0xFF9AA0B3), + ), + ), + ], + )), + ] + .divide( + const SizedBox(height: 24)) + .addToStart( + const SizedBox(height: 14)) + .addToEnd( + const SizedBox(height: 17)), + ), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 15, 0, 15, AppConstants.page_button_bottom_padding), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 0.056, + // decoration: BoxDecoration( + // color: + // FlutterFlowTheme.of(context).secondaryBackground, + // ), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 0.056, + decoration: BoxDecoration( + // color: FlutterFlowTheme.of(context) + // .secondaryBackground, + borderRadius: BorderRadius.circular(12), + ), + child: FFButtonWidget( + onPressed: () async { + // showCustomConfirmDialog(context, "是否确认注销?") + // .then((v) async { + // if (v != "confirm") { + // return; + // } + // LoginController loginController = Get.find(); + // UserInfoController userInfoController = + // Get.find(); + // var code = await loginController.deletedAccount(); + // if (code != null && code == 1) { + // final box = GetStorage(); + // box.remove('user'); + // box.remove('token'); + // userInfoController.model.token = null; + // userInfoController.model.user = null; + // userInfoController.model.login = 0; + // userInfoController.model.message = 0; + // GlobalController globalController = + // Get.find(); + // globalController.resetParmAll(); + // Get.offAllNamed("/loginPage"); + // } + // }); + }, + text: '注销账号', + options: FFButtonOptions( + height: 40, + padding: const EdgeInsetsDirectional.fromSTEB( + 24, 0, 24, 0), + iconPadding: const EdgeInsetsDirectional.fromSTEB( + 0, 0, 0, 0), + color: const Color(0xFFFF7159), + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: AppFontsize.normal_text_size, + letterSpacing: 0, + ), + elevation: 0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1, + ), + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ), + ), + ], + ), + ), + ), + )); + }); + } + + Future _copyToClipboard(String text) async { + await Clipboard.setData(ClipboardData(text: text)); + } +} diff --git a/lib/pages/device_control/device_people_info.dart b/lib/pages/device_control/device_people_info.dart new file mode 100644 index 0000000..99d2cdc --- /dev/null +++ b/lib/pages/device_control/device_people_info.dart @@ -0,0 +1,266 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; + +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/base/THFlutterFlowDropDown.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; + +class DevicePeopleInfo extends StatelessWidget { + DevicePeopleInfo({super.key}); + + get glController => Get.find(); + get bodyData => glController.model.mainDevicePeople; + + getInfoRow(context, String str) { + return Container( + width: double.infinity, + height: 60.rpx, + decoration: BoxDecoration(), + alignment: Alignment.centerLeft, + child: Text( + '$str', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: 26.rpx, + letterSpacing: 0, + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, boxConstraints) => GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: Colors.white), + titleSpacing: 0, + title: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '详情', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + actions: [], + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Obx( + () => Container( + padding: EdgeInsets.only( + left: 30.rpx, right: 30.rpx, top: 30.rpx), + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 1.123, + // decoration: BoxDecoration( + // // color: AppColors.bg_color, + // image: DecorationImage( + // image: AssetImage("assets/images/background.png"), + // fit: BoxFit.cover, + // ), + // ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + ClickableContainer( + backgroundColor: Color(0xFF003058), + highlightColor: Color(0xFF036060), + borderRadius: 16.rpx, + padding: EdgeInsets.fromLTRB( + 30.rpx, 20.rpx, 0, 20.rpx), + onTap: () {}, + child: Container( + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(16.rpx)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + alignment: Alignment.centerLeft, + child: Text( + '设备信息', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: 30.rpx, + ), + ), + ), + getInfoRow(context, + "名称:${glController.getDeviceGroupName2(glController.model.deviceMain)}"), + getInfoRow(context, + "房间:${glController.model.deviceMain["roomName"] ?? "-"}"), + getInfoRow(context, + "网络:${glController.model.deviceMain["status"] ?? "-"}"), + getInfoRow(context, + "MAC:${glController.model.deviceMain["mac"] ?? "-"}"), + ], + ), + )), + ...List.generate( + "${glController.model.deviceMain["bindMacB"]}" + .length > + 6 + ? 2 + : 1, (index) { + String location_ = ""; + if ("${glController.model.deviceMain["bindMacB"]}" + .length > + 6 && + (glController.model.mainDevicePeople[0] + ?["direction"] == + 1 || + glController.model.mainDevicePeople[1] + ?["direction"] == + 1)) { + location_ = + "${glController.model.mainDevicePeople[index]?["direction"] == 1 ? '左侧' : '右侧'}"; + } + // return Container( + // decoration: BoxDecoration( + // color: Color(0xFF003058), + // borderRadius: BorderRadius.circular(16.rpx), + // ), + // child: Padding( + // padding: EdgeInsets.symmetric( + // horizontal: 30.rpx), + // child: Column( + // children: [ + // Container( + // width: double.infinity, + // margin: EdgeInsets.only( + // bottom: 30.rpx, top: 50.rpx), + // decoration: BoxDecoration(), + // child: Text( + // '人员资料${index == 0 ? "A" : "B"}', + // style: FlutterFlowTheme.of(context) + // .bodyMedium + // .override( + // fontFamily: 'Readex Pro', + // color: Colors.white, + // fontSize: 32.rpx, + // letterSpacing: 0, + // ), + // ), + // ), + // if (location_.isNotEmpty) + // getInfoRow( + // context, "校准位置:$location_"), + // getInfoRow(context, + // "姓名:${bodyData[index]["name"] ?? "-"}"), + // getInfoRow(context, + // "性别:${bodyData[index]["gender"] == null ? "-" : (bodyData[index]["gender"] == 1 ? "男" : "女")}"), + // getInfoRow(context, + // "身高:${bodyData[index]["height"] == null ? "-" : "${bodyData[index]["height"]}cm"}"), + // getInfoRow(context, + // "体重:${bodyData[index]["weight"] == null ? "-" : "${bodyData[index]["weight"]}kg"}"), + // getInfoRow(context, + // "生日:${bodyData[index]["birthday"] == null ? "-" : (time_08_Formatter_pattern(bodyData[index]["birthday"], "yyyy年MM月dd日"))}"), + // getInfoRow(context, + // "电话:${bodyData[index]["tel"] ?? "-"}"), + // getInfoRow(context, + // "紧急联系人:${bodyData[index]["contact"] ?? "-"}"), + // ], + // ))); + + return ClickableContainer( + backgroundColor: Color(0xFF003058), + highlightColor: Color(0xFF036060), + borderRadius: 16.rpx, + padding: EdgeInsets.fromLTRB( + 30.rpx, 20.rpx, 30.rpx, 20.rpx), + onTap: () {}, + child: Column( + children: [ + Container( + width: double.infinity, + alignment: Alignment.centerLeft, + child: Text( + '人员资料${index == 0 ? "A" : "B"}', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: 32.rpx, + letterSpacing: 0, + ), + ), + ), + if (location_.isNotEmpty) + getInfoRow(context, "校准位置:$location_"), + getInfoRow(context, + "姓名:${bodyData[index]["name"] ?? "-"}"), + getInfoRow(context, + "性别:${bodyData[index]["gender"] == null ? "-" : (bodyData[index]["gender"] == 1 ? "男" : "女")}"), + getInfoRow(context, + "身高:${bodyData[index]["height"] == null ? "-" : "${bodyData[index]["height"]}cm"}"), + getInfoRow(context, + "体重:${bodyData[index]["weight"] == null ? "-" : "${bodyData[index]["weight"]}kg"}"), + getInfoRow(context, + "生日:${bodyData[index]["birthday"] == null ? "-" : (time_08_Formatter_pattern(bodyData[index]["birthday"], "yyyy年MM月dd日"))}"), + getInfoRow(context, + "电话:${bodyData[index]["tel"] ?? "-"}"), + getInfoRow(context, + "紧急联系人:${bodyData[index]["contact"] ?? "-"}"), + ], + ), + ); + }) + ].divide(SizedBox( + height: 25.rpx, + )), + ), + ), + ), + ), + ), + ), + )), + ); + } +} diff --git a/lib/pages/device_control/edit_address_page.dart b/lib/pages/device_control/edit_address_page.dart new file mode 100644 index 0000000..e8ce5d8 --- /dev/null +++ b/lib/pages/device_control/edit_address_page.dart @@ -0,0 +1,1333 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_city_picker/city_picker.dart'; +import 'package:flutter_city_picker/model/address.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; + +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/color/appFontsize.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; +import 'package:vbvs_app/controller/mh/address_controller.dart'; +import 'package:vbvs_app/controller/mh/address_list_controller.dart'; + +class EditAddressPage extends GetView + implements CityPickerListener { + final scaffoldKey = GlobalKey(); + BoxConstraints? bodysize; + + /// 0: 省 + /// 1: 市 + /// 2: 地区 + /// 3: 街道 + + String _addressProvince = "请选择省"; + String _addressCity = "请选择市"; + String _addressArea = "请选择地区"; + String _addressStreet = "请选择街道"; + List _selectProvince = []; + List _selectCity = []; + List _selectArea = []; + List _selectStreet = []; + + @override + Widget build(BuildContext context) { + AddressListController addressListController = Get.find(); + var address = + Map.from(addressListController.model.address); + controller.model.ischecked = address['isChecked']; + controller.model.all_address = getAddressDesc(address); + controller.model.detail = address['detail']; + controller.model.name = address['name']; + controller.model.phone = address['phone']; + controller.model.ischecked = address['isChecked']; + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + // key: scaffoldKey, + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: Colors.white), + titleSpacing: 0, + // leading: returnIconButtomAddCallback(() { + // controller.saveDataApi(); + // updateParm(isShowToast: false); + // }), + // leading: returnIconButtomNew, + title: Container( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '编辑地址', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + + actions: [], + centerTitle: false, + ), + body: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + child: Column( + // mainAxisSize: MainAxisSize.max, + children: [ + // TitleComponentWidget( + // titleName: '编辑收货地址', + // ), + + Expanded( + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB(0, 28.rpx, 0, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.907, + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 30.rpx), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + width: MediaQuery.sizeOf(context).width, + decoration: BoxDecoration( + color: Color(0xFF003058), + borderRadius: + BorderRadius.circular(16.rpx), + ), + child: Align( + alignment: + const AlignmentDirectional(0, -1), + child: Container( + width: MediaQuery.sizeOf(context).width, + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB(15, 0, 15, 0), + child: Container( + width: MediaQuery.sizeOf(context) + .width, + // decoration: BoxDecoration( + // color: Color(0XFF003058), + // ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + width: MediaQuery.sizeOf( + context) + .width, + height: MediaQuery.sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minHeight: 46, + ), + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular( + 16), + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Expanded( + child: Container( + width: MediaQuery + .sizeOf( + context) + .width * + 0.1, + height: 100, + decoration: + BoxDecoration(), + child: Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '地址信息', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: Colors + .white, + fontSize: + AppFontsize + .title_size, + letterSpacing: + 0, + fontWeight: + FontWeight + .w600, + ), + ), + ), + ), + ), + Container( + width: + MediaQuery.sizeOf( + context) + .width * + 0.17, + height: + MediaQuery.sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + maxWidth: 55, + ), + decoration: + BoxDecoration(), + child: Row( + mainAxisSize: + MainAxisSize + .max, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Align( + alignment: + const AlignmentDirectional( + 0, 0), + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0, + 3, + 0, + 0), + child: + Container( + width: 18, + height: 18, + decoration: + const BoxDecoration(), + child: + Align( + alignment: + const AlignmentDirectional( + 0, + 0), + child: Theme( + data: ThemeData( + checkboxTheme: + CheckboxThemeData( + visualDensity: VisualDensity.compact, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(64), + ), + ), + unselectedWidgetColor: + const Color(0xFFD3D3D3), + ), + child: Obx(() { + return Checkbox( + value: controller.model.ischecked, + onChanged: (newValue) async { + controller.model.ischecked = newValue; + controller.updateAll(); + }, + side: BorderSide( + width: 1.5, + color: FlutterFlowTheme.of(context).secondaryText, + ), + activeColor: const Color(0xFF84F5FF), + checkColor: Color(0xFF011D33), + ); + })), + ), + ), + ), + ), + Text( + '默认', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize + .normal_text_size, + letterSpacing: + 0, + color: Color( + 0XFF84F5FF)), + ), + ], + ), + ), + ].divide(const SizedBox( + width: 12)), + ), + ), + Container( + width: MediaQuery.sizeOf( + context) + .width, + height: MediaQuery.sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minHeight: 31, + ), + decoration: BoxDecoration(), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Container( + width: + MediaQuery.sizeOf( + context) + .width * + 0.17, + height: + MediaQuery.sizeOf( + context) + .height * + 0.038, + constraints: + BoxConstraints( + minWidth: + 105.rpx, + maxWidth: + 105.rpx), + decoration: + BoxDecoration(), + child: Row( + mainAxisSize: + MainAxisSize + .max, + children: [ + Text( + '收件人', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize + .normal_text_size, + letterSpacing: + 0, + color: Colors + .white), + ), + ], + ), + ), + Expanded( + child: Container( + width: 100, + height: 100, + decoration: + BoxDecoration( + color: + Colors.white, + borderRadius: + BorderRadius + .circular( + 8), + ), + child: + TextFormField( + // autofocus: true, + obscureText: + false, + onChanged: (val) { + controller.model + .name = val; + }, + initialValue: + address[ + 'name'], + decoration: + InputDecoration( + contentPadding: + const EdgeInsetsDirectional + .fromSTEB( + 10, + 0, + 10, + 18), + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular( + 8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular( + 8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular( + 8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular( + 8), + ), + ), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + ), + ), + ), + ].divide(const SizedBox( + width: 15)), + ), + ), + Container( + width: MediaQuery.sizeOf( + context) + .width, + height: MediaQuery.sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minHeight: 31, + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Container( + width: + MediaQuery.sizeOf( + context) + .width * + 0.17, + height: + MediaQuery.sizeOf( + context) + .height * + 0.038, + constraints: + BoxConstraints( + minWidth: + 105.rpx, + maxWidth: + 105.rpx), + decoration: + BoxDecoration(), + child: Row( + mainAxisSize: + MainAxisSize + .max, + children: [ + Text( + '手机号', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize + .normal_text_size, + letterSpacing: + 0, + color: Colors + .white, + ), + ), + ], + ), + ), + Expanded( + child: Container( + width: 100, + height: 100, + decoration: + BoxDecoration( + borderRadius: + BorderRadius + .circular( + 8), + color: + Colors.white, + ), + child: + TextFormField( + // autofocus: true, + onChanged: (val) { + controller.model + .phone = + val; + }, + obscureText: + false, + initialValue: + address[ + 'phone'], + decoration: + InputDecoration( + contentPadding: + const EdgeInsetsDirectional + .fromSTEB( + 10, + 0, + 10, + 18), + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular( + 8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular( + 8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular( + 8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular( + 8), + ), + ), + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + ), + ), + ), + ].divide(const SizedBox( + width: 15)), + ), + ), + Container( + width: MediaQuery.sizeOf( + context) + .width, + height: MediaQuery.sizeOf( + context) + .height * + 0.038, + constraints: + const BoxConstraints( + minHeight: 31, + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Container( + width: + MediaQuery.sizeOf( + context) + .width * + 0.17, + height: + MediaQuery.sizeOf( + context) + .height * + 0.038, + constraints: + BoxConstraints( + minWidth: + 105.rpx, + maxWidth: + 105.rpx), + child: Row( + mainAxisSize: + MainAxisSize + .max, + children: [ + InkWell( + // onTap: () { + // CityPicker.show( + // context: + // context, + // cityPickerListener: + // this, + // ); + // }, + child: Text( + '所在地区', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize.normal_text_size, + letterSpacing: + 0, + color: Colors + .white, + ), + ), + ), + ], + ), + ), + Expanded( + child: InkWell( + onTap: () { + CityPicker.show( + context: + context, + cityPickerListener: + this, + ); + }, + child: Container( + width: 100, + height: 100, + decoration: + BoxDecoration( + color: const Color( + 0xFFF3F5F6), + borderRadius: + BorderRadius + .circular( + 8), + ), + child: Obx(() { + return TextFormField( + enabled: + false, + controller: controller.onReDraw( + TextEditingController( + text: + controller.model.all_address), + (val) { + val.text = controller + .model + .all_address; + }), + // autofocus: true, + obscureText: + false, + decoration: InputDecoration( + contentPadding: const EdgeInsetsDirectional.fromSTEB(10, 0, 10, 18), + labelStyle: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + hintStyle: FlutterFlowTheme.of(context).labelMedium.override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + enabledBorder: UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + disabledBorder: UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 0, + ), + borderRadius: + BorderRadius.circular(8), + ), + focusedBorder: UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + errorBorder: UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + focusedErrorBorder: UnderlineInputBorder( + borderSide: + const BorderSide( + color: + Color(0x00000000), + width: + 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + suffixIcon: Transform.rotate( + angle: + 1.5708, // 90 度相当于 pi / 2 弧度 + child: + Icon( + Icons.arrow_forward_ios, + color: + FlutterFlowTheme.of(context).secondaryText, + size: + 12, + ), + )), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + ); + })), + ), + ), + ].divide(const SizedBox( + width: 15)), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0, 0, 0, 15), + child: Container( + width: MediaQuery.sizeOf( + context) + .width, + height: MediaQuery.sizeOf( + context) + .height * + 0.093, + constraints: + const BoxConstraints( + minHeight: 76, + ), + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional( + -1, -1), + child: Container( + width: MediaQuery + .sizeOf( + context) + .width * + 0.17, + height: MediaQuery + .sizeOf( + context) + .height * + 0.038, + constraints: + BoxConstraints( + minWidth: 105 + .rpx, + maxWidth: + 105.rpx), + child: Row( + mainAxisSize: + MainAxisSize + .max, + children: [ + Text( + '详细地址', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize + .normal_text_size, + letterSpacing: + 0, + color: Colors + .white), + ), + // Align( + // alignment: + // AlignmentDirectional( + // 0, + // -0.1), + // child: Icon( + // Icons + // .star_rate_sharp, + // color: Color( + // 0xFFE50012), + // size: 8, + // ), + // ), + ], + ), + ), + ), + Expanded( + child: Container( + width: 100, + height: MediaQuery + .sizeOf( + context) + .height * + 0.093, + decoration: + BoxDecoration( + color: const Color( + 0xFFF3F5F6), + borderRadius: + BorderRadius + .circular( + 8), + ), + child: + TextFormField( + // autofocus: true, + onChanged: + (val) { + controller + .model + .detail = + val; + }, + initialValue: + address[ + 'detail'], + maxLines: 2, + obscureText: + false, + decoration: + InputDecoration( + contentPadding: + const EdgeInsetsDirectional + .fromSTEB( + 10, + 10, + 10, + 10), + labelStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + hintStyle: FlutterFlowTheme.of( + context) + .labelMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + enabledBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular(8), + ), + focusedBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular(8), + ), + errorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular(8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: + const BorderSide( + color: Color( + 0x00000000), + width: 2, + ), + borderRadius: + BorderRadius + .circular(8), + ), + ), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + ), + ), + ), + ), + ].divide(const SizedBox( + width: 15)), + ), + ), + ), + ].divide( + const SizedBox(height: 15)), + ), + ), + ), + ), + ), + ), + ), + ], + ), + )), + ), + ), + ), + + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(15, 0, + 15, AppConstants.page_button_bottom_padding), + child: CustomCard( + borderRadius: 10, + gradientDirection: GradientDirection.vertical, + onTap: () { + // if (controller.model.all_address == null || + // controller.model.all_address!.isEmpty) { + // showToast("地址不能为空"); + // return; + // } + // if (controller.model.name == null || + // controller.model.name!.isEmpty) { + // showToast("名字不能为空"); + // return; + // } + // if (controller.model.detail == null || + // controller.model.detail!.isEmpty) { + // showToast("详细地址不能为空"); + // return; + // } + // if (controller.model.phone == null || + // controller.model.phone!.isEmpty) { + // showToast("手机号不能为空"); + // return; + // } + // if (!MyUtils.isValidPhoneNumber( + // controller.model.phone!)) { + // showToast("无效的手机号码"); + // return; + // } + // if (addressListController.model.type == 1) { + // await controller.addAddress(controller.model); + // } else { + // await controller.updateAddress( + // address, controller.model); + // } + // await addressListController.getAddressList(); + // Get.back(); + // controller.model = AddressModel(); + // controller.updateAll(); + }, + colors: const [ + Color(0xFFFCFCFC), + Color(0xFFF8FAF9), + Color(0XFFECF6F3), + Color(0XFFD9F0E9), + Color(0xFFCEECE3) + ], + child: Container( + width: double.infinity, + height: 90.rpx, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + ), + child: Text( + "保存", + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: stringToColor("#011D33"), + letterSpacing: 0, + fontSize: 30.rpx, + ), + ), + ), + ) + + // Container( + // width: bodysize!.maxWidth, + // height: bodysize!.maxHeight * 0.056, + // decoration: BoxDecoration( + // color: FlutterFlowTheme.of(context) + // .secondaryBackground, + // ), + // child: + + // Container( + // width: bodysize!.maxWidth, + // height: bodysize!.maxHeight * 0.056, + // decoration: BoxDecoration( + // color: FlutterFlowTheme.of(context) + // .secondaryBackground, + // borderRadius: BorderRadius.circular(12), + // ), + // child: FFButtonWidget( + // onPressed: () async { + // // if (controller.model.all_address == null || + // // controller.model.all_address!.isEmpty) { + // // showToast("地址不能为空"); + // // return; + // // } + // // if (controller.model.name == null || + // // controller.model.name!.isEmpty) { + // // showToast("名字不能为空"); + // // return; + // // } + // // if (controller.model.detail == null || + // // controller.model.detail!.isEmpty) { + // // showToast("详细地址不能为空"); + // // return; + // // } + // // if (controller.model.phone == null || + // // controller.model.phone!.isEmpty) { + // // showToast("手机号不能为空"); + // // return; + // // } + // // if (!MyUtils.isValidPhoneNumber( + // // controller.model.phone!)) { + // // showToast("无效的手机号码"); + // // return; + // // } + // // if (addressListController.model.type == 1) { + // // await controller.addAddress(controller.model); + // // } else { + // // await controller.updateAddress( + // // address, controller.model); + // // } + // // await addressListController.getAddressList(); + // // Get.back(); + // // controller.model = AddressModel(); + // // controller.updateAll(); + // }, + // text: '确定', + // options: FFButtonOptions( + // height: 40, + // padding: const EdgeInsetsDirectional.fromSTEB( + // 24, 0, 24, 0), + // iconPadding: + // const EdgeInsetsDirectional.fromSTEB( + // 0, 0, 0, 0), + // color: const Color(0xFFD3B684), + // textStyle: FlutterFlowTheme.of(context) + // .titleSmall + // .override( + // fontFamily: 'Readex Pro', + // color: Colors.white, + // fontSize: AppFontsize.normal_text_size, + // letterSpacing: 0, + // ), + // elevation: 0, + // borderSide: const BorderSide( + // color: Colors.transparent, + // width: 1, + // ), + // borderRadius: BorderRadius.circular(6), + // ), + // ), + // ), + // ), + ), + ], + ), + ), + ))); + }); + } + + @override + Future> onDataLoad( + int index, String code, String name) async { + debugPrint("onDataLoad ---> $index $name"); + + if (index == 0) { + await Future.delayed(const Duration(milliseconds: 200)); + return HttpUtils.getCityData("", index); + } else { + if (controller.model.currentType == 0) { + return Future.value([]); + } else if (controller.model.currentType == 1) { + if (index == 2) { + return Future.value([]); + } + return HttpUtils.getCityData(code, index); + } else if (controller.model.currentType == 2) { + if (index == 3) { + return Future.value([]); + } + return HttpUtils.getCityData(code, index); + } else { + return HttpUtils.getCityData(code, index); + } + } + } + + @override + void onFinish(List data) { + debugPrint("onFinish"); + String add = ""; + for (var node in data) { + add += "${node.name} "; + } + if (controller.model.currentType == 0) { + _addressProvince = add; + _selectProvince = data; + } else if (controller.model.currentType == 1) { + _addressCity = add; + _selectCity = data; + } else if (controller.model.currentType == 2) { + _addressArea = add; + _selectArea = data; + } else { + _addressStreet = add; + _selectStreet = data; + } + controller.model.all_address = add; + controller.model.addressList = data; + controller.updateAll(); + } + + String getAddressDesc(Map address) { + // 提取地址的各个字段 + String? province = address['province']; + String? city = address['city']; + String? area = address['county']; + String? street = address['street']; + + // 使用 where 过滤掉 null 或空字符串的值,并用空格连接有效的字段 + return [province, city, area, street] + .where((element) => element != null && element.isNotEmpty) + .join(' '); + } +} + +class HttpUtils { + static Future> getCityData(String code, int index) async { + final AddressController addressController = Get.find(); + addressController.model.currentType = 1; + + if (code.isEmpty) { + addressController.updateAll(); + return addressController.getData(level: 0); + } + addressController.model.currentType = index + 1; + //控制选择区域层级 1.省 2.市 3.区 4.街道 + if (addressController.model.currentType > 3) { + return []; + } + return addressController.getData(pid: int.parse(code)); + } +} diff --git a/lib/pages/device_control/edit_bed.dart b/lib/pages/device_control/edit_bed.dart new file mode 100644 index 0000000..367b83e --- /dev/null +++ b/lib/pages/device_control/edit_bed.dart @@ -0,0 +1,203 @@ +import 'package:ef/base/widget/flutterflow/FlutterFlowTheme.dart'; +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; + +class EditBedPage extends StatefulWidget { + const EditBedPage({Key? key}) : super(key: key); + @override + _EditBedPageState createState() => _EditBedPageState(); +} + +BoxConstraints? bodysize; +RxString _bedName = "".obs; + +class _EditBedPageState extends State { + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () { + FocusScope.of(context).requestFocus(FocusNode()); + }, + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '智能床名称', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Padding( + padding: EdgeInsets.only(top: 40.rpx), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: bodysize!.maxHeight * 1, + height: bodysize!.maxHeight * 0.335, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + child: + Image.asset('assets/images/bed_name.png'), + width: bodysize!.maxWidth * 0.69, + height: 193.rpx, + ), + Padding( + padding: + EdgeInsets.symmetric(horizontal: 60.rpx), + child: Container( + alignment: Alignment.center, + height: bodysize!.maxHeight * 0.076, + decoration: const BoxDecoration( + border: Border( + bottom: BorderSide( + color: Color(0xFF929699), + width: 0))), + child: TextFormField( + // autofocus: true, + obscureText: false, + onChanged: (val) { + // controller.model.name = val; + }, + textAlign: TextAlign.center, + initialValue: _bedName.value, + decoration: InputDecoration( + hintText: "请输入床的名称", + contentPadding: + const EdgeInsetsDirectional + .fromSTEB(10, 0, 10, 0), + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + fontSize: 36.rpx, // 设置输入文字大小 + color: Colors.white, // 设置输入文字颜色 + ), + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + color: Color(0xFF929699), + fontSize: 36.rpx, + ), + enabledBorder: UnderlineInputBorder( + borderSide: const BorderSide( + color: Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + focusedBorder: UnderlineInputBorder( + borderSide: const BorderSide( + color: Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + errorBorder: UnderlineInputBorder( + borderSide: const BorderSide( + color: Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + focusedErrorBorder: + UnderlineInputBorder( + borderSide: const BorderSide( + color: Color(0x00000000), + width: 2, + ), + borderRadius: + BorderRadius.circular(8), + ), + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + letterSpacing: 0, + ), + ), + )) + ], + ), + ), + Padding( + padding: EdgeInsets.only( + left: 30.rpx, right: 30.rpx, bottom: 85.rpx), + child: CustomCard( + borderRadius: 10, + gradientDirection: GradientDirection.vertical, + onTap: () {}, + colors: const [ + Color(0xFFFCFCFC), + Color(0xFFF8FAF9), + Color(0XFFECF6F3), + Color(0XFFD9F0E9), + Color(0xFFCEECE3) + ], + child: Container( + width: double.infinity, + height: 90.rpx, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + ), + child: Text("完成", + style: TextStyle( + color: const Color(0xFF003058), + fontSize: 26.rpx)), + ), + )) + ], + ))), + ), + ), + ); + }); + } +} diff --git a/lib/pages/device_control/edit_userinfo_page.dart b/lib/pages/device_control/edit_userinfo_page.dart new file mode 100644 index 0000000..a9925cc --- /dev/null +++ b/lib/pages/device_control/edit_userinfo_page.dart @@ -0,0 +1,205 @@ +import 'package:ef/base/widget/flutterflow/FlutterFlowTheme.dart'; +import 'package:flutter/material.dart'; + +import 'package:get/get.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; + +import '../../controller/mh/muser_info_controller.dart'; + +class EditUserInfoPage extends GetView { + final scaffoldKey = GlobalKey(); + + // EditUserInfoPage() { + // UserInfoController controller = Get.find(); + // controller.model.user!.tmpHead = controller.model.user!.head; + // } + + @override + Widget build(BuildContext context) { + // UserInfoController controller = Get.find(); + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + key: scaffoldKey, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: Colors.white), + titleSpacing: 0, + title: Container( + width: double.infinity, + height: 70.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '编辑资料', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + Positioned( + right: 30.rpx, + child: CustomCard( + borderRadius: 10, + gradientDirection: GradientDirection.vertical, + onTap: () {}, + colors: const [ + Color(0xFFFCFCFC), + Color(0xFFF8FAF9), + Color(0XFFECF6F3), + Color(0XFFD9F0E9), + Color(0xFFCEECE3) + ], + child: Container( + width: 120.rpx, + height: 60.rpx, + alignment: Alignment.center, + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(5), + // color: stringToColor("#182B7C"), + // ), + child: Text( + "保存", + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: stringToColor("#9EA4B7"), + letterSpacing: 0, + fontSize: 30.rpx, + ), + ), + ), + )) + ], + ), + ), + centerTitle: false, + ), + body: Container( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(top: 108.rpx), + child: Container( + width: 160.rpx, + height: 160.rpx, + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: Image.asset( + "assets/images/people_avatar.png", + fit: BoxFit.cover, + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 44.rpx), + child: Text( + '点击更换头像', + style: + TextStyle(color: Color(0XFF85F5FF), fontSize: 26.rpx), + ), + ), + Padding( + padding: + EdgeInsets.fromLTRB(60.rpx, 122.rpx, 60.rpx, 0.rpx), + child: Container( + width: double.infinity, + height: 88.rpx, + decoration: BoxDecoration( + border: Border( + top: BorderSide( + color: Color(0xFFD3D3D3), width: 2.rpx), // 上边线 + bottom: BorderSide( + color: Color(0xFFD3D3D3), width: 2.rpx), // 下边线 + ), + ), + alignment: Alignment(0, 0), + child: Text( + '玛利亚', + style: TextStyle( + color: Color(0XFFFFFFFF), fontSize: 26.rpx), + ), + ), + ), + ], + ), + ), + ), + )); + } + + // Widget getImageWidget(BuildContext context) { + // try { + // UserInfoController controller = Get.find(); + + // var head = controller.model.user!.tmpHead; + // return InkWell( + // onTap: () { + // controller.uploadImg(); + // }, + // child: Row( + // children: [ + // Container( + // width: 50, + // height: 50, + // decoration: BoxDecoration( + // color: FlutterFlowTheme.of(context).secondaryBackground, + // ), + // child: Container( + // width: 120, + // height: 120, + // clipBehavior: Clip.antiAlias, + // decoration: BoxDecoration( + // shape: BoxShape.circle, + // ), + // child: head == null || head.isEmpty + // ? Image.asset( + // 'assets/images/avatar.png', + // fit: BoxFit.cover, + // ) + // : Image.network( + // "${getStorageResourceUrl(head)}", + // fit: BoxFit.cover, + // ), + // ), + // ), + // SizedBox(width: 10), + // Icon( + // Icons.arrow_forward_ios, + // color: Color(0xFF373737), + // size: 12, + // ), + // ], + // ), + // ); + // } catch (e) { + // print(e); + // } + // return Container(); + // } +} diff --git a/lib/pages/device_control/experience_store_page.dart b/lib/pages/device_control/experience_store_page.dart new file mode 100644 index 0000000..73c4d3c --- /dev/null +++ b/lib/pages/device_control/experience_store_page.dart @@ -0,0 +1,454 @@ +import 'dart:async'; + +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/appColors.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/color/appFontsize.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/controller/mh/experience_store_list_page.dart'; +import 'package:vbvs_app/pages/device_control/Empty.dart'; +import 'package:vbvs_app/pages/device_control/experience_store_widget.dart'; +import 'package:vbvs_app/pages/device_control/searchWidget.dart'; + +class ExperienceStorePage extends GetView { + ExperienceStorePage({super.key}); + +// class _ExperienceStorePageState extends State { +// get controller => Get.find(); +// final scaffoldKey = GlobalKey(); + BoxConstraints? bodysize; + + ScrollController scrollController = ScrollController(); + ExperienceStoreListController controller = Get.find(); + int runTime = 0; + + // @override + // void initState() { + // // TODO: implement initState + // super.initState(); + // Timer(Duration(milliseconds: 100), () async { + // controller.resetParm(); + // await controller.determinePosition(); + // controller.page = 0; + // controller.getData(); + // scrollController.addListener(() { + // int ctime = DateTime.now().millisecondsSinceEpoch; + // if (ctime - runTime > 100 && + // scrollController.position.pixels + 80 > + // scrollController.position.maxScrollExtent) { + // runTime = ctime; + // print( + // "bottom get more data ${scrollController.position.pixels} ${scrollController.position.maxScrollExtent}"); + // controller.getData(); + // } + // }); + // }); + // } + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + controller.model.experienceStoreModelList = [ + { + "id": "5b82d1d9c33c74647e7624ec1db7918f", + "enabled": true, + "code": "3401002", + "name": "SWES眠花糖合肥省委大院体验店", + "customerId": null, + "setNetCustomerKid": null, + "customer": null, + "kingdeeId": "", + "channel": null, + "salePersonId": "ed648f977422a9f32a05b4892a3cb529", + "salePerson": null, + "deptId": 3, + "deptName": null, + "dept": null, + "introduction": "", + "mobile": "18156022846", + "hotline": "0551-64464894", + "city": "合肥市", + "district": "庐阳区", + "addressDetail": "合肥市庐阳区逍遥津街道南含山路与红星路交汇处", + "image": "", + "latitude": "31.858934", + "longitude": "117.282166", + "isDel": false, + "isAppShow": true, + "business": true, + "authEndTime": null, + "createTime": 1701133326000, + "createAdminId": "f6da6faa2d50e7eff7b54bcdd55b0283", + "updateTime": 1709193588000, + "updateAdminId": null, + "distance": 2.2 + }, + { + "id": "97603deebb83f610f73acf5d0def2bce", + "enabled": true, + "code": "3401003", + "name": "SWES眠花糖合肥安粮国贸体验店", + "customerId": null, + "setNetCustomerKid": null, + "customer": null, + "kingdeeId": "", + "channel": null, + "salePersonId": "69297c65588adde4ee5de3c43a2c4033", + "salePerson": null, + "deptId": 3, + "deptName": null, + "dept": null, + "introduction": "", + "mobile": "18655643429", + "hotline": "0551-65156985", + "city": "合肥市", + "district": "政务新区", + "addressDetail": "安徽省合肥市蜀山区合作化南路16号", + "image": "", + "latitude": "31.82018", + "longitude": "117.25367", + "isDel": false, + "isAppShow": true, + "business": true, + "authEndTime": null, + "createTime": 1701133473000, + "createAdminId": "f6da6faa2d50e7eff7b54bcdd55b0283", + "updateTime": 1709193752000, + "updateAdminId": null, + "distance": 3.5 + }, + { + "id": "b6b588d7ff6b248115ee3e5951cf39a1", + "enabled": true, + "code": "3301001", + "name": "SWES眠花糖杭州南星桥旗舰店", + "customerId": null, + "setNetCustomerKid": null, + "customer": null, + "kingdeeId": "", + "channel": null, + "salePersonId": "f3a5e7935f65e94bc5aa6b2d63211e61", + "salePerson": null, + "deptId": 33, + "deptName": null, + "dept": null, + "introduction": "", + "mobile": "15222919097", + "hotline": "0571-86718606", + "city": "杭州市", + "district": "上城区", + "addressDetail": "浙江省杭州市上城区飞云江路45号一层102室", + "image": "", + "latitude": "30.21667", + "longitude": "120.17757", + "isDel": false, + "isAppShow": true, + "business": true, + "authEndTime": null, + "createTime": 1701135379000, + "createAdminId": "f6da6faa2d50e7eff7b54bcdd55b0283", + "updateTime": 1709194185000, + "updateAdminId": null, + "distance": 332.1 + }, + { + "id": "38fdbb715dc7bfddae3e32685c288e49", + "enabled": true, + "code": "3102001", + "name": "SWES眠花糖上海复兴荟旗舰店", + "customerId": null, + "setNetCustomerKid": null, + "customer": null, + "kingdeeId": "", + "channel": null, + "salePersonId": "4ae944badb423197bc54c0a6ec252944", + "salePerson": null, + "deptId": 32, + "deptName": null, + "dept": null, + "introduction": "", + "mobile": "13053037959", + "hotline": "021-63391962", + "city": "上海市", + "district": "黄浦区", + "addressDetail": "上海市黄浦区复兴东路1108号1层-1室", + "image": "", + "latitude": "31.22209", + "longitude": "121.494667", + "isDel": false, + "isAppShow": true, + "business": true, + "authEndTime": null, + "createTime": 1701135192000, + "createAdminId": "f6da6faa2d50e7eff7b54bcdd55b0283", + "updateTime": 1709194151000, + "updateAdminId": null, + "distance": 407.3 + }, + { + "id": "af908e6c5d1a2c8113b1c73117e15064", + "enabled": true, + "code": "3101001", + "name": "SWES眠花糖上海外滩九里体验店", + "customerId": null, + "setNetCustomerKid": null, + "customer": null, + "kingdeeId": "", + "channel": null, + "salePersonId": "1794f729f27ad4a44afad10061446dd5", + "salePerson": null, + "deptId": 31, + "deptName": null, + "dept": null, + "introduction": "", + "mobile": "13856414205", + "hotline": "021-63391208", + "city": "上海市", + "district": "黄浦区", + "addressDetail": "上海市黄浦区紫霞路103-107号1层103-12室", + "image": "", + "latitude": "31.218434", + "longitude": "121.502098", + "isDel": false, + "isAppShow": true, + "business": true, + "authEndTime": null, + "createTime": 1701134886000, + "createAdminId": "f6da6faa2d50e7eff7b54bcdd55b0283", + "updateTime": 1709194053000, + "updateAdminId": null, + "distance": 408.1 + }, + { + "id": "a5f1fc9a03ba827841c473e28a3fcdb2", + "enabled": true, + "code": "3101002", + "name": "SWES眠花糖上海尚悦湾旗舰店", + "customerId": null, + "setNetCustomerKid": null, + "customer": null, + "kingdeeId": "", + "channel": null, + "salePersonId": "d97ec48ee3b1060eb7ff5c81f0ffa37f", + "salePerson": null, + "deptId": 31, + "deptName": null, + "dept": null, + "introduction": "", + "mobile": "19523660595", + "hotline": "021-63336707", + "city": "上海市", + "district": "浦东新区", + "addressDetail": "上海市浦东新区银城路66号", + "image": "", + "latitude": "31.24103", + "longitude": "121.51045", + "isDel": false, + "isAppShow": true, + "business": true, + "authEndTime": null, + "createTime": 1701135694000, + "createAdminId": "f6da6faa2d50e7eff7b54bcdd55b0283", + "updateTime": 1709194087000, + "updateAdminId": null, + "distance": 408.4 + }, + { + "id": "21ddfb547060e930f841605dc4469bec", + "enabled": true, + "code": "1101001", + "name": "SWES眠花糖北京富力城旗舰店", + "customerId": null, + "setNetCustomerKid": null, + "customer": null, + "kingdeeId": "", + "channel": null, + "salePersonId": "b66028a628ce0fcb871ab7db5c17128e", + "salePerson": null, + "deptId": 11, + "deptName": null, + "dept": null, + "introduction": "", + "mobile": "15556119960", + "hotline": "010-58766288", + "city": "北京市", + "district": "朝阳区", + "addressDetail": "北京市朝阳区天力街3号楼1至2层商业12号", + "image": "", + "latitude": "39.89862", + "longitude": "116.45851", + "isDel": false, + "isAppShow": false, + "business": true, + "authEndTime": null, + "createTime": 1701134049000, + "createAdminId": "f6da6faa2d50e7eff7b54bcdd55b0283", + "updateTime": 1733193484000, + "updateAdminId": null, + "distance": 897.7 + }, + { + "id": "432bfdf508115827c5dca474b72dea68", + "enabled": true, + "code": "1102001", + "name": "SWES眠花糖北京英皇中心旗舰店", + "customerId": null, + "setNetCustomerKid": null, + "customer": null, + "kingdeeId": "", + "channel": null, + "salePersonId": "155848302d5b6f2768111574f0161816", + "salePerson": null, + "deptId": 12, + "deptName": null, + "dept": null, + "introduction": "", + "mobile": "18225602774", + "hotline": "010-53269059", + "city": "北京市", + "district": "朝阳区", + "addressDetail": "北京市朝阳区建国门外大街丁12号", + "image": "", + "latitude": "39.907911", + "longitude": "116.444584", + "isDel": false, + "isAppShow": true, + "business": true, + "authEndTime": null, + "createTime": 1701134158000, + "createAdminId": "f6da6faa2d50e7eff7b54bcdd55b0283", + "updateTime": 1710490644000, + "updateAdminId": null, + "distance": 898.9 + } + ]; + bodysize = cc; + + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + // key: scaffoldKey, + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: Colors.white), + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '预约体验', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + Positioned( + right: 30.rpx, + child: ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Color(0xFF055466), + padding: EdgeInsets.only(left: 0), + onTap: () { + Get.toNamed("/myExperiencePage"); + }, + child: SvgPicture.asset( + 'assets/img/icon/history_store.svg', + width: 35.rpx, + height: 35.rpx, + color: Colors.white, + ))) + ], + ), + ), + centerTitle: false, + ), + body: SingleChildScrollView( + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + //todo + + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0, 40.rpx, 0, 38.rpx), + child: SearchWidget( + keyword: controller.model.keyword, + color: controller.model.color, + hint: "请输入门店名称", + onChange: (d) { + controller.model.keyword = d; + }, + findCallback: () { + // controller.page = 0; + // controller.getData(); + }, + ), + ), + Obx(() { + if (controller + .model.experienceStoreModelList.length == + 0) { + return Empty(); + } else { + return Container(); + } + }), + Expanded( + child: Obx(() => ListView( + controller: scrollController, + shrinkWrap: true, + scrollDirection: Axis.vertical, + children: List.generate( + controller + .model + .experienceStoreModelList + .length, (index) { + return ExperienceStoreWidget( + index: index, + data: controller.model + .experienceStoreModelList[index]); + }) + .divide(const SizedBox( + height: 25, + )) + .addToStart(SizedBox( + height: AppConstants.list_start_height, + )) + .addToEnd(SizedBox( + height: AppConstants.list_ano_end_height, + ))))), + ], + ), + ), + )), + )); + }); + } +} diff --git a/lib/pages/device_control/experience_store_widget.dart b/lib/pages/device_control/experience_store_widget.dart new file mode 100644 index 0000000..cc49a78 --- /dev/null +++ b/lib/pages/device_control/experience_store_widget.dart @@ -0,0 +1,306 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/controller/mh/book_info_controller.dart'; +import 'package:vbvs_app/pages/common/selectDialog.dart'; +import 'package:vbvs_app/pages/device_control/app_map_location.dart'; + +import '../../common/color/appFontsize.dart'; +import '../../common/util/MyUtils.dart'; + +class ExperienceStoreWidget extends GetView { + int index; + Map data; + + ExperienceStoreWidget({required this.index, required this.data}) {} + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + // height: MediaQuery.sizeOf(context).height * 0.187, + decoration: BoxDecoration( + color: Color(0XFF003058), + borderRadius: BorderRadius.circular(16), + ), + + child: Container( + width: MediaQuery.sizeOf(context).width, + margin: EdgeInsetsDirectional.fromSTEB(26.rpx, 14, 14, 15), + height: 120, + decoration: BoxDecoration( + color: Color(0XFF003058), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 4), + child: Container( + width: MediaQuery.sizeOf(context).width, + // height: MediaQuery.sizeOf(context).height * 0.018, + constraints: const BoxConstraints( + minHeight: 30, + ), + + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.018, + child: Align( + alignment: const AlignmentDirectional(0, 0), + child: Text( + // experienceStoreModel.name ?? '未命名', + data["name"] ?? '', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: 30.rpx, + fontWeight: FontWeight.bold, + letterSpacing: 0, + ), + ), + ), + ), + ), + ), + Container( + width: MediaQuery.sizeOf(context).width, + height: 1.rpx, + decoration: const BoxDecoration( + color: Color(0xFF929699), + ), + ), + Flexible( + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(0, 10, 0, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + // height: MediaQuery.sizeOf(context).height * 0.034, + constraints: const BoxConstraints( + minHeight: 55, + ), + + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.034, + constraints: const BoxConstraints( + minHeight: 55, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: Align( + alignment: const AlignmentDirectional(-1, 0), + child: Text( + '地址:${data["addressDetail"]}', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: const Color(0xFF929699), + fontSize: 20.rpx, + letterSpacing: 0, + lineHeight: 1), + ), + ), + ), + Flexible( + child: Align( + alignment: const AlignmentDirectional(-1, 0), + child: Text( + '电话:${data["hotline"]}', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: const Color(0xFF929699), + fontSize: 20.rpx, + letterSpacing: 0, + lineHeight: 1), + ), + ), + ), + ], + ), + ), + ), + ), + ), + Flexible( + child: Container( + width: MediaQuery.sizeOf(context).width, + // height: MediaQuery.sizeOf(context).height * 0.038, + + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.038, + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Flexible( + child: InkWell( + onTap: () { + MyUtils.makePhoneCall("${data["hotline"]}"); + }, + child: Container( + width: MediaQuery.sizeOf(context).width * 0.105, + height: MediaQuery.sizeOf(context).height * 0.038, + constraints: const BoxConstraints( + minWidth: 50, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + // child: Icon( + // Icons.phone_in_talk, + // color: Color(0xFFD3B684), + // size: 12, + // ), + child: SvgPicture.asset( + 'assets/images/phone.svg', + width: 27.rpx, + height: 27.rpx, + color: const Color(0xFF84F5FF), + ), + ), + Text( + '咨询', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: AppFontsize.small_text_size, + letterSpacing: 0, + ), + ), + ].divide(const SizedBox(width: 13)), + ), + ), + )), + Flexible( + child: InkWell( + onTap: () async { + // //"latitude" -> "31.858934" "longitude" -> "117.282166" + // AppMapLocation.checkInstalledApps() + // .then((d) { + // if (AppMapLocation + // .availableMapsToNames.isEmpty) { + // showToast("未检测到导航软件"); + // } else { + // showOneSelectionDialog(context, + // title: "选择地图", + // arr: AppMapLocation + // .availableMapsToNames, + // checkChange: (index) { + // AppMapLocation.launchMap( + // index, + // data["name"], + // double.parse( + // "${data["latitude"]}"), + // double.parse( + // "${data["longitude"]}")); + // }); + // } + // }); + }, + child: Container( + width: MediaQuery.sizeOf(context).width * 0.105, + height: MediaQuery.sizeOf(context).height * 0.038, + constraints: const BoxConstraints( + minWidth: 50, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + // child: Icon( + // Icons.location_on, + // color: Color(0xFFD3B684), + // size: 12, + // ), + child: SvgPicture.asset( + 'assets/images/locationColor.svg', + width: 22.rpx, + height: 29.rpx, + color: Color(0xFF84F5FF), + ), + ), + Text( + '导航', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: AppFontsize.small_text_size, + letterSpacing: 0, + ), + ), + ].divide(const SizedBox(width: 13)), + ), + ), + ), + ), + Container( + width: MediaQuery.sizeOf(context).width * 0.208, + height: MediaQuery.sizeOf(context).height * 0.038, + constraints: BoxConstraints( + maxWidth: 156.rpx, + maxHeight: 60.rpx, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30.rpx), + ), + child: FFButtonWidget( + onPressed: () { + BookInfoController bookInfoController = + Get.find(); + bookInfoController.model.userName = ""; + bookInfoController.model.userPhone = ""; + Get.toNamed("/bookInfoPage", + arguments: {"data": data}); + }, + text: '预约', + options: FFButtonOptions( + padding: const EdgeInsetsDirectional.fromSTEB( + 0, 0, 0, 0), + color: Color(0xFF84F5FF), + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF011D33), + fontSize: 26.rpx, + letterSpacing: 0, + ), + elevation: 0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1, + ), + borderRadius: BorderRadius.circular(30.rpx), + ), + ), + ), + ].divide(const SizedBox(width: 26)), + ), + ), + ), + ), + ], + ), + ), + + // ), + ), + ); + } +} diff --git a/lib/pages/device_control/issue_list_page.dart b/lib/pages/device_control/issue_list_page.dart new file mode 100644 index 0000000..50e9eef --- /dev/null +++ b/lib/pages/device_control/issue_list_page.dart @@ -0,0 +1,187 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/color/appFontsize.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/pages/device_control/issue_preview_widget.dart'; + +import '../../controller/mh/issue_controller.dart'; + +class IssueListPage extends GetView { + final scaffoldKey = GlobalKey(); + BoxConstraints? bodysize; + + final ScrollController scrollController = ScrollController(); + + // IssueListPage() { + // controller.model.limit = AppConstants.limit; + // controller.model.offset = 0; + // controller.model.isLoading = false; + // controller.model.hasMore = true; + // controller.model.issueList!.clear(); + // controller.initData(); + + // scrollController.addListener(() { + // if (scrollController.position.pixels == + // scrollController.position.maxScrollExtent && + // controller.model.hasMore) { + // controller.initData(); + // controller.updateAll(); + // } + // }); + // } + + // void initData() async {} + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + controller.model.issueList = [ + {'title': 'APP如何连接我的智能床?'}, + {'title': '智能床如何连接网络?'}, + {'title': '跟换WIFI名称或密码,或者刚换了路由器后,我的智能床无法使用怎么办?'}, + {'title': '在APP中,如何查看我的睡眠报告?'}, + {'title': '在APP中,如何查看我的睡眠报告?'}, + {'title': '在APP中,如何查看我的睡眠报告?'} + ]; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: Colors.white), + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '问题与帮助', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + actions: [], + centerTitle: false, + ), + // backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + body: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + decoration: BoxDecoration( + // color: AppColors.bg_color, + // color: Color(0xFFF6F6F6), + ), + child: Obx(() { + return Visibility( + visible: controller.model.issueList != null && + controller.model.issueList!.isNotEmpty, + replacement: Container( + width: MediaQuery.sizeOf(context).width, + height: 100, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).secondaryBackground, + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(31, 27, 0, 0), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: AlignmentDirectional(-1, 0), + child: Text( + '暂无内容!', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: AppFontsize.title_size, + letterSpacing: 0, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + // TitleComponentWidget( + // titleName: '问题与帮助', + // ), + Flexible( + child: Padding( + padding: + EdgeInsetsDirectional.fromSTEB(15, 13, 15, 15), + child: Container( + width: bodysize!.maxWidth, + decoration: BoxDecoration( + // color: Colors.white, + // borderRadius: BorderRadius.circular(16), + ), + child: Obx(() => ListView( + controller: scrollController, + padding: const EdgeInsets.fromLTRB( + 0, + 5, + 0, + 0, + ), + shrinkWrap: true, + scrollDirection: Axis.vertical, + children: (controller.model.issueList! + .asMap() + .entries + .map((e) => IssuePreviewWidget( + index: e.key, + issueListController: controller)) + .toList() as List) + // .divide(const SizedBox( + // height: 30, + // )) + // .addToEnd(const SizedBox( + // height: 26, + // )) + // .addToStart(SizedBox( + // height: 16, + // )) + )), + ), + ), + ), + ], + ), + ); + }), + ), + ), + )); + }); + } +} diff --git a/lib/pages/device_control/issue_preview_widget.dart b/lib/pages/device_control/issue_preview_widget.dart new file mode 100644 index 0000000..7ebf886 --- /dev/null +++ b/lib/pages/device_control/issue_preview_widget.dart @@ -0,0 +1,104 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/controller/mh/issue_controller.dart'; +import 'package:vbvs_app/controller/mh/issue_preview_controller.dart'; + +import '../../common/color/appFontsize.dart'; + +class IssuePreviewWidget extends GetView { + final int index; + final IssueListController issueListController; + + IssuePreviewWidget({ + required this.index, + required this.issueListController, + }); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () async { + // issueListController.model.selectedIndex = index; + // issueListController.updateAll(); + // await Future.delayed(Duration(milliseconds: 100)); + // issueListController.model.selectedIndex = -1; + // issueListController.updateAll(); + // var article = issueListController.model.issueList![index]; + // Get.toNamed("/helpArticle", arguments: article); + }, + child: Obx(() { + return Container( + alignment: Alignment.center, + width: double.infinity, + constraints: BoxConstraints( + // minWidth: 100, + minHeight: 119.rpx, + ), + decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(0), + // 整行的背景颜色 + color: index == issueListController.model.selectedIndex + ? Colors.grey[300] + : Colors.transparent, + border: Border( + bottom: BorderSide(color: const Color(0xFF929699), width: 0.rpx), + ), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(16.rpx, 0, 41.rpx, 0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + flex: 9, + child: Align( + alignment: AlignmentDirectional(-1, -1), + child: Text( + issueListController.model.issueList![index]['title'] ?? + '', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: Color(0xFFFFFFFF), + fontSize: AppFontsize.title_size, + letterSpacing: 0, + lineHeight: 1), + ), + ), + ), + Expanded( + flex: 1, + child: Align( + alignment: Alignment.centerRight, + child: ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.transparent, + padding: EdgeInsets.only(right: 0), + onTap: () {}, + child: Container( + height: 30.rpx, + width: 30.rpx, + child: SvgPicture.asset( + 'assets/img/icon/expand.svg', + color: Colors.white, + ) + // Icon( + // Icons.arrow_forward_ios, + // color: Colors.white, + // // size: 14.rpx, + // ), + )), + ), + ), + ], + ), + ), + ); + }), + ); + } +} diff --git a/lib/pages/device_control/message_page.dart b/lib/pages/device_control/message_page.dart new file mode 100644 index 0000000..ce3262a --- /dev/null +++ b/lib/pages/device_control/message_page.dart @@ -0,0 +1,418 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/color/appFontsize.dart'; +import 'package:vbvs_app/common/color/app_uri_status.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/NullDataComponentWidget.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; +import 'package:vbvs_app/controller/mh/message_controller.dart'; +import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; +import 'package:vbvs_app/pages/main_bottom/component/MessageWidgetWidget.dart'; + +class MessagePage extends StatefulWidget { + const MessagePage({super.key}); + + @override + State createState() => _MessagePageState(); +} + +class _MessagePageState extends State { + ThemeController themeController = Get.find(); + MhMessageController messageController = Get.find(); + late PageController _pageController; + + @override + void initState() { + super.initState(); + messageController.model.type = 1; + _pageController = + PageController(initialPage: messageController.model.type == 1 ? 0 : 1); + messageController.getMessageStatus(); + _fetchMessageData(); + } + + void _fetchMessageData() { + String type = messageController.model.type == 1 ? "app_vsm" : "app_system"; + messageController.updateMessageStatus(type: type); + messageController.getMessageList().then((response) { + if (response.code != HttpStatusCodes.ok) { + TopSlideNotification.show( + // Get.context!, + context, + text: response.msg ?? "服务器.失败".tr, + textColor: themeController.currentColor.sc9, + ); + } + }); + } + + void _onTabChanged(int index) { + messageController.model.type = index == 0 ? 1 : 2; + messageController.updateAll(); + _fetchMessageData(); + _pageController.animateToPage(index, + duration: const Duration(milliseconds: 300), curve: Curves.easeInOut); + } + + void _onPageChanged(int index) { + int newType = index == 0 ? 1 : 2; + if (messageController.model.type != newType) { + messageController.model.type = newType; + messageController.updateAll(); + _fetchMessageData(); + } + } + + @override + void dispose() { + _pageController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + messageController.messageList.value = [ + { + "_id": "6836c3ee4e626030c8000000", + "type": "app_vsm", + "data": { + "title": "实时监测通知", + "val": [ + {"k": "设备ID", "v": "48ca43b1b454"}, + {"k": "使用人员", "v": "bb"}, + {"k": "消息类型", "v": "呼吸异常"}, + {"k": "检测值", "v": '26'}, + {"k": "检测时间", "v": "2025-05-28 16:06:07"} + ] + }, + "level": 3, + "tid": "67f5d96e26ef310463000000", + "uid": "68319fe9702cc59bd1000000", + "status": 0, + "createTime": "1748419566651" + }, + { + "_id": "6836c3e84e625f30c8000000", + "type": "app_vsm", + "data": { + "title": "实时监测通知", + "val": [ + {"k": "设备ID", "v": "48ca43b1b454"}, + {"k": "使用人员", "v": "bb"}, + {"k": "消息类型", "v": "心率异常"}, + {"k": "检测值", "v": '115'}, + {"k": "检测时间", "v": "2025-05-28 16:06:00"} + ] + }, + "level": 3, + "tid": "67f5d96e26ef310463000000", + "uid": "68319fe9702cc59bd1000000", + "status": 0, + "createTime": "1748419560486" + }, + { + "_id": "6836bd0c4e625e30c8000000", + "type": "app_vsm", + "data": { + "title": "实时监测通知", + "val": [ + {"k": "设备ID", "v": "48ca43b1b454"}, + {"k": "使用人员", "v": "bb"}, + {"k": "消息类型", "v": "心率异常"}, + {"k": "检测值", "v": '107'}, + {"k": "检测时间", "v": "1748417761000"} + ] + }, + "level": 3, + "tid": "67f5d96e26ef310463000000", + "uid": "68319fe9702cc59bd1000000", + "status": 0, + "createTime": "1748417804381" + } + ]; + + SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarIconBrightness: Brightness.light, + )); + + return LayoutBuilder( + builder: (context, boxConstraints) => GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: themeController.currentColor.sc3), + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '消息中心', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + actions: const [], + centerTitle: false, + ), + backgroundColor: Colors.transparent, + body: SafeArea( + top: true, + child: Padding( + padding: EdgeInsets.only(top: 30.rpx), + child: Column( + children: [ + SizedBox( + height: 100.rpx, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Row( + children: [ + // 第一个 Tab 占据屏幕一半 + bodyMessage(), + // 第二个 Tab 占据屏幕另一半 + systemMessage(), + ], + ), + Obx(() { + double screenWidth = + MediaQuery.of(context).size.width; + double tabWidth = screenWidth / 2; + double margin = 30.rpx; + double lineWidth = tabWidth - 2 * margin; + // 计算滑块左边距,保证滑块水平居中于对应tab的文字 + double left = (messageController.model.type == 1 + ? 0 + : tabWidth) + + margin; + return AnimatedPositioned( + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + bottom: 0, + left: left, + child: Container( + width: lineWidth, + height: 4.rpx, + decoration: BoxDecoration( + color: Color(0xFF84F5FF), + borderRadius: BorderRadius.circular(2.rpx), + ), + ), + ); + }), + ], + ), + ), + Expanded( + child: PageView( + controller: _pageController, + onPageChanged: _onPageChanged, + children: [ + Obx(() { + final list = messageController.messageList.value; + return list.isEmpty + ? const NullDataWidget() + : _buildMessageListView(list); + }), + Obx(() { + final list = messageController.messageList.value; + return list.isEmpty + ? const NullDataWidget() + : _buildMessageListView(list); + }), + ], + ), + ), + bottomIcon(context) + ], + ), + )), + ), + ), + ), + ); + } + + Container bottomIcon(BuildContext context) { + return Container( + height: 120.rpx, + decoration: BoxDecoration( + color: Color(0xFF003058), + ), + width: double.infinity, + child: TextButton( + onPressed: () {}, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Baseline( + baselineType: TextBaseline.alphabetic, + baseline: AppFontsize.normal_text_size * 1.6, // 调整基线位置 + child: SvgPicture.asset( + 'assets/images/read_message.svg', + width: 40.rpx, + height: 40.rpx, + )), + SizedBox(width: 14.rpx), // 加号和文字间距 + Text( + '全部已读', + style: FlutterFlowTheme.of(context).titleSmall.override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: 26.rpx, + letterSpacing: 0, + ), + ), + ], + ), + ), + ); + } + + Expanded systemMessage() { + return Expanded( + child: Align( + alignment: Alignment.center, + child: Obx(() { + return ClickableContainer( + padding: EdgeInsets.zero, + backgroundColor: Colors.transparent, + highlightColor: themeController.currentColor.sc21, + borderRadius: 8.rpx, + onTap: () => _onTabChanged(1), + child: Stack( + alignment: Alignment.center, + clipBehavior: Clip.none, + children: [ + Text( + '系统消息'.tr, + style: TextStyle( + fontSize: AppConstants().title_text_fontSize, + color: messageController.model.type == 1 + ? Colors.white + : Color(0xFF84F5FF), + height: 1.0, + ), + ), + Obx(() { + return messageController.model.system_message_read == 1 + ? Positioned( + top: -4, + right: -14, + child: Container( + width: 8, + height: 8, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + ), + ) + : const SizedBox.shrink(); + }), + ], + ), + ); + }), + ), + ); + } + + Expanded bodyMessage() { + return Expanded( + child: Align( + alignment: Alignment.center, + child: Obx(() { + return ClickableContainer( + padding: EdgeInsets.zero, + backgroundColor: Colors.transparent, + highlightColor: themeController.currentColor.sc21, + borderRadius: 8.rpx, + onTap: () => _onTabChanged(0), + child: Stack( + alignment: Alignment.center, + clipBehavior: Clip.none, + children: [ + Text( + '体征消息'.tr, + style: TextStyle( + fontSize: AppConstants().title_text_fontSize, + color: messageController.model.type == 2 + ? Colors.white + : Color(0xFF84F5FF), + height: 1.0, + ), + ), + Obx(() { + return messageController.model.body_message_read == 1 + ? Positioned( + top: -4, + right: -14, + child: Container( + width: 8, + height: 8, + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + ), + ) + : const SizedBox.shrink(); + }), + ], + ), + ); + }), + ), + ); + } + + Widget _buildMessageListView(List dataList) { + return Container( + width: double.infinity, + padding: EdgeInsets.symmetric(horizontal: 30.rpx), + child: SingleChildScrollView( + child: Column( + children: [ + SizedBox(height: 30.rpx), + ...dataList + .map((item) => MessageWidgetWidget(data: item)) + .toList() + .divide(SizedBox(height: 30.rpx)), + SizedBox(height: 30.rpx), + ], + ), + ), + ); + } +} diff --git a/lib/pages/device_control/my_experience_page.dart b/lib/pages/device_control/my_experience_page.dart new file mode 100644 index 0000000..48b6405 --- /dev/null +++ b/lib/pages/device_control/my_experience_page.dart @@ -0,0 +1,152 @@ +import 'dart:async'; + +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/color/appColors.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/controller/mh/my_experience_list_controller.dart'; +import 'package:vbvs_app/pages/device_control/Empty.dart'; +import 'package:vbvs_app/pages/device_control/my_experience_widget.dart'; + +class MyExperiencePage extends StatefulWidget { + const MyExperiencePage({super.key}); + + @override + State createState() => _MyExperiencePageState(); +} + +class _MyExperiencePageState extends State { + ScrollController scrollController = ScrollController(); + int runTime = 0; + @override + void initState() { + super.initState(); + Timer(Duration.zero, () { + controller.resetParm(); + controller.getAllBook(); + controller.page = 0; + controller.getData(); + scrollController.addListener(() { + print( + "${scrollController.position.pixels} ${scrollController.position.maxScrollExtent}"); + int ctime = DateTime.now().millisecondsSinceEpoch; + if (ctime - runTime > 100 && + scrollController.position.pixels + 80 > + scrollController.position.maxScrollExtent) { + runTime = ctime; + print( + "bottom get more data ${scrollController.position.pixels} ${scrollController.position.maxScrollExtent}"); + controller.getData(); + } + }); + }); + } + + get controller => Get.find(); + final scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + // key: scaffoldKey, + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: Colors.white), + titleSpacing: 0, + // leading: returnIconButtomAddCallback(() { + // controller.saveDataApi(); + // updateParm(isShowToast: false); + // }), + // leading: returnIconButtomNew, + title: Container( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '我的预约', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + + actions: [], + centerTitle: false, + ), + + body: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 1, + decoration: BoxDecoration( + color: Color(0xFFF6F6F6), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + // TitleComponentWidget( + // titleName: '我的预约', + // ), + Obx(() { + if (controller.model.bookInfoList.length == 0) { + return Empty(); + } else { + return Container(); + } + }), + Expanded( + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 1, + decoration: BoxDecoration(), + child: Obx(() => ListView( + controller: scrollController, + shrinkWrap: true, + scrollDirection: Axis.vertical, + children: [ + const SizedBox( + height: AppConstants.list_start_height), + ...List.generate( + controller.model.bookInfoList.length, + (index) { + return MyExperienceWidget( + index: index, + bookExperienceListController: controller); + }), + SizedBox( + height: AppConstants.list_end_height, + ) + ], + ))), + ) + ], + ), + ), + ), + )); + } +} diff --git a/lib/pages/device_control/my_experience_widget.dart b/lib/pages/device_control/my_experience_widget.dart new file mode 100644 index 0000000..9967f06 --- /dev/null +++ b/lib/pages/device_control/my_experience_widget.dart @@ -0,0 +1,424 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; + +import 'package:vbvs_app/controller/mh/my_experience_list_controller.dart'; + +import '../../common/color/appFontsize.dart'; + +class MyExperienceWidget extends GetView { + int index; + BookExperienceListController bookExperienceListController; + + MyExperienceWidget( + {required this.index, required this.bookExperienceListController}) {} + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsetsDirectional.fromSTEB(15, 0, 15, 0), + child: Obx(() { + Map data = {}; + bookExperienceListController.model.experienceStoreModelList + .forEach((item) { + if (item["id"] == + bookExperienceListController.model.bookInfoList[index] + ["storeId"]) { + data = item; + } + }); + return Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.187, + margin: const EdgeInsets.only(bottom: 25), + constraints: const BoxConstraints( + minHeight: 170, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).secondaryBackground, + borderRadius: BorderRadius.circular(16), + ), + child: Padding( + padding: const EdgeInsetsDirectional.fromSTEB(14, 14, 14, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.187, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).secondaryBackground, + ), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.187, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context).secondaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 17), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.018, + constraints: const BoxConstraints( + minHeight: 20, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + ), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.018, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + ), + child: Align( + alignment: const AlignmentDirectional(0, 0), + child: Text( + // widget!.name, + "体验时间:${DateFormat("yyyy-MM-dd HH:mm").format(DateTime.fromMillisecondsSinceEpoch(int.parse("${bookExperienceListController.model.bookInfoList[index]["bookTimeStart"]}")))}", + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: const Color(0xFF182B7C), + fontSize: AppFontsize.title_size, + letterSpacing: 0, + ), + ), + ), + ), + ), + ), + Container( + width: MediaQuery.sizeOf(context).width, + height: 1.rpx, + decoration: const BoxDecoration( + color: Color(0xFFAAAFC0), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(0, 10, 0, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.034, + constraints: const BoxConstraints( + minHeight: 55, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + ), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.034, + constraints: const BoxConstraints( + minHeight: 55, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: Align( + alignment: + const AlignmentDirectional(-1, 0), + child: Text( + '门店:${data["name"] ?? ""}', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: const Color(0xFF9EA4B7), + fontSize: + AppFontsize.small_text_size, + letterSpacing: 0, + ), + ), + ), + ), + Flexible( + child: Align( + alignment: + const AlignmentDirectional(-1, 0), + child: Text( + '地址:${data['addressDetail'] ?? ""}', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: const Color(0xFF9EA4B7), + fontSize: + AppFontsize.small_text_size, + letterSpacing: 0, + ), + ), + ), + ), + Flexible( + child: Align( + alignment: + const AlignmentDirectional(-1, 0), + child: Text( + '电话:${data["hotline"]} ', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: const Color(0xFF9EA4B7), + fontSize: + AppFontsize.small_text_size, + letterSpacing: 0, + ), + ), + ), + ), + ], + ), + ), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0), + child: Container( + constraints: const BoxConstraints( + minHeight: 40, + ), + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.038, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + ), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 0.038, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + ), + child: // Generated code for this Row Widget... + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Flexible( + child: InkWell( + onTap: () { + if (data["hotline"] != null) { + MyUtils.makePhoneCall(data["hotline"]); + } + }, + child: Container( + width: MediaQuery.sizeOf(context).width * + 0.105, + height: + MediaQuery.sizeOf(context).height * + 0.038, + constraints: const BoxConstraints( + maxWidth: 50, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + const Flexible( + child: Icon( + Icons.phone_in_talk, + color: Color(0xFFD3B684), + size: 12, + ), + ), + Text( + '咨询', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + // color: Color(0xFF9EA4B7), + color: + const Color(0xFF333333), + fontSize: AppFontsize + .small_text_size, + letterSpacing: 0, + ), + ), + ].divide(const SizedBox(width: 13)), + ), + ), + )), + Flexible( + child: InkWell( + onTap: () { + // AppMapLocation.checkInstalledApps() + // .then((d) { + // if (AppMapLocation + // .availableMapsToNames.isEmpty) { + // showToast("未检测到导航软件"); + // } else { + // showOneSelectionDialog(context, + // title: "选择地图", + // arr: AppMapLocation + // .availableMapsToNames, + // checkChange: (index) { + // AppMapLocation.launchMap( + // index, + // data["name"], + // double.parse( + // "${data["latitude"]}"), + // double.parse( + // "${data["longitude"]}")); + // }); + // } + // }); + }, + child: Container( + width: MediaQuery.sizeOf(context).width * + 0.105, + height: + MediaQuery.sizeOf(context).height * + 0.038, + constraints: const BoxConstraints( + maxWidth: 50, + ), + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + const Flexible( + child: Icon( + Icons.location_on, + color: Color(0xFFD3B684), + size: 12, + ), + ), + Text( + '导航', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + // color: Color(0xFF9EA4B7), + color: + const Color(0xFF333333), + fontSize: AppFontsize + .small_text_size, + letterSpacing: 0, + ), + ), + ].divide(const SizedBox(width: 13)), + ), + ), + )), + Container( + width: + MediaQuery.sizeOf(context).width * 0.22, + height: MediaQuery.sizeOf(context).height * + 0.038, + constraints: const BoxConstraints( + maxWidth: 78, + maxHeight: 100, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + ), + child: FFButtonWidget( + onPressed: () { + // if (bookExperienceListController + // .model.bookInfoList[index] + // ["status"] == + // 2) { + // showCustomConfirmAndCancelDialog( + // context, "取消预约") + // .then((d) { + // if (d == "confirm") { + // bookExperienceListController + // .cancelBook( + // bookExperienceListController + // .model + // .bookInfoList[ + // index]["id"], + // success: () { + // var rd = jsonDecode(jsonEncode( + // bookExperienceListController + // .model + // .bookInfoList[index])); + // rd["status"] = -1; + // rd["addressDetail"] = + // data['addressDetail']; + // rd["name"] = data["name"]; + // bookExperienceListController + // .messageAdd(rd); + // }); + // } + // }); + // } + }, + text: bookExperienceListController + .model.bookInfoList[index] + ["status"] == + 2 + ? '取消预约' + : bookExperienceListController + .model.bookInfoList[index] + ["statusName"], + options: FFButtonOptions( + height: 40, + padding: const EdgeInsetsDirectional + .fromSTEB(13, 0, 13, 0), + iconPadding: const EdgeInsetsDirectional + .fromSTEB(0, 0, 0, 0), + color: bookExperienceListController + .model + .bookInfoList[index] + ["status"] == + 2 + ? const Color(0xFFD3B684) + : stringToColor("#D3D3D3"), + textStyle: FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: + AppFontsize.small_text_size, + letterSpacing: 0, + ), + elevation: 0, + borderSide: const BorderSide( + color: Colors.transparent, + width: 1, + ), + borderRadius: BorderRadius.circular(32), + ), + ), + ), + ].divide(const SizedBox(width: 26)), + )), + ), + ), + ], + ), + ), + ), + ), + ); + })); + } +} diff --git a/lib/pages/device_control/new_Home_page.dart b/lib/pages/device_control/new_Home_page.dart new file mode 100644 index 0000000..7198c9f --- /dev/null +++ b/lib/pages/device_control/new_Home_page.dart @@ -0,0 +1,854 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; + +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/controller/device/body_device_controller.dart'; +import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; +import 'package:vbvs_app/controller/mh/muser_info_controller.dart'; + + +class NewHomePage extends StatefulWidget { + const NewHomePage({super.key}); + @override + State createState() => _NewHomePageState(); +} + +class _NewHomePageState extends State { + MUserInfoController userInfoController = Get.find(); + BodyDeviceController deviceController = Get.find(); + double borderRadius = 16.rpx; + + var formFieldController = FormFieldController(null); + + get gloablController => Get.find(); + + // get userInfoController => Get.find(); + + var sleepDays = [].obs; + + var sleep_mac = "".obs; + + Map scoreColor = { + "-1": "#d3d3d3", + "1": "#4e8408", + "2": "#7bbb33", + "3": "#e15b8d", + "4": "#ff0000", + }; + + Map scoreName = { + "-1": "暂无", + "1": "优秀", + "2": "良好", + "3": "合格", + "4": "注意", + }; + + @override + void initState() { + super.initState(); + } + + getWeekName(int i) { + String v = ""; + switch (i) { + case 1: + v = "周一"; + break; + case 2: + v = "周二"; + break; + case 3: + v = "周三"; + break; + case 4: + v = "周四"; + break; + case 5: + v = "周五"; + break; + case 6: + v = "周六"; + break; + case 7: + v = "周日"; + break; + } + return v; + } + + @override + Widget build(BuildContext context) { + int login = userInfoController.model.login!; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + iconTheme: IconThemeData(color: themeController.currentColor.sc3), + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + titleSpacing: 0, + title: Row( + children: [ + // 左侧头像 + SizedBox(width: 40.rpx), + CircleAvatar( + radius: 27.rpx, // 可根据需求调整 + backgroundImage: login == 1 + ? (userInfoController.model.user!.avatar == null || + userInfoController.model.user!.avatar!.isEmpty + ? const AssetImage( + "assets/images/people_avatar.png", + ) + : NetworkImage( + userInfoController.model.user!.avatar!, + )) + : const AssetImage( + "assets/images/people_avatar.png", + ), + ), + SizedBox(width: 23.rpx), // 左侧头像和文本之间的间距 + Text( + 'Eason Chan', + style: TextStyle(fontSize: 30.rpx, color: Colors.white), + ), + + const Spacer(), // 左右分隔 + // Container( + // width: 61.rpx, + // height: 78.rpx, + // alignment: const Alignment(0, 0), + // child: Image.asset( + // "assets/images/xiaoe.png", + // fit: BoxFit.cover, + // ), + // ), + // SizedBox(width: 46.rpx), // icon 之间的间距 + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.transparent, + padding: EdgeInsets.only(right: 0), + onTap: () {}, + child: Container( + height: 60.rpx, + width: 75.rpx, + child: SvgPicture.asset( + 'assets/img/icon/xiaoe.svg', + // color: Colors.white, + ))), + + // SizedBox(width: 40.rpx), + ], + ), + centerTitle: false, + ), + body: SafeArea( + child: Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 1.123, + // decoration: BoxDecoration( + // color: AppColors.bg_color, + // image: DecorationImage( + // image: AssetImage("assets/images/background.png"), + // fit: BoxFit.cover, + // ), + // ), + decoration: BoxDecoration( + + ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + padding: + EdgeInsets.fromLTRB(26.rpx, 10.rpx, 26.rpx, 40.rpx), + width: double.infinity, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 30.rpx), + child: Column( + children: [ + Padding( + padding: + EdgeInsets.fromLTRB(17.rpx, 30.rpx, 0, 0), + child: Row( + children: [ + Text('上海 22° 多云', + style: TextStyle( + fontSize: 26.rpx, + color: Colors.white)), + Icon(Icons.cloud, + size: 30.rpx, color: Colors.white), + ], + ), + ), + ], + ))), + Container( + padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx), + child: Column( + children: [ + if (gloablController.model.deviceList.length > 0) + Container( + child: Column( + children: [ + Container( + width: MediaQuery.sizeOf(context).width, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.circular(borderRadius), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + EdgeInsetsDirectional.fromSTEB( + 30.rpx, + 16.rpx, + 16.rpx, + 8.rpx), + child: Container( + width: MediaQuery.sizeOf(context) + .width, + height: MediaQuery.sizeOf(context) + .height * + 0.065, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context) + .secondaryBackground, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + ValueListenableBuilder( + valueListenable: + formFieldController, + builder: (c, a, s) => + FlutterFlowDropDown< + String>( + controller: + formFieldController, + options: gloablController + .model.JunheDevices + .map((d) => + "${d["mac"]}") + .toList(), + optionLabels: + gloablController + .model.JunheDevices + .map((d) { + var s = + d["name"] ?? d["mac"]; + if (s == null) { + return ""; + } else { + return "$s"; + } + }).toList(), + onChanged: (val) { + // print("$val"); + // if (val == null) { + // sleepDays.value = []; + // } else { + // getSleeps( + // formFieldController + // .value); + // } + // // sleep_mac.value = val!; + }, + width: 360.rpx, + height: 72.rpx, + maxHeight: 200.rpx, + textStyle: TextStyle( + fontSize: 28.rpx, + overflow: TextOverflow + .ellipsis), + hintText: '', + icon: Icon( + Icons + .keyboard_arrow_down_rounded, + color: + FlutterFlowTheme.of( + context) + .secondaryText, + size: 48.rpx, + ), + fillColor: stringToColor( + "#F3F5F6"), + elevation: 2, + borderColor: stringToColor( + "#F3F5F6"), + borderWidth: 2, + borderRadius: 18, + margin: + EdgeInsetsDirectional + .fromSTEB( + 32.rpx, + 8.rpx, + 32.rpx, + 8.rpx), + hidesUnderline: true, + isOverButton: false, + isSearchable: false, + isMultiSelect: false, + ), + ), + InkWell( + onTap: () { + // if (formFieldController + // .value != + // null) { + // Get.toNamed( + // "/sleepWebview", + // arguments: [ + // formFieldController + // .value + // ]); + // } + }, + child: Row( + mainAxisSize: + MainAxisSize.max, + children: [ + Text( + '睡眠报告', + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + fontSize: + 30.rpx), + ), + SizedBox( + width: 12.rpx, + ), + SvgPicture.asset( + "assets/images/table.svg", + width: 28.rpx, + height: 28.rpx), + SizedBox( + width: 20.rpx, + ), + ], + ), + ), + ], + ), + ), + ), + Container( + padding: EdgeInsets.only( + top: 0.rpx, + bottom: 20.rpx, + left: 16.rpx, + right: 16.rpx), + width: double.infinity, + decoration: BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + ...List.generate( + sleepDays.value.length, + (index) { + var day = sleepDays[index]; + return Expanded( + child: Container( + padding: EdgeInsets.only( + top: 10.rpx, + bottom: 20.rpx), + width: 100, + // decoration: BoxDecoration( + // color: index == 2 + // ? stringToColor("#F3F5F6") + // : Colors.white, + // borderRadius: + // BorderRadius.circular( + // borderRadius), + // ), + child: Column( + mainAxisSize: + MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment + .start, + crossAxisAlignment: + CrossAxisAlignment + .center, + children: [ + Text( + day['week'], + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + 30.rpx, + letterSpacing: + 0, + ), + ), + Text( + day['date'], + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + fontSize: + 24.rpx, + ), + ), + SizedBox( + height: 6.rpx, + ), + Column( + children: [ + Row( + mainAxisSize: + MainAxisSize + .max, + mainAxisAlignment: + MainAxisAlignment + .center, + children: [ + Text( + '${day['score'] ?? "-"}', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + 48.rpx, + letterSpacing: + 0, + ), + ), + if (day['score'] != + null) + SizedBox( + width: + 2.rpx, + ), + if (day['score'] != + null) + Text( + '分', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + letterSpacing: + 0, + fontSize: + 26.rpx, + ), + ), + ], + ), + Container( + width: 120.rpx, + height: 52.rpx, + decoration: + BoxDecoration( + color: stringToColor( + day['scoreColor'] ?? + "#f3f5f6"), + borderRadius: + BorderRadius + .circular( + 26.rpx), + shape: BoxShape + .rectangle, + ), + alignment: + Alignment + .center, + child: Text( + '${day['scoreType'] ?? "暂无"}', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: day['scoreType'] != + null + ? Colors + .white + : stringToColor( + "#ced1d7"), + letterSpacing: + 0, + fontSize: + 28.rpx, + ), + ), + ) + ], + ) + ], + ), + ), + ); + }) + ], + ), + ), + ], + ), + ), + ...List.generate( + gloablController.model.deviceList.length, + (index) { + var device = gloablController + .model.deviceList[index]; + String rname = device['roomName']; + if (index != 0) { + String lrname = gloablController.model + .deviceList[index - 1]["roomName"]; + if (lrname == rname) { + rname = ""; + } + } + return Column(children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 20.rpx, 20.rpx, 0, 0), + child: Container( + decoration: BoxDecoration(), + alignment: + AlignmentDirectional(-1, 0), + child: rname.isNotEmpty + ? Text( + "$rname", + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: Colors.white, + fontSize: 32.rpx, + letterSpacing: 0, + ), + ) + : SizedBox( + height: 10.rpx, + ), + ), + ), + // getDeviceList(context, device) + ]); + }), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0, 40.rpx, 0, 100.rpx), + child: Container( + width: MediaQuery.sizeOf(context).width, + height: 84.rpx, + decoration: BoxDecoration(), + child: FFButtonWidget( + onPressed: () { + // print('Button pressed ...'); + // Get.toNamed("/homeDeviceType"); + }, + text: '添加新设备', + icon: Icon( + Icons.add, + size: 60.rpx, + ), + options: FFButtonOptions( + height: 80.rpx, + padding: + EdgeInsetsDirectional.fromSTEB( + 48.rpx, 0, 48.rpx, 0), + iconPadding: + EdgeInsetsDirectional.fromSTEB( + 0, 0, 0, 0), + color: stringToColor("#182B7C"), + textStyle: + FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + letterSpacing: 0, + fontSize: 30.rpx), + elevation: 3, + borderSide: BorderSide( + color: Colors.transparent, + width: 1, + ), + borderRadius: BorderRadius.circular( + borderRadius), + ), + ), + ), + ), + ], + ), + ), + if (gloablController.model.deviceList.length == 0) + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0, 0, 0, 80.rpx), + child: Container( + width: MediaQuery.sizeOf(context).width, + padding: EdgeInsets.only( + top: 90.rpx, bottom: 80.rpx), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.circular(borderRadius), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '检测到您当前暂无设备!', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 32.rpx, + letterSpacing: 0, + ), + ), + SizedBox( + height: + MediaQuery.sizeOf(context).height * + 0.037, + ), + Container( + width: MediaQuery.sizeOf(context).width * + 0.54, + height: 90.rpx, + decoration: BoxDecoration( + color: FlutterFlowTheme.of(context) + .secondaryBackground, + borderRadius: BorderRadius.circular(0), + ), + child: FFButtonWidget( + onPressed: () { + // print('Button pressed ...'); + Get.toNamed("/homeDeviceType"); + }, + text: '立即添加一台', + icon: Icon( + Icons.add, + color: FlutterFlowTheme.of(context) + .primaryText, + size: 60.rpx, + ), + options: FFButtonOptions( + iconPadding: + EdgeInsetsDirectional.fromSTEB( + 0, 0, 0, 0), + color: Colors.white, + textStyle: + FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: 'Readex Pro', + color: + FlutterFlowTheme.of( + context) + .primaryText, + letterSpacing: 0, + fontSize: 30.rpx), + elevation: 3, + borderSide: BorderSide( + color: Color(0xFFABB0C0), + width: 1, + ), + borderRadius: + BorderRadius.circular(45.rpx), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ) + ], + ), + ), + ) + + // Padding( + // padding: EdgeInsets.symmetric(horizontal: 30.rpx), + // child: Column( + // children: [ + // Padding( + // padding: EdgeInsets.fromLTRB(17.rpx, 30.rpx, 0, 0), + // child: Row( + // children: [ + // Text('上海 22° 多云', + // style: TextStyle( + // fontSize: 26.rpx, color: Colors.white)), + // Icon(Icons.cloud, + // size: 30.rpx, color: Colors.white), + // ], + // ), + // ), + // ], + // )) + ), + ), + )); + } +} + +class ScoreItem { + final String weekday; // 如“周四” + final String dateStr; // 如“07/03” + final int score; + final bool isToday; + + ScoreItem({ + required this.weekday, + required this.dateStr, + required this.score, + this.isToday = false, + }); +} + +class ScoreCard extends StatelessWidget { + final String selectedUser; + final List scoreList; + final ValueChanged? onUserChanged; + final VoidCallback? onChartPressed; + + const ScoreCard({ + super.key, + required this.selectedUser, + required this.scoreList, + this.onUserChanged, + this.onChartPressed, + }); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: const Color(0xff0F2B44), + borderRadius: BorderRadius.circular(16), + ), + padding: const EdgeInsets.all(12), + child: Column( + children: [ + // 顶部用户选择 + 图标按钮 + Row( + children: [ + DropdownButtonHideUnderline( + child: DropdownButton( + value: selectedUser, + borderRadius: BorderRadius.circular(12), + dropdownColor: const Color(0xff0F2B44), + iconEnabledColor: Colors.white, + style: const TextStyle(color: Colors.white), + items: ['Eason Chan', 'Jay Chou', 'G.E.M.'] + .map((user) => DropdownMenuItem( + value: user, + child: Text(user), + )) + .toList(), + onChanged: onUserChanged, + ), + ), + const Spacer(), + IconButton( + onPressed: onChartPressed, + icon: const Icon(Icons.bar_chart, color: Colors.white), + ), + ], + ), + const SizedBox(height: 12), + // 日期+分数 横向滚动展示 + SizedBox( + height: 70, + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemCount: scoreList.length, + separatorBuilder: (_, __) => const SizedBox(width: 12), + itemBuilder: (context, index) { + final item = scoreList[index]; + final isToday = item.isToday; + + return Container( + padding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + color: isToday + ? Colors.white.withOpacity(0.1) + : Colors.transparent, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(item.weekday, + style: const TextStyle( + color: Colors.white70, fontSize: 12)), + Text(item.dateStr, + style: const TextStyle( + color: Colors.white54, fontSize: 10)), + const SizedBox(height: 4), + Text( + item.score.toString(), + style: TextStyle( + color: Colors.white, + fontWeight: + isToday ? FontWeight.bold : FontWeight.normal, + fontSize: 16, + ), + ), + ], + ), + ); + }, + ), + ) + ], + ), + ); + } +} diff --git a/lib/pages/device_control/new_message_page copy.dart b/lib/pages/device_control/new_message_page copy.dart new file mode 100644 index 0000000..445ae72 --- /dev/null +++ b/lib/pages/device_control/new_message_page copy.dart @@ -0,0 +1,304 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/color/app_uri_status.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/component/NullDataComponentWidget.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; +import 'package:vbvs_app/controller/message/message_controller.dart'; +import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; +import 'package:vbvs_app/pages/main_bottom/component/MessageWidgetWidget.dart'; + +class MessagePage extends StatefulWidget { + const MessagePage({super.key}); + + @override + State createState() => _MessagePageState(); +} + +class _MessagePageState extends State { + ThemeController themeController = Get.find(); + MessageController messageController = Get.find(); + late PageController _pageController; + + @override + void initState() { + super.initState(); + _pageController = + PageController(initialPage: messageController.model.type == 1 ? 0 : 1); + messageController.getMessageStatus(); + _fetchMessageData(); + } + + void _fetchMessageData() { + String type = messageController.model.type == 1 ? "app_vsm" : "app_system"; + messageController.updateMessageStatus(type: type); + messageController.getMessageList().then((response) { + if (response.code != HttpStatusCodes.ok) { + TopSlideNotification.show( + Get.context!, + text: response.msg ?? "服务器.失败".tr, + textColor: themeController.currentColor.sc9, + ); + } + }); + } + + void _onTabChanged(int index) { + messageController.model.type = index == 0 ? 1 : 2; + messageController.updateAll(); + _fetchMessageData(); + _pageController.animateToPage(index, + duration: const Duration(milliseconds: 300), curve: Curves.easeInOut); + } + + void _onPageChanged(int index) { + int newType = index == 0 ? 1 : 2; + if (messageController.model.type != newType) { + messageController.model.type = newType; + messageController.updateAll(); + _fetchMessageData(); + } + } + + @override + void dispose() { + _pageController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarIconBrightness: Brightness.light, + )); + + return LayoutBuilder( + builder: (context, boxConstraints) => GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/img/bgNoImg.png'), + fit: BoxFit.fill, + ), + ), + child: Scaffold( + appBar: AppBar( + backgroundColor: themeController.currentColor.sc17, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: themeController.currentColor.sc3), + toolbarHeight: 140.rpx, + titleSpacing: 0, + title: Padding( + padding: EdgeInsetsDirectional.fromSTEB(40.rpx, 0, 0, 0), + child: Container( + width: double.infinity, + height: 140.rpx, + child: Column( + children: [ + SizedBox(height: 40.rpx), + Expanded( + child: Stack( + alignment: Alignment.bottomLeft, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Obx(() { + return ClickableContainer( + padding: EdgeInsets.all(0), + backgroundColor: Colors.transparent, + highlightColor: + themeController.currentColor.sc21, + borderRadius: 8.rpx, + onTap: () => _onTabChanged(0), + child: Container( + width: 160.rpx, + alignment: Alignment.center, + child: Stack( + alignment: Alignment.center, + clipBehavior: Clip.none, + children: [ + Text( + '体征消息'.tr, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Inter', + fontSize: AppConstants() + .title_text_fontSize, + color: + messageController + .model.type == + 2 + ? themeController + .currentColor.sc3 + : themeController + .currentColor.sc2, + ), + ), + Obx(() { + return messageController.model + .body_message_read == + 1 + ? Positioned( + top: -4, + right: -14, + child: Container( + width: 8, + height: 8, + decoration: + const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + ), + ) + : const SizedBox.shrink(); + }), + ], + ), + ), + ); + }), + Obx(() { + return ClickableContainer( + padding: EdgeInsets.all(0), + backgroundColor: Colors.transparent, + highlightColor: + themeController.currentColor.sc21, + borderRadius: 8.rpx, + onTap: () => _onTabChanged(1), + child: Container( + width: 160.rpx, + alignment: Alignment.center, + child: Stack( + alignment: Alignment.center, + clipBehavior: Clip.none, + children: [ + Text( + '系统消息'.tr, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Inter', + fontSize: AppConstants() + .title_text_fontSize, + color: + messageController + .model.type == + 1 + ? themeController + .currentColor.sc3 + : themeController + .currentColor.sc2, + ), + ), + Obx(() { + return messageController.model + .system_message_read == + 1 + ? Positioned( + top: -4, + right: -14, + child: Container( + width: 8, + height: 8, + decoration: + const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + ), + ) + : const SizedBox.shrink(); + }), + ], + ), + ), + ); + }), + ].divide(SizedBox(width: 10.rpx)), + ), + Obx(() { + double lineWidth = 170.rpx; + return AnimatedPositioned( + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + bottom: 0, + left: messageController.model.type == 1 + ? 0 + : 170.rpx, + child: Container( + width: lineWidth, + height: 4.rpx, + decoration: BoxDecoration( + color: themeController.currentColor.sc2, + borderRadius: BorderRadius.circular(2.rpx), + ), + ), + ); + }), + ], + ), + ), + SizedBox(height: 17.rpx), + ], + ), + ), + ), + actions: const [], + centerTitle: false, + ), + backgroundColor: Colors.transparent, + body: SafeArea( + top: true, + child: PageView( + controller: _pageController, + onPageChanged: _onPageChanged, + children: [ + Obx(() { + final list = messageController.messageList.value; + return list.isEmpty + ? const NullDataWidget() + : _buildMessageListView(list); + }), + Obx(() { + final list = messageController.messageList.value; + return list.isEmpty + ? const NullDataWidget() + : _buildMessageListView(list); + }), + ], + ), + ), + ), + ), + ), + ); + } + + Widget _buildMessageListView(List dataList) { + return Container( + width: double.infinity, + padding: EdgeInsets.symmetric(horizontal: 30.rpx), + child: SingleChildScrollView( + child: Column( + children: [ + SizedBox(height: 30.rpx), + ...dataList + .map((item) => MessageWidgetWidget(data: item)) + .toList() + .divide(SizedBox(height: 30.rpx)), + SizedBox(height: 30.rpx), + ], + ), + ), + ); + } +} diff --git a/lib/pages/device_control/new_mine_page.dart b/lib/pages/device_control/new_mine_page.dart new file mode 100644 index 0000000..d687b1b --- /dev/null +++ b/lib/pages/device_control/new_mine_page.dart @@ -0,0 +1,416 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; +import 'package:vbvs_app/controller/mh/muser_info_controller.dart'; +import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; + +import 'package:vbvs_app/enum/LoginStatus.dart'; + +class NewMinePage extends StatefulWidget { + const NewMinePage({super.key}); + + @override + State createState() => _MinePageState(); +} + +class _MinePageState extends State { + GlobalController globalController = Get.find(); + MUserInfoController userInfoController = Get.find(); + ThemeController themeController = Get.find(); + final GlobalKey _textKey = GlobalKey(); + + double _textHalfWidth = 0; + @override + void initState() { + super.initState(); + _calculateTextHalfWidth('Eason Chan'); + } + + void _calculateTextHalfWidth(String text) { + final textSpan = TextSpan( + text: text, + style: TextStyle( + fontSize: 30.rpx, + height: 1, + ), + ); + final textPainter = TextPainter( + text: textSpan, + textDirection: TextDirection.ltr, + ); + textPainter.layout(); // 计算文本宽度 + setState(() { + _textHalfWidth = textPainter.width / 2; + }); + } + + @override + Widget build(BuildContext context) { + SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, // 这里设置你希望的颜色 + statusBarIconBrightness: Brightness.light, // 状态栏图标的亮度 + )); + int login = userInfoController.model.login!; + return LayoutBuilder( + builder: (context, bodySize) => GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + actions: [ + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.transparent, + padding: EdgeInsets.only(right: 38.rpx), + onTap: () { + // if (userInfoController.model.login == + // LoginStatus.LOGIN.code) { + // TopSlideNotification.show( + // context, + // text: "待开发功能".tr, + // ); + // } else { + // TopSlideNotification.show( + // context, + // text: "必须登录提示".tr, + // textColor: themeController.currentColor.sc9, + // ); + // Get.toNamed("/loginPage"); + // } + Get.toNamed('/messagePage'); + }, + child: Container( + height: 42.rpx, + width: 42.rpx, + child: SvgPicture.asset( + 'assets/img/icon/message.svg', + color: Colors.white, + // color: Colors.white, + ))), + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.transparent, + padding: EdgeInsets.only(right: 11.rpx), + onTap: () { + Get.toNamed("/peopleInfoPage"); + }, + child: Container( + height: 42.rpx, + width: 42.rpx, + child: SvgPicture.asset( + 'assets/img/icon/people_info.svg', + color: Colors.white, + ))), + ], + ), + body: SafeArea( + top: true, + child: Container( + height: bodySize.maxHeight, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.only(top: 30.rpx), + child: Container( + width: 120.rpx, + height: 120.rpx, + clipBehavior: Clip.antiAlias, + decoration: const BoxDecoration( + shape: BoxShape.circle, + ), + child: login == 1 + ? (userInfoController.model.user!.avatar == null || + userInfoController + .model.user!.avatar!.isEmpty + ? Image.asset( + "assets/images/people_avatar.png", + fit: BoxFit.cover, + ) + : Image.network( + userInfoController.model.user!.avatar!, + fit: BoxFit.cover, + )) + : Image.asset( + "assets/images/people_avatar.png", + fit: BoxFit.cover, + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.only(top: 19.rpx), + child: Container( + width: double.infinity, + decoration: const BoxDecoration(), + child: Stack( + alignment: Alignment.center, // 使子组件在Stack中居中 + children: [ + Container( + // width: 194.rpx, + height: 63.rpx, + child: Column( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.center, // 文字水平居中 + children: [ + Text( + 'Eason Chan', + style: TextStyle( + fontSize: 30.rpx, + color: Colors.white, + height: 1), + ), + Text( + '135****2598', + style: TextStyle( + fontSize: 26.rpx, + color: const Color(0XFF929699), + height: 1), + ), + ], + ), + ), + Positioned( + left: MediaQuery.of(context).size.width / 2 + + _textHalfWidth + + 30.rpx, + top: -10.rpx, + child: ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: const Color(0xFF055466), + padding: EdgeInsets.zero, + onTap: () { + Get.toNamed("/editUserInfoPage"); + }, + child: Container( + width: 42.rpx, + height: 42.rpx, + alignment: Alignment.center, + child: SvgPicture.asset( + 'assets/images/edit.svg', + color: Colors.white, + width: 18.rpx, + height: 18.rpx, + ), + )), + ), + ], + ), + ), + ), + + Container( + margin: EdgeInsets.only( + left: 60.rpx, right: 60.rpx, top: 94.rpx), + child: Text( + '对已绑定的智能设备进行个性化配置,以获得更好的体验,', + style: TextStyle( + fontSize: 26.rpx, + color: const Color(0XFF929699), + height: 1), + )), + Padding( + padding: EdgeInsets.only(top: 46.rpx, bottom: 109.rpx), + child: ElevatedButton( + onPressed: () {}, + style: ElevatedButton.styleFrom( + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + backgroundColor: const Color(0XFF85F5FF), + side: const BorderSide(color: Color(0XFF74DAE5)), + // foregroundColor: Colors.cyanAccent, + minimumSize: Size(260.rpx, 60.rpx), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + ), + child: Text( + '我的智能床', + style: TextStyle( + fontSize: 26.rpx, color: const Color(0xFF003058)), + ), + ), + ), + // 使用 Expanded 让滚动区域占据可用空间 + // SizedBox(height: 109.rpx), + Expanded( + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Colors.transparent, + ), + child: SingleChildScrollView( + // 直接使用 SingleChildScrollView + child: Column( + children: [ + _buildListTile( + Icons.receipt_long, '我的订单', '快捷查看我在网上的订单记录', + showTopLine: true), + _buildListTile(Icons.store_mall_directory, '门店体验', + '如果想免费体验智能设备,可在此进行提前预约', + path: "/experienceStorePage"), + _buildListTile( + Icons.build, + '设备报修', + '当您的智能设备需要报修时,可以通过该功能联系解决', + path: '/deviceRepairPage', + ), + _buildListTile( + Icons.shopping_cart, '网上商城', '最新的智能产品线上购买服务'), + _buildListTile( + Icons.location_on, '地址管理', '用于收货和报修时联系您', + path: "/addressListPage"), + _buildListTile(Icons.help_outline, '问题与帮助', + '常见的问题汇总,如:智能床连接流程、如何查看睡眠报告', + path: "/issueListpage"), + _buildListTile( + Icons.headset_mic, + '在线客服', + '购买和使用智能床过程中,如果遇到疑问可与客服进行联系', + ), + ], + ), + ), + ), + ), // 使用 Expanded 让滚动区域占据可用空间 + Padding( + padding: + EdgeInsets.fromLTRB(30.rpx, 24.rpx, 30.rpx, 50.rpx), + child: _buildSettingButton(), + ), + ], + ), + // Column( + // mainAxisSize: MainAxisSize.max, + // children: [ + + // ], + // ), + ), + ), + ), + ), + ), + ); + } + + /// 构建列表项(带分隔线) + Widget _buildListTile( + IconData icon, + String title, + String subtitle, { + // VoidCallback? onTap, + String? path, + bool showTopLine = false, + }) { + return ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.white, + padding: EdgeInsets.all(0.rpx), + onTap: () { + Get.toNamed(path!); + }, + child: Container( + decoration: BoxDecoration( + border: Border( + top: showTopLine + ? BorderSide(color: Color(0xFF929699), width: 2.rpx) + : BorderSide.none, + bottom: BorderSide(color: Color(0xFF929699), width: 2.rpx), + ), + ), + height: 116.rpx, + child: Padding( + padding: EdgeInsets.fromLTRB(40.rpx, 0.rpx, 40.rpx, 0.rpx), + child: Row( + children: [ + Icon(icon, color: const Color(0xFF85F5FF), size: 28.rpx), + SizedBox(width: 30.rpx), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, // 垂直方向居中对齐 + children: [ + Text( + title, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // SizedBox(height: 6.rpx), // 加点间距 + Text( + subtitle, + style: TextStyle( + color: Color(0xFF929699), + fontSize: 20.rpx, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + softWrap: true, // 允许换行 + ), + ], + ), + ), + ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Colors.transparent, + padding: EdgeInsets.only(right: 0), + onTap: () {}, + child: Container( + height: 30.rpx, + width: 30.rpx, + child: SvgPicture.asset( + 'assets/img/icon/expand.svg', + color: Colors.white, + ) + // Icon( + // Icons.arrow_forward_ios, + // color: Colors.white, + // // size: 14.rpx, + // ), + )), + ], + ), + ), + )); + } + + Widget _buildSettingButton() { + return Container( + width: double.infinity, + height: MediaQuery.sizeOf(context).height * 0.055, + constraints: BoxConstraints( + minHeight: 90.rpx, + ), + child: ElevatedButton( + onPressed: () { + Get.toNamed("/settingPage"); + }, + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF04345E), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.rpx)), + ), + child: + Text('设置', style: TextStyle(fontSize: 26.rpx, color: Colors.white)), + ), + ); + } +} diff --git a/lib/pages/device_control/new_settingPage.dart b/lib/pages/device_control/new_settingPage.dart new file mode 100644 index 0000000..1906e4f --- /dev/null +++ b/lib/pages/device_control/new_settingPage.dart @@ -0,0 +1,618 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; +import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; + +class SettingPage extends StatefulWidget { + @override + _SettingPageState createState() => _SettingPageState(); +} + +class _SettingPageState extends State { + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, bodySize) { + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + titleSpacing: 0, + automaticallyImplyLeading: false, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '设置', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(30.rpx, 0, 30.rpx, 0), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 25.rpx, 0.rpx, 0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: Color(0xFF003058), + borderRadius: BorderRadius.circular( + AppConstants().normal_container_radius), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 0, 0.rpx, 0), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + ClickableContainer( + backgroundColor: + Colors.transparent, // 容器背景色 + highlightColor: themeController + .currentColor.sc21, // 点击时的背景色 + padding: EdgeInsetsDirectional.fromSTEB( + 40.rpx, 0.rpx, 40.rpx, 0.rpx), + onTap: () { + TopSlideNotification.show(context, + text: "待开发功能".tr); + }, + child: Container( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 30.rpx, 0.rpx, 30.rpx), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Text('修改密码', + style: TextStyle( + fontSize: 30.rpx, + color: Colors.white, + height: 1)), + ].divide(SizedBox(width: 22.rpx)), + ), + SvgPicture.asset( + 'assets/img/icon/arrow_right.svg', + width: 8.rpx, + height: 15 + .rpx, // 如果 SVG 中没有固定颜色,可以这样设置 + color: themeController + .currentColor.sc3, + ), + // Row( + // mainAxisSize: MainAxisSize.max, + // children: [ + // Text( + // '深色', + // style: FlutterFlowTheme.of( + // context) + // .bodyMedium + // .override( + // fontFamily: 'Inter', + // color: + // Color(0xFFD9E3EB), + // fontSize: 26.rpx, + // letterSpacing: 0.0, + // ), + // ), + + // ].divide(SizedBox(width: 28.rpx)), + // ), + ], + ), + ), + ), + ), + ClickableContainer( + backgroundColor: + Colors.transparent, // 容器背景色 + highlightColor: themeController + .currentColor.sc21, // 点击时的背景色 + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 0.rpx, 0.rpx, 0.rpx), + onTap: () { + print('点击了容器'); + Get.toNamed("/aboutUsPage"); + }, + child: Container( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 40.rpx, 30.rpx, 40.rpx, 30.rpx), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Text( + '当前版本', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: 'Inter', + color: Colors.white, + fontSize: AppConstants() + .title_text_fontSize, + letterSpacing: 0.0, + lineHeight: 1.0, + ), + ), + ].divide(SizedBox(width: 22.rpx)), + ), + Text('SWES3.513.4', + style: TextStyle( + color: Colors.white, + fontSize: 26.rpx, + height: 1)), + // SvgPicture.asset( + // 'assets/img/icon/arrow_right.svg', + // width: 8.rpx, + // height: 14 + // .rpx, // 如果 SVG 中没有固定颜色,可以这样设置 + // color: themeController + // .currentColor.sc3, + // ), + ], + ), + ), + ), + ), + ClickableContainer( + backgroundColor: + Colors.transparent, // 容器背景色 + highlightColor: themeController + .currentColor.sc21, // 点击时的背景色 + padding: EdgeInsetsDirectional.fromSTEB( + 40.rpx, 0.rpx, 40.rpx, 0.rpx), + onTap: () { + // TopSlideNotification.show(context, + // text: "待开发功能".tr); + Get.toNamed("/languagePage"); + }, + child: Container( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 30.rpx, 0.rpx, 30.rpx), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Text( + '切换语言', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: 'Inter', + color: Colors.white, + fontSize: AppConstants() + .title_text_fontSize, + letterSpacing: 0.0, + lineHeight: 1.0), + ), + ].divide(SizedBox(width: 22.rpx)), + ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Obx(() { + return Text( + languageController + .selectLanguage + .value! + .language_name!, + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: 'Inter', + color: + Color(0xFFD9E3EB), + fontSize: 26.rpx, + letterSpacing: 0.0, + lineHeight: 1.0, + ), + ); + }), + + // SvgPicture.asset( + // 'assets/img/icon/arrow_right.svg', + // width: 8.rpx, + // height: 15 + // .rpx, // 如果 SVG 中没有固定颜色,可以这样设置 + // color: themeController + // .currentColor.sc3, + // ), + ].divide(SizedBox(width: 28.rpx)), + ), + ], + ), + ), + ), + ), + ClickableContainer( + backgroundColor: + Colors.transparent, // 容器背景色 + highlightColor: themeController + .currentColor.sc21, // 点击时的背景色 + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 0.rpx, 0.rpx, 0.rpx), + onTap: () { + print('点击了容器'); + Get.toNamed("/aboutUsPage"); + }, + child: Container( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 40.rpx, 30.rpx, 40.rpx, 30.rpx), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Text( + '设置页.关于我们'.tr, + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: 'Inter', + color: Colors.white, + fontSize: AppConstants() + .title_text_fontSize, + letterSpacing: 0.0, + lineHeight: 1.0, + ), + ), + ].divide(SizedBox(width: 22.rpx)), + ), + SvgPicture.asset( + 'assets/img/icon/arrow_right.svg', + width: 8.rpx, + height: 14 + .rpx, // 如果 SVG 中没有固定颜色,可以这样设置 + color: themeController + .currentColor.sc3, + ), + ], + ), + ), + ), + ), + ClickableContainer( + backgroundColor: + Colors.transparent, // 容器背景色 + highlightColor: themeController + .currentColor.sc21, // 点击时的背景色 + padding: EdgeInsetsDirectional.fromSTEB( + 40.rpx, 0.rpx, 40.rpx, 0.rpx), + onTap: () { + TopSlideNotification.show(context, + text: "待开发功能".tr); + }, + child: Container( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 30.rpx, 0.rpx, 30.rpx), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Text( + '设置页.用户协议'.tr, + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: 'Inter', + color: Colors.white, + fontSize: AppConstants() + .title_text_fontSize, + letterSpacing: 0.0, + lineHeight: 1.0, + ), + ), + ].divide(SizedBox(width: 22.rpx)), + ), + SvgPicture.asset( + 'assets/img/icon/arrow_right.svg', + width: 8.rpx, + height: 15 + .rpx, // 如果 SVG 中没有固定颜色,可以这样设置 + color: themeController + .currentColor.sc3, + ), + ], + ), + ), + ), + ), + ClickableContainer( + backgroundColor: + Colors.transparent, // 容器背景色 + highlightColor: themeController + .currentColor.sc21, // 点击时的背景色 + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 0.rpx, 0.rpx, 0.rpx), + onTap: () { + TopSlideNotification.show(context, + text: "待开发功能".tr); + }, + child: Container( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 40.rpx, 30.rpx, 40.rpx, 30.rpx), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisSize: MainAxisSize.max, + children: [ + Text( + '设置页.隐私协议'.tr, + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: 'Inter', + color: Colors.white, + fontSize: AppConstants() + .title_text_fontSize, + letterSpacing: 0.0, + lineHeight: 1.0, + ), + ), + ].divide(SizedBox(width: 22.rpx)), + ), + SvgPicture.asset( + 'assets/img/icon/arrow_right.svg', + width: 8.rpx, + height: 14 + .rpx, // 如果 SVG 中没有固定颜色,可以这样设置 + color: themeController + .currentColor.sc3, + ), + ], + ), + ), + ), + ), + ] + .divide(SizedBox(height: 0.rpx)) + .addToStart(SizedBox(height: 30.rpx)) + .addToEnd(SizedBox(height: 30.rpx)), + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 174.rpx, 0.rpx, 0), + child: CustomCard( + borderRadius: 16.rpx, + + // 圆角半径 + onTap: () { + // ApiResponse apiResponse = + // userInfoController.logOut(); + // TopSlideNotification.show( + // context, + // text: apiResponse.msg!, + // textColor: + // apiResponse.code == HttpStatusCodes.ok + // ? themeController.currentColor.sc2 + // : themeController.currentColor.sc9, + // ); + // if (apiResponse.code == HttpStatusCodes.ok) { + // Get.offAllNamed("/mianPageBottomChange"); + // } + }, + colors: [ + Color(0XFF84F5FF), + ], // 渐变色是同一个色,也可以根据需要调整 + child: Container( + width: + // MediaQuery.sizeOf(context).width * 0.66, + bodySize.maxWidth, + height: MediaQuery.sizeOf(context).height * 0.055, + constraints: BoxConstraints( + minWidth: 500.rpx, + minHeight: 90.rpx, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '设置页.退出登录'.tr, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + color: Color(0xFF003058), + fontFamily: 'Inter', + fontSize: AppConstants() + .normal_text_fontSize, + letterSpacing: 0.0, + ), + ), + ].divide(SizedBox( + width: 17.rpx, + )), + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 100.rpx, 20.rpx, 100.rpx, 0), + child: CustomCard( + borderRadius: + AppConstants().button_container_radius, // 圆角半径 + onTap: () { + TopSlideNotification.show( + context, + text: "待开发功能".tr, + ); + }, + colors: [ + Colors.transparent, + ], // 渐变色是同一个色,也可以根据需要调整 + child: Container( + width: + // MediaQuery.sizeOf(context).width * 0.66, + bodySize.maxWidth, + height: MediaQuery.sizeOf(context).height * 0.055, + constraints: BoxConstraints( + minWidth: 500.rpx, + minHeight: 90.rpx, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '设置页.注销账号'.tr, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + color: + themeController.currentColor.sc9, + fontFamily: 'Inter', + fontSize: AppConstants() + .normal_text_fontSize, + letterSpacing: 0.0, + ), + ), + ].divide(SizedBox( + width: 17.rpx, + )), + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 135.rpx, 0.rpx, 0), + child: ClickableContainer( + borderRadius: + AppConstants().button_container_radius, // 圆角半径 + onTap: () {}, + backgroundColor: + Colors.transparent, // 渐变色是同一个色,也可以根据需要调整 + highlightColor: themeController.currentColor.sc5, + padding: EdgeInsetsDirectional.fromSTEB( + 0.rpx, 0.rpx, 0.rpx, 0), + child: Container( + width: + // MediaQuery.sizeOf(context).width * 0.66, + bodySize.maxWidth, + height: MediaQuery.sizeOf(context).height * 0.055, + constraints: BoxConstraints( + minWidth: 500.rpx, + minHeight: 90.rpx, + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'ICP备案号:浙ICP备2023000785号-1'.tr, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + color: themeController + .currentColor.sc4, + fontFamily: 'Inter', + fontSize: AppConstants() + .smaller_text_fontSize, + letterSpacing: 0.0, + ), + ), + Text( + 'Copyright © 202-2025 嘉兴太和信息技术有限责任公司 版权所有' + .tr, + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + color: themeController + .currentColor.sc4, + fontFamily: 'Inter', + fontSize: AppConstants() + .smaller_text_fontSize, + letterSpacing: 0.0, + ), + ), + ].divide(SizedBox( + height: 17.rpx, + ))), + ), + ), + ), + ], + ), + ), + ), + ), + )), + ); + }); + } +} diff --git a/lib/pages/device_control/people_info.dart b/lib/pages/device_control/people_info.dart new file mode 100644 index 0000000..6b1bbce --- /dev/null +++ b/lib/pages/device_control/people_info.dart @@ -0,0 +1,815 @@ +import 'dart:async'; + +import 'package:ef/base/widget/flutterflow/FlutterFlowTheme.dart'; +import 'package:ef/ef.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; +import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; +import 'package:vbvs_app/controller/mh/people_info_controller.dart'; +import 'package:vbvs_app/pages/common/selectDialog.dart'; + +class PeopleInfoPage extends StatefulWidget { + const PeopleInfoPage({super.key}); + + @override + State createState() => _PeopleInfoState(); +} + +class _PeopleInfoState extends State { + get controller => Get.find(); + + get glcontroller => Get.find(); + + // @override + // void initState() { + // super.initState(); + // Timer(const Duration(milliseconds: 100), () { + // controller.getPeoples(); + // }); + // } + + getLine() { + return Container( + height: 1, + color: stringToColor("#152676"), + ); + } + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, boxConstraints) => GestureDetector( + // onTap: () => FocusScope.of(context).unfocus(), + onTap: () { + // 触摸收起键盘 + FocusScope.of(context).requestFocus(FocusNode()); + }, + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: Colors.white), + titleSpacing: 0, + title: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '人员资料', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + Positioned( + right: 30.rpx, + child: CustomCard( + borderRadius: 10, + gradientDirection: GradientDirection.vertical, + onTap: () { + // bool isOk = true; + // for (var i = 0; i < 2; i++) { + // var d = controller.model.peopleList[i]; + // print("${d.toJson()}"); + // String before = "人员信息${i == 0 ? "A" : "B"}:"; + // if (isOk && + // d.height != null && + // d.height != "" && + // int.tryParse("${d.height}") == null) { + // showToast("$before身高请输入数字"); + // isOk = false; + // } + // if (isOk && + // d.weight != null && + // d.weight != "" && + // int.tryParse("${d.weight}") == null) { + // showToast("$before体重请输入数字"); + // isOk = false; + // } + // if (isOk && + // d.tel != null && + // d.tel != "" && + // MyUtils.isValidPhoneNumber("${d.tel}") == + // false) { + // showToast("$before请输入正确的电话"); + // isOk = false; + // } + // if (isOk && + // d.emergencyContact != null && + // d.emergencyContact != "" && + // MyUtils.isValidPhoneNumber( + // "${d.emergencyContact}") == + // false) { + // showToast("$before请输入正确的紧急联系人电话"); + // isOk = false; + // } + // if (isOk) { + // controller.savePeoples().then((d) { + // showToast("保存成功", color: color_success); + // }).catchError((d) { + // print("$d"); + // showToast("保存失败"); + // }); + // } + // } + // controller.model.peopleList.forEach((d) {}); + }, + colors: const [ + Color(0xFFFCFCFC), + Color(0xFFF8FAF9), + Color(0XFFECF6F3), + Color(0XFFD9F0E9), + Color(0xFFCEECE3) + ], + child: Container( + width: 120.rpx, + height: 60.rpx, + alignment: Alignment.center, + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(5), + // color: stringToColor("#182B7C"), + // ), + child: Text( + "保存", + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: stringToColor("#9EA4B7"), + letterSpacing: 0, + fontSize: 30.rpx, + ), + ), + ), + )) + ], + ), + ), + actions: [], + centerTitle: false, + ), + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Container( + padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx), + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 1.123, + // decoration: BoxDecoration( + // color: Colors.transparent, + // image: DecorationImage( + // image: AssetImage("assets/images/background.png"), + // fit: BoxFit.cover, + // ), + // ), + child: SingleChildScrollView( + child: Column( + children: [ + ...List.generate( + "${glcontroller.model.deviceMain["bindMacB"]}" + .length > + 6 + ? 2 + : 1, (index) { + String location_ = ""; + if ("${glcontroller.model.deviceMain["bindMacB"]}" + .length > + 6 && + (glcontroller.model.mainDevicePeople[0] + ?["direction"] == + 1 || + glcontroller.model.mainDevicePeople[1] + ?["direction"] == + 1)) { + location_ = + "${glcontroller.model.mainDevicePeople[index]?["direction"] == 1 ? '左侧' : '右侧'}"; + } + return Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only( + top: index == 0 ? 30.rpx : 90.rpx, + bottom: 20.rpx), + child: Text( + "人员信息${index == 0 ? "A" : "B"}", + style: TextStyle( + color: Colors.white, fontSize: 30.rpx), + ), + ), + Container( + padding: + EdgeInsets.only(left: 30.rpx, right: 30.rpx), + child: Column( + children: [ + if (location_.isNotEmpty) + Container( + width: double.infinity, + height: + MediaQuery.sizeOf(context).height * + 0.064, + decoration: BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '校准位置', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + Text( + '$location_', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + ], + ), + ), + getLine(), + Container( + width: double.infinity, + height: MediaQuery.sizeOf(context).height * + 0.064, + decoration: BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '性名', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + Container( + width: 300.rpx, + child: TextField( + obscureText: false, + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 30.rpx, + color: Colors.white), + decoration: const InputDecoration( + fillColor: Colors.transparent, + filled: true, + hintText: "请输入姓名", + hintStyle: TextStyle( + color: Colors.white), + border: InputBorder.none, + contentPadding: + EdgeInsets.all(0)), + onChanged: (value) { + controller.model.peopleList[index] + .name = value; + controller.updateAll(); + }, + controller: controller.onReDraw( + TextEditingController( + text: controller + .model + .peopleList[index] + .name ?? + ""), + (textEditingController) { + textEditingController.text = + controller + .model + .peopleList[index] + .name ?? + ""; + }, "people_name_$index"), + ), + ), + ], + ), + ), + getLine(), + Obx( + () => Container( + width: double.infinity, + height: + MediaQuery.sizeOf(context).height * + 0.064, + decoration: BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '性别', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + InkWell( + onTap: () { + // 触摸收起键盘 + FocusScope.of(context) + .requestFocus(FocusNode()); + Future.delayed( + const Duration( + milliseconds: 250), () { + // 延迟执行的代码 + showOneSelectionDialog(context, + arr: ["女", "男"], + checkIndex: controller + .model + .peopleList[ + index] + .sex == + "女" + ? 0 + : 1, + checkChange: (sindex) { + controller + .model + .peopleList[index] + .sex = + (sindex == 0 ? '女' : '男'); + controller.updateAll(); + print("sex $sindex"); + }).then((d) { + // Timer(Duration.zero, () { + // FocusScope.of(context).unfocus(); + // }); + }); + }); + }, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + width: 200.rpx, + child: Text( + '${controller.model.peopleList[index].sex}', + textAlign: TextAlign.right, + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: Colors.white, + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + ), + SizedBox( + width: 16.rpx, + ), + Icon( + Icons.expand_more, + color: Colors.white, + size: 48.rpx, + ), + ], + ), + ), + ], + ), + ), + ), + getLine(), + Container( + width: double.infinity, + height: MediaQuery.sizeOf(context).height * + 0.064, + decoration: BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '身高(cm)', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + Container( + width: 300.rpx, + child: TextField( + obscureText: false, + keyboardType: TextInputType.number, + textInputAction: + TextInputAction.done, + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 30.rpx, + color: Colors.white), + decoration: InputDecoration( + fillColor: Colors.transparent, + filled: true, + hintText: "请输入身高(厘米)", + hintStyle: TextStyle( + color: Colors.white), + border: InputBorder.none, + contentPadding: + EdgeInsets.all(0)), + onChanged: (value) { + controller.model.peopleList[index] + .height = value; + controller.updateAll(); + }, + controller: controller.onReDraw( + TextEditingController( + text: controller + .model + .peopleList[index] + .height ?? + ""), + (textEditingController) { + textEditingController.text = + controller + .model + .peopleList[index] + .height ?? + ""; + }, "people_height_$index"), + ), + ) + ], + ), + ), + getLine(), + Container( + width: double.infinity, + height: MediaQuery.sizeOf(context).height * + 0.064, + decoration: BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '体重(kg)', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + Container( + width: 300.rpx, + child: TextField( + obscureText: false, + keyboardType: TextInputType.number, + textInputAction: + TextInputAction.done, + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 30.rpx, + color: Colors.white), + decoration: InputDecoration( + fillColor: Colors.transparent, + filled: true, + hintText: "请输入体重(公斤)", + hintStyle: TextStyle( + color: Colors.white), + border: InputBorder.none, + contentPadding: + EdgeInsets.all(0)), + onChanged: (value) { + controller.model.peopleList[index] + .weight = value; + controller.updateAll(); + }, + controller: controller.onReDraw( + TextEditingController( + text: controller + .model + .peopleList[index] + .weight ?? + ""), + (textEditingController) { + textEditingController.text = + controller + .model + .peopleList[index] + .weight ?? + ""; + }, "people_weight_$index"), + ), + ), + ], + ), + ), + getLine(), + Obx( + () => Container( + width: double.infinity, + height: + MediaQuery.sizeOf(context).height * + 0.064, + decoration: BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '生日', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + InkWell( + onTap: () { + // 触摸收起键盘 + FocusScope.of(context) + .requestFocus(FocusNode()); + Future.delayed( + const Duration( + milliseconds: 250), () { + // 延迟执行的代码 + showDateSelectionDialog(context, + checkDate: controller + .model + .peopleList[index] + .birthday ?? + DateTime.now(), + checkChange: (DateTime d) { + controller + .model + .peopleList[index] + .birthday = d; + controller.updateAll(); + print("$d"); + }).then((d) { + // Timer(Duration.zero, () { + // FocusScope.of(context).unfocus(); + // }); + }); + }); + }, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + constraints: BoxConstraints( + minWidth: 200.rpx), + child: Text( + controller + .model + .peopleList[ + index] + .birthday != + null + ? DateFormat( + "yyyy年MM月dd日") + .format(controller + .model + .peopleList[ + index] + .birthday!) + : '', + textAlign: TextAlign.right, + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: Colors.white, + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + ), + SizedBox( + width: 16.rpx, + ), + Icon( + Icons.expand_more, + color: Colors.white, + size: 48.rpx, + ), + ], + ), + ), + ], + ), + ), + ), + // getLine(), + // Container( + // width: double.infinity, + // height: MediaQuery.sizeOf(context).height * + // 0.064, + // decoration: BoxDecoration(), + // child: Row( + // mainAxisSize: MainAxisSize.max, + // mainAxisAlignment: + // MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // '电话', + // style: FlutterFlowTheme.of(context) + // .bodyMedium + // .override( + // fontFamily: 'Readex Pro', + // color: Color(0xFF9EA4B7), + // fontSize: 30.rpx, + // letterSpacing: 0, + // ), + // ), + // Container( + // width: 300.rpx, + // child: TextField( + // obscureText: false, + // keyboardType: TextInputType.number, + // textInputAction: + // TextInputAction.done, + // textAlign: TextAlign.right, + // style: TextStyle( + // fontSize: 30.rpx, + // color: Colors.white), + // decoration: InputDecoration( + // fillColor: Colors.transparent, + // filled: true, + // hintText: "请输入电话", + // hintStyle: TextStyle( + // color: Colors.white), + // border: InputBorder.none, + // contentPadding: + // EdgeInsets.all(0)), + // onChanged: (value) { + // controller.model.peopleList[index] + // .tel = value; + // controller.updateAll(); + // }, + // controller: controller.onReDraw( + // TextEditingController( + // text: controller + // .model + // .peopleList[index] + // .tel ?? + // ""), + // (textEditingController) { + // textEditingController.text = + // controller + // .model + // .peopleList[index] + // .tel ?? + // ""; + // }, "people_tel_$index"), + // ), + // ), + // ], + // ), + // ), + getLine(), + Container( + width: double.infinity, + height: MediaQuery.sizeOf(context).height * + 0.064, + decoration: BoxDecoration(), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '联系人', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + Container( + width: 300.rpx, + child: TextField( + obscureText: false, + keyboardType: TextInputType.number, + textInputAction: + TextInputAction.done, + textAlign: TextAlign.right, + style: TextStyle( + fontSize: 30.rpx, + color: Colors.white), + decoration: InputDecoration( + fillColor: Colors.transparent, + filled: true, + hintText: "请输入联系人", + hintStyle: TextStyle( + color: Colors.white), + border: InputBorder.none, + contentPadding: + EdgeInsets.all(0)), + onChanged: (value) { + controller.model.peopleList[index] + .emergencyContact = value; + controller.updateAll(); + }, + controller: controller.onReDraw( + TextEditingController( + text: controller + .model + .peopleList[index] + .emergencyContact ?? + ""), + (textEditingController) { + textEditingController.text = + controller + .model + .peopleList[index] + .emergencyContact ?? + ""; + }, "people_emergencyContact_$index"), + ), + ), + ], + ), + ), + ], + ), + ) + ], + ); + }), + SizedBox( + height: 100.rpx, + ), + ], + )), + ), + ), + ), + )), + ); + } +} diff --git a/lib/pages/device_control/repair_history_page.dart b/lib/pages/device_control/repair_history_page.dart new file mode 100644 index 0000000..41325b7 --- /dev/null +++ b/lib/pages/device_control/repair_history_page.dart @@ -0,0 +1,797 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:timeline_tile/timeline_tile.dart'; +import 'package:vbvs_app/common/color/appColors.dart'; +import 'package:vbvs_app/common/color/appFontsize.dart'; +import 'package:vbvs_app/common/color/repair_status.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/controller/mh/repair_process.dart'; +import 'package:vbvs_app/pages/device_control/repair_process_widget.dart'; + +import '../../component/img/img_preview_widget.dart'; +import '../../controller/mh/apply_repair_controller.dart'; +import '../../controller/mh/repair_info_controller.dart'; + +class RepairHistoryListPage extends GetView { + final scaffoldKey = GlobalKey(); + BoxConstraints? bodysize; + + @override + Widget build(BuildContext context) { + controller.model.applyRepairModel = ApplyRepairModel() + ..id = 1001 + ..apply_name = '张三' + ..tel = '13812345678' + ..address = '北京市海淀区清华东路66号' + ..desc = '床垫传感器失灵,无法监测心率和呼吸' + ..create_time = DateTime.parse('2025-05-01 10:00:00') + ..device_type = '床垫' + ..device_category = 'BY-H' + ..device_id = 'BD202505011001' + ..device_name = '智能床垫 BY-H 型号' + ..issue_img = [ + 'https://example.com/img1.jpg', + 'https://example.com/img2.jpg' + ] + ..imagesLImit = 3 + ..img_bucket = 'mianhuatang_repair' + ..status = '待处理' + ..select_device = '床垫/BY-H/智能床垫' + ..device_list = ['床垫/BY-H/智能床垫', '床垫/BY-A/智能床垫', '床垫/BY-C/智能床垫'] + ..score = null + ..score_time = null + ..messageType = 1 + ..repairId = 1001; + + controller.model.repairProcessList = [ + RepairProcessModel() + ..status = '申请提交' + ..create_time = DateTime.parse('2025-05-01 10:05:00') + ..desc = '用户提交了维修申请' + ..record_id = 1001 + ..deal_user = null, + RepairProcessModel() + ..status = '客服受理' + ..create_time = DateTime.parse('2025-05-01 10:20:00') + ..desc = '客服已联系用户确认问题' + ..record_id = 1001 + ..deal_user = 2001, + RepairProcessModel() + ..status = '维修完成' + ..create_time = DateTime.parse('2025-05-02 15:30:00') + ..desc = '维修人员完成修复,等待用户确认' + ..record_id = 1001 + ..deal_user = 3001, + ]; + + final List events = controller.model.repairProcessList; + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return WillPopScope( + child: GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + // key: scaffoldKey, + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '详情', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + + body: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 30.rpx, 30.rpx, 30.rpx, 0), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 0, 0, 0, 10), + child: Container( + width: MediaQuery.sizeOf(context).width, + decoration: BoxDecoration( + color: Color(0xFF003058), //true + borderRadius: BorderRadius.circular(8), + ), + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB(17, 10, 0, 0), + child: Container( + decoration: const BoxDecoration(), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + // 'SWES01号智能一键入眠床', + controller + .model + .applyRepairModel! + .device_name ?? + '未命名', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: 30.rpx, + letterSpacing: 0, + color: Colors.white, + ), + ), + ), + Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '系列:' + + (controller + .model + .applyRepairModel! + .device_category ?? + '未命名'), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: const Color( + 0xFF929699), + fontSize: 26.rpx, + letterSpacing: 0, + ), + ), + ), + Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '类型:' + + (controller + .model + .applyRepairModel! + .device_type ?? + '未命名'), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: const Color( + 0xFF929699), + fontSize: 26.rpx, + letterSpacing: 0, + ), + ), + ), + Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '序列号:' + + (controller + .model + .applyRepairModel! + .device_id ?? + '未命名'), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: const Color( + 0xFF929699), + fontSize: 26.rpx, + letterSpacing: 0, + ), + ), + ), + Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '报修单号:' + + (controller + .model + .applyRepairModel! + .id + .toString() ?? + '未命名'), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: const Color( + 0xFF929699), + fontSize: 26.rpx, + letterSpacing: 0, + ), + ), + ), + Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '提交时间:' + + (MyUtils.formatDateTime( + controller + .model + .applyRepairModel! + .create_time!)), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: const Color( + 0xFF929699), + fontSize: 26.rpx, + letterSpacing: 0, + ), + ), + ), + Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '问题描述:' + + (controller + .model + .applyRepairModel! + .desc ?? + '未命名'), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: const Color( + 0xFF929699), + fontSize: 26.rpx, + letterSpacing: 0, + ), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0, 10, 0, 24), + child: Container( + width: MediaQuery.sizeOf( + context) + .width, + height: MediaQuery.sizeOf( + context) + .height * + 0.15, + constraints: + const BoxConstraints( + + // minHeight: 140, + ), + child: Container( + width: 100, + height: 100, + child: Obx(() => + ListView( + shrinkWrap: + true, + scrollDirection: + Axis + .horizontal, + children: getImage(controller + .model + .applyRepairModel!) + .divide( + const SizedBox( + width: + 12, + )) + .addToStart( + const SizedBox( + width: + 0, + ))))), + )), + ] + .divide( + const SizedBox(height: 5)) + .addToStart(const SizedBox( + height: 5, + )), + ), + )), + ), + ), + Padding( + padding: + const EdgeInsetsDirectional.fromSTEB( + 0, 25, 0, 25), // 设置上下间距为 34 + child: Align( + alignment: AlignmentDirectional + .centerStart, // 文字左对齐 + child: Text( + '报修状态', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: 30.rpx, + letterSpacing: 0.0, + ), + ), + ), + ), + Container( + width: bodysize!.maxWidth, // 设置宽度自适应 + child: ListView.builder( + shrinkWrap: true, // 让ListView根据内容自适应高度 + physics: + const NeverScrollableScrollPhysics(), // 禁用内部滚动,交由外部滚动视图处理 + itemCount: events.length, + itemBuilder: (context, index) { + bool isLast = + index == events.length - 1; + return TimelineTile( + isFirst: index == 0, + isLast: isLast, + axis: + TimelineAxis.vertical, // 垂直方向时间轴 + alignment: + TimelineAlign.start, // 线条左对齐 + lineXY: 0.5, // 线条和圆圈相对位置 + indicatorStyle: IndicatorStyle( + width: 15, // 圆圈的宽度 + padding: const EdgeInsets.all( + 1), // 避免线条进入圆圈内部 + indicatorXY: 0.2, // 圆圈居中 + indicator: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: const Color( + 0xFFC8CBD2), // 最后一个元素为蓝色 + width: 1, + ), + color: stringToColor("#C8CBD2"), + ), + ), + ), + beforeLineStyle: LineStyle( + color: stringToColor( + "#C8CBD2"), // 上方线条颜色 + thickness: 1, // 线条厚度 + ), + afterLineStyle: LineStyle( + color: stringToColor( + "#C8CBD2"), // 最后一个节点的线条颜色 + thickness: 1, // 线条厚度 + ), + endChild: Padding( + padding: const EdgeInsets.all(8.0), + child: RepairStatusWidget( + index: index, + repairInfoController: controller, + ), + ), + ); + }, + ), + ), + Obx(() { + if (RepairStatus.completed == + controller.model.applyRepairModel! + .status && + controller.model.applyRepairModel! + .score == + null) + return Align( + alignment: + const AlignmentDirectional(1, 0), + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB(17, 33, 0, 24), + child: Container( + width: 61, + height: MediaQuery.sizeOf(context) + .height * + 0.03, + constraints: const BoxConstraints( + minHeight: 24, + ), + decoration: const BoxDecoration(), + child: FFButtonWidget( + onPressed: () { + Get.toNamed("/scorePage"); + }, + text: '待评价', + options: FFButtonOptions( + height: 40, + padding: + const EdgeInsetsDirectional + .fromSTEB(0, 0, 0, 0), + iconPadding: + const EdgeInsetsDirectional + .fromSTEB(0, 0, 0, 0), + // color: FlutterFlowTheme.of(context) + // .secondaryBackground, + color: Colors.white, + textStyle: + FlutterFlowTheme.of(context) + .titleSmall + .override( + fontFamily: + 'Readex Pro', + // color: Color(0xFF333333), + // color: stringToColor("#D3B684"), + color: stringToColor( + "#117EFD"), + fontSize: 11, + letterSpacing: 0, + ), + elevation: 0, + borderSide: BorderSide( + // color: Color(0xFFC8CBD2), + // color: stringToColor("#D3B684"), + color: + stringToColor("#117EFD"), + width: 1, + ), + borderRadius: + BorderRadius.circular(50), + ), + ), + ), + ), + ); + return Container(); + }), + Obx(() { + if (RepairStatus.completed == + controller.model.applyRepairModel! + .status && + controller.model.applyRepairModel! + .score != + null) + return Padding( + padding: const EdgeInsetsDirectional + .fromSTEB(0, 0, 0, 5), + child: Container( + width: + MediaQuery.sizeOf(context).width, + decoration: BoxDecoration( + color: Colors.white, //true + borderRadius: + BorderRadius.circular(8), + ), + child: Padding( + padding: const EdgeInsetsDirectional + .fromSTEB(0, 0, 0, 0), + child: Container( + decoration: const BoxDecoration(), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 17, 0, 30, 10), + child: Container( + width: MediaQuery.sizeOf( + context) + .width, + height: 30, + decoration: + const BoxDecoration(), + child: Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Text( + '评价状态', + style: FlutterFlowTheme + .of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + color: const Color( + 0xFF333333), + fontSize: 15, + letterSpacing: + 0.0, + ), + ), + ), + ), + ), + Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 17, 0, 0, 0), + child: Container( + width: + MediaQuery.sizeOf( + context) + .width, + constraints: + const BoxConstraints( + minHeight: 24, + ), + decoration: + const BoxDecoration(), + child: // Generated code for this Column Widget... + Column( + mainAxisSize: + MainAxisSize.max, + children: [ + Align( + alignment: + const AlignmentDirectional( + -1, 0), + child: Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0, + 0, + 0, + 10), + child: Text( + // '2023-08-22 12:12:44', + MyUtils.formatDateTime( + controller + .model + .applyRepairModel! + .score_time!), + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize.normal_text_size, + letterSpacing: + 0.0, + ), + ), + ), + ), + Row( + mainAxisSize: + MainAxisSize + .max, + children: [ + Align( + alignment: + const AlignmentDirectional( + -1, + 0), + child: + Padding( + padding: + const EdgeInsetsDirectional + .fromSTEB( + 0, + 0, + 5, + 0), + child: Text( + '已评价', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: + AppFontsize.normal_text_size, + letterSpacing: + 0.0, + ), + ), + ), + ), + Icon( + Icons.star, + color: controller + .model + .applyRepairModel! + .score! >= + 1 + ? stringToColor( + "#F8AE00") + : stringToColor( + "#D0D0D0"), + size: 14, + ), + Icon( + Icons.star, + color: controller + .model + .applyRepairModel! + .score! >= + 2 + ? stringToColor( + "#F8AE00") + : stringToColor( + "#D0D0D0"), + size: 14, + ), + Icon( + Icons.star, + color: controller + .model + .applyRepairModel! + .score! >= + 3 + ? stringToColor( + "#F8AE00") + : stringToColor( + "#D0D0D0"), + size: 14, + ), + Icon( + Icons.star, + color: controller + .model + .applyRepairModel! + .score! >= + 4 + ? stringToColor( + "#F8AE00") + : stringToColor( + "#D0D0D0"), + size: 14, + ), + Icon( + Icons.star, + color: controller + .model + .applyRepairModel! + .score! >= + 5 + ? stringToColor( + "#F8AE00") + : stringToColor( + "#D0D0D0"), + size: 14, + ), + ], + ), + ], + ), + ), + ), + ), + ] + .divide(const SizedBox( + height: 0)) + .addToStart(const SizedBox( + height: 5, + )) + .addToEnd(const SizedBox( + height: 15, + )), + ), + ), + ), + ), + ); + return Container(); + }), + ], + ), + ), + ), + ), + ), + ], + ), + ), + ), + )), + onWillPop: () async { + // 处理返回事件,比如弹出提示框等 + print("页面返回事件"); + return true; // 返回 true 允许页面返回,返回 false 阻止页面返回 + }, + ); + }); + } + + List getImage(ApplyRepairModel applyRepairModel) { + List images = []; + ApplyRepairController controller = Get.find(); + applyRepairModel.issue_img!.forEach((element) async { + images.add( + Container( + // height: 10, + // width: 10, + + child: ImgPreviewWidget( + imgUrl: element, + index: applyRepairModel.issue_img!.indexOf(element), + applyRepairController: controller, + isDel: false, + ), + ), + ); + }); + + return images; + } +} diff --git a/lib/pages/device_control/repair_history_widget.dart b/lib/pages/device_control/repair_history_widget.dart new file mode 100644 index 0000000..da96ecc --- /dev/null +++ b/lib/pages/device_control/repair_history_widget.dart @@ -0,0 +1,144 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/appColors.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/controller/mh/repair_info_controller.dart'; +import 'package:vbvs_app/controller/mh/repair_list_controller.dart'; +import 'package:vbvs_app/pages/device_control/ColorChangeOnTap.dart'; + +import '../../common/color/appFontsize.dart'; + +class RepairHistoryWidget extends GetView { + int index; + RepairListController repairListController; + + RepairHistoryWidget( + {required this.index, required this.repairListController}) {} + + @override + Widget build(BuildContext context) { + int tmp = index; + index = tmp; + return ColorChangeOnPress( + pressColor: AppColors().press_color, // 按下时的颜色 + shouldNavigate: true, // 是否需要跳转 + routeName: "/repairHistoryListPage", // 路由名称 + topLeft: 16, + topRight: 16, + bottomLeft: 16, + bottomRight: 16, + onTap: () async { + // print("object"); + // final RepairInfoController repairInfoController = + // Get.find(); + // await repairInfoController + // .initData(repairListController.model.repairList[index]) + // .then((_) { + // repairInfoController.updateAll(); + // // Get.toNamed("/repairHistoryListPage"); // 这个在 ColorChangeOnPress 中已经处理 + // }); + }, + child: Container( + width: MediaQuery.sizeOf(context).width, + constraints: BoxConstraints( + minHeight: 70, + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(15, 14, 15, 13), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: MediaQuery.sizeOf(context).width * 0.5, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: AlignmentDirectional(-1, 0), + child: Text( + repairListController + .model.repairList[index].device_category ?? + '', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: Color(0xFF333333), + fontSize: AppFontsize.title_size, + letterSpacing: 0, + ), + ), + ), + Align( + alignment: AlignmentDirectional(-1, 0), + child: Text( + "报修单号:${repairListController.model.repairList[index].id}", + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: Color(0xFFC8CBD2), + fontSize: AppFontsize.small_text_size, + letterSpacing: 0, + ), + ), + ), + Align( + alignment: AlignmentDirectional(-1, 0), + child: Text( + "提交时间:" + + (MyUtils.formatDateTime(repairListController + .model.repairList[index].create_time!) ?? + ''), + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: Color(0xFFC8CBD2), + fontSize: AppFontsize.small_text_size, + letterSpacing: 0, + ), + ), + ), + ], + ), + ), + Container( + width: MediaQuery.sizeOf(context).width * 0.2, + height: MediaQuery.sizeOf(context).height * 0.075, + constraints: BoxConstraints( + maxWidth: 130, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Align( + alignment: AlignmentDirectional(0, 0), + child: Text( + repairListController.model.repairList[index].status ?? + '', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: Color(0xFF333333), + fontSize: AppFontsize.normal_text_size, + letterSpacing: 0, + ), + ), + ), + Flexible( + child: Align( + alignment: AlignmentDirectional(0, 0.05), + child: Icon( + Icons.arrow_forward_ios, + color: FlutterFlowTheme.of(context).secondaryText, + size: 10, + ), + ), + ), + ].divide(SizedBox(width: 27)), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/device_control/repair_list.dart b/lib/pages/device_control/repair_list.dart new file mode 100644 index 0000000..4f89197 --- /dev/null +++ b/lib/pages/device_control/repair_list.dart @@ -0,0 +1,575 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; + +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; +import 'package:vbvs_app/controller/mh/apply_repair_controller.dart'; +import 'package:vbvs_app/controller/mh/repair_list_controller.dart'; + + +class DeviceRepairPage extends GetView { + final scaffoldKey = GlobalKey(); + BoxConstraints? bodysize; + + // final ScrollController scrollController = ScrollController(); + // final RepairListController controller = Get.find(); + + // DeviceRepairPage() { + // controller.model.limit = AppConstants.limit; + // controller.model.offset = 0; + // controller.model.isLoading = false; + // controller.model.hasMore = true; + // controller.model.repairList.clear(); + // controller.initData(); + // Get.put(RepairListController()); + + // scrollController.addListener(() { + // if (scrollController.position.pixels == + // scrollController.position.maxScrollExtent && + // controller.model.hasMore) { + // controller.initData(); + // controller.updateAll(); + // } + // }); + // } + final List mockData = List.generate(4, (index) { + return ApplyRepairModel() + ..device_name = "SWESO1号智能一键入眠床" + ..status = index == 0 ? "已提交" : "已完成" + ..create_time = DateTime(2024, 5, 12, 12, 5, 12); + }); + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + // key: scaffoldKey, + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '设备报修', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Padding( + padding: EdgeInsets.fromLTRB(30.rpx, 6.rpx, 30.rpx, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 报修须知 + Container( + height: 412.rpx, + decoration: BoxDecoration( + border: Border.all( + color: Color(0XFFC8CBD2), width: 0.rpx), + borderRadius: BorderRadius.circular(10), + ), + child: Padding( + padding: EdgeInsets.fromLTRB( + 27.rpx, 49.rpx, 43.rpx, 39.rpx), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + // 固定的标题部分 + Text( + "报修须知", + style: TextStyle( + fontSize: 30.rpx, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + SizedBox(height: 33.rpx), + // 可滚动的正文部分,限定高度 + Expanded( + child: SingleChildScrollView( + child: RichText( + text: TextSpan( + style: TextStyle( + color: Color(0XFF929699), + fontSize: 26.rpx, + ), + children: [ + TextSpan( + text: + "尊敬的用户,感谢您选择我司产品。在使用过程中,如果设备出现故障需要维修,请首先确认设备是否正确连接控制器或网络,检查设置是否正常,排除误操作问题。若问题依然存在,请记录下设备名称、设备编号、和具体故障内容,方便我们快速地为您提供帮助。您可以通过智慧棉花糖APP保修页面直接报修或拨打 ", + style: TextStyle( + color: + Color(0XFF929699), + fontSize: 26.rpx, + height: 1.3)), + TextSpan( + text: "400-8756-966", + style: TextStyle( + color: Colors.white, + // height: 1.3, + decoration: TextDecoration + .underline, // 添加下划线 + decorationColor: + Colors.white, + decorationThickness: 4.rpx, + ), + ), + TextSpan( + text: " 反馈。", + style: TextStyle( + color: + Color(0XFF929699), + fontSize: 26.rpx, + height: 1.3)), + ], + ), + ), + ), + ), + ], + ))), + + SizedBox(height: 24.rpx), + + InkWell( + onTap: () { + // bool isOk = true; + // for (var i = 0; i < 2; i++) { + // var d = controller.model.peopleList[i]; + // print("${d.toJson()}"); + // String before = "人员信息${i == 0 ? "A" : "B"}:"; + // if (isOk && + // d.height != null && + // d.height != "" && + // int.tryParse("${d.height}") == null) { + // showToast("$before身高请输入数字"); + // isOk = false; + // } + // if (isOk && + // d.weight != null && + // d.weight != "" && + // int.tryParse("${d.weight}") == null) { + // showToast("$before体重请输入数字"); + // isOk = false; + // } + // if (isOk && + // d.tel != null && + // d.tel != "" && + // MyUtils.isValidPhoneNumber("${d.tel}") == + // false) { + // showToast("$before请输入正确的电话"); + // isOk = false; + // } + // if (isOk && + // d.emergencyContact != null && + // d.emergencyContact != "" && + // MyUtils.isValidPhoneNumber( + // "${d.emergencyContact}") == + // false) { + // showToast("$before请输入正确的紧急联系人电话"); + // isOk = false; + // } + // if (isOk) { + // controller.savePeoples().then((d) { + // showToast("保存成功", color: color_success); + // }).catchError((d) { + // print("$d"); + // showToast("保存失败"); + // }); + // } + // } + // controller.model.peopleList.forEach((d) {}); + }, + child: CustomCard( + borderRadius: 10, + gradientDirection: GradientDirection.vertical, + onTap: () { + Get.toNamed("/applyRepairPage"); + }, + colors: const [ + Color(0xFFFCFCFC), + Color(0xFFF8FAF9), + Color(0XFFECF6F3), + Color(0XFFD9F0E9), + Color(0xFFCEECE3) + ], + child: Container( + width: double.infinity, + height: 90.rpx, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + ), + child: Text( + "我要报修", + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: stringToColor("#011D33"), + letterSpacing: 0, + fontSize: 30.rpx, + ), + ), + ), + )), + + SizedBox(height: 235.rpx), + + // 报修历史标题 + Container( + width: double.infinity, + child: Text("报修历史", + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + height: 1)), + ), + + SizedBox(height: 32.rpx), + + // 报修历史列表 + Expanded( + child: ListView.builder( + itemCount: mockData.length, + itemBuilder: (context, index) { + final item = mockData[index]; + return ClickableContainer( + backgroundColor: Colors.transparent, + highlightColor: Color(0XFF055466), + padding: EdgeInsets.only(top: 0), + onTap: () { + Get.toNamed("/repairHistoryListPage"); + }, + child: Container( + height: 119.rpx, + // margin: const EdgeInsets.only(bottom: 10), + // padding: const EdgeInsets.symmetric( + // vertical: 12, horizontal: 16), + decoration: BoxDecoration( + // color: const Color(0xFF06486F), + border: Border( + top: index == 0 + ? BorderSide( + color: + const Color(0xFF929699), + width: 1.rpx) + : BorderSide.none, + bottom: BorderSide( + color: const Color(0xFF929699), + width: 1.rpx), + ), + ), + child: Padding( + padding: EdgeInsets.fromLTRB( + 17.rpx, 0, 30.rpx, 0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + // 左侧设备信息 + Column( + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + item.device_name ?? '', + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx), + ), + const SizedBox(height: 4), + Text( + "提交时间:${item.create_time?.toString().substring(0, 19) ?? ''}", + style: TextStyle( + color: Colors.white60, + fontSize: 20.rpx), + ), + ], + ), + // 右侧状态 + Row( + children: [ + Text( + item.status ?? '', + style: TextStyle( + color: Colors.white, + fontSize: 26.rpx), + ), + Icon(Icons.arrow_forward_ios, + color: Colors.white, + size: 30.rpx), + ], + ) + ], + ), + ))); + }, + ), + ), + ], + ), + )) + // Container( + // width: bodysize!.maxWidth, + // height: bodysize!.maxHeight * 1, + // decoration: BoxDecoration( + // color: Color(0xFFF6F6F6), + // ), + // child: Column( + // mainAxisSize: MainAxisSize.max, + // children: [ + // // TitleComponentWidget( + // // titleName: '设备报修', + // // ), + // Expanded( + // child: Padding( + // padding: EdgeInsetsDirectional.fromSTEB(15, 0, 15, 0), + // child: Container( + // width: bodysize!.maxWidth, + // height: bodysize!.maxHeight * 0.9, + // decoration: BoxDecoration( + // color: Color(0xFFF6F6F6), + // ), + // child: Column( + // mainAxisSize: MainAxisSize.max, + // children: [ + // Padding( + // padding: + // EdgeInsetsDirectional.fromSTEB(0, 14, 0, 13), + // child: Container( + // width: bodysize!.maxWidth, + // height: bodysize!.maxHeight * 0.186, + // constraints: BoxConstraints( + // minHeight: 170, + // ), + // decoration: BoxDecoration( + // color: FlutterFlowTheme.of(context) + // .secondaryBackground, + // borderRadius: BorderRadius.circular(16), + // border: Border.all( + // color: Colors.white, + // ), + // ), + // child: Column( + // mainAxisSize: MainAxisSize.max, + // children: [ + // Padding( + // padding: EdgeInsetsDirectional.fromSTEB( + // 0, 14, 0, 18), + // child: Text( + // '报修须知', + // style: FlutterFlowTheme.of(context) + // .bodyMedium + // .override( + // fontFamily: 'Readex Pro', + // fontSize: AppFontsize.title_size, + // letterSpacing: 0, + // fontWeight: FontWeight.w600, + // ), + // ), + // ), + // Flexible( + // child: Padding( + // padding: EdgeInsetsDirectional.fromSTEB( + // 14, 0, 14, 14), // 应用 padding + // child: SingleChildScrollView( + // child: Column( + // mainAxisSize: MainAxisSize.max, + // children: [ + // Text( + // '尊敬的用户,感谢您选择我司产品。在使用过程中,如果设备出现故障或需要维修,请首先确认设备是否正确连接电源和网络,检查设置是否正常,排除基本操作问题。若问题依然存在,请记录下设备名称、设备型号、和具体故障情况等,方便我们更快速地为您提供帮助。您可以通过智慧眠花糖APP保修或者直接拨打400-8756-966反馈。', + // style: FlutterFlowTheme.of( + // context) + // .bodyMedium + // .override( + // fontFamily: 'Readex Pro', + // color: Color(0xFF333333), + // fontSize: AppFontsize + // .small_text_size, + // letterSpacing: 0, + // lineHeight: 1.5, + // ), + // ), + // // 如果需要,可以在 Text 下面添加其他小部件 + // ], + // ), + // ), + // ), + // ) + // ], + // ), + // ), + // ), + // Padding( + // padding: + // EdgeInsetsDirectional.fromSTEB(0, 0, 0, 42), + // child: Container( + // width: bodysize!.maxWidth, + // height: 46, + // decoration: BoxDecoration( + // color: FlutterFlowTheme.of(context) + // .secondaryBackground, + // borderRadius: BorderRadius.circular(16), + // ), + // child: Container( + // width: bodysize!.maxWidth, + // height: bodysize!.maxHeight * 0.056, + // decoration: BoxDecoration( + // color: FlutterFlowTheme.of(context) + // .secondaryBackground, + // borderRadius: BorderRadius.circular(16), + // ), + // child: FFButtonWidget( + // onPressed: () { + // Get.toNamed("/applyRepairPage"); + // }, + // text: '我要报修', + // options: FFButtonOptions( + // height: 46, + // padding: EdgeInsetsDirectional.fromSTEB( + // 24, 0, 24, 0), + // iconPadding: EdgeInsetsDirectional.fromSTEB( + // 0, 0, 0, 0), + // color: Color(0xFFE55E92), + // textStyle: FlutterFlowTheme.of(context) + // .titleSmall + // .override( + // fontFamily: 'Readex Pro', + // color: Colors.white, + // fontSize: AppFontsize.title_size, + // letterSpacing: 0, + // ), + // elevation: 0, + // borderSide: BorderSide( + // color: Colors.transparent, + // width: 1, + // ), + // borderRadius: BorderRadius.circular(8), + // ), + // ), + // ), + // ), + // ), + // Expanded( + // child: Container( + // width: bodysize!.maxWidth, + // height: bodysize!.maxHeight * 1, + // decoration: BoxDecoration( + // color: Color(0xFFF6F6F6), + // ), + // child: Column( + // mainAxisSize: MainAxisSize.max, + // children: [ + // Align( + // alignment: AlignmentDirectional(-1, 0), + // child: Padding( + // padding: EdgeInsetsDirectional.fromSTEB( + // 14, 0, 0, 17), + // child: Text( + // '报修历史', + // style: FlutterFlowTheme.of(context) + // .bodyMedium + // .override( + // fontFamily: 'Readex Pro', + // color: Color(0xFF333333), + // fontSize: AppFontsize.title_size, + // letterSpacing: 0, + // fontWeight: FontWeight.w600, + // ), + // ), + // ), + // ), + // Obx(() { + // return Visibility( + // visible: + // controller.model.repairList != null && + // controller + // .model.repairList!.isNotEmpty, + // replacement: + // EmptyMessageWidget(), + // child: Expanded( + // // child: Obx(() => + // child: ListView( + // controller: + // scrollController, // 绑定 ScrollController + // shrinkWrap: true, + // scrollDirection: Axis.vertical, + // children: (controller + // .model.repairList + // .asMap() + // .entries + // .map((e) => + // RepairHistoryWidget( + // index: e.key, + // repairListController: + // controller)) + // .toList() as List) + // .divide(const SizedBox( + // height: 13, + // )) + // .addToEnd(SizedBox( + // height: AppConstants + // .list_end_height, + // ))) + // // ), + // ), + // ); + // }), + // ], + // ), + // ), + // ), + // ], + // ), + // ), + // ), + // ), + // ], + // ), + // ), + ), + )); + }); + } +} diff --git a/lib/pages/device_control/repair_process_widget.dart b/lib/pages/device_control/repair_process_widget.dart new file mode 100644 index 0000000..1c9391f --- /dev/null +++ b/lib/pages/device_control/repair_process_widget.dart @@ -0,0 +1,121 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/color/appColors.dart'; +import 'package:vbvs_app/common/color/repair_status.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/controller/mh/repair_info_controller.dart'; + +import '../../common/color/appFontsize.dart'; + +class RepairStatusWidget extends GetView { + int index; + RepairInfoController repairInfoController; + + RepairStatusWidget( + {required this.index, required this.repairInfoController}) {} + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0), + child: Container( + width: MediaQuery.sizeOf(context).width, + decoration: BoxDecoration( + // color: Colors.white, + ), + child: Container( + width: MediaQuery.sizeOf(context).width, + decoration: BoxDecoration( + // color: Colors.white, + borderRadius: BorderRadius.circular(8), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: AlignmentDirectional(-1, 0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 10), + child: Text( + // '2023-08-22 12:12:44', + MyUtils.formatDateTime(repairInfoController + .model.repairProcessList[index].create_time!) ?? + '未知时间', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + fontSize: AppFontsize.normal_text_size, + letterSpacing: 0, + color: index == + repairInfoController + .model.repairProcessList.length - + 1 + ? Colors.white + : Colors.white, + ), + ), + ), + ), + Align( + alignment: AlignmentDirectional(-1, 0), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 10), + child: Text( + // '审核中', + repairInfoController + .model.repairProcessList[index].status ?? + '未知状态', + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + fontSize: AppFontsize.normal_text_size, + letterSpacing: 0, + color: repairInfoController + .model.repairProcessList[index].status == + RepairStatus.pending + ? AppColors().check_Color + : repairInfoController + .model + .repairProcessList[index] + .status == + RepairStatus.approved || + repairInfoController + .model + .repairProcessList[index] + .status == + '维修中' + ? AppColors().repair_Color + : repairInfoController + .model + .repairProcessList[index] + .status == + RepairStatus.completed + ? AppColors().finish_Color + : AppColors().unOp_Color, // 根据状态设置文字颜色 + ), + ), + ), + ), + Align( + alignment: AlignmentDirectional(-1, 0), + child: Text( + // repairProcessModel.content ?? '未备注', + (repairInfoController + .model.repairProcessList[index].desc?.isEmpty ?? + true) + ? '未备注' + : repairInfoController + .model.repairProcessList[index].desc!, + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: AppFontsize.small_text_size, + letterSpacing: 0, + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/device_control/room_picker.dart b/lib/pages/device_control/room_picker.dart new file mode 100644 index 0000000..afe3fe2 --- /dev/null +++ b/lib/pages/device_control/room_picker.dart @@ -0,0 +1,185 @@ +import 'package:ef/base/widget/flutterflow/FlutterFlowTheme.dart'; +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; + +class RoomPickerPage extends StatefulWidget { + @override + _RoomPickerPageState createState() => _RoomPickerPageState(); +} + +class _RoomPickerPageState extends State { + final List rooms = ['主卧', '次卧', '儿童房', '客厅', '厨房', '书房', '阳台', '洗手间']; + + int selectedIndex = 1; + BoxConstraints? bodysize; + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, // 深蓝背景 + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '房间选择', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + body: SafeArea( + child: Column( + children: [ + // 顶部标题栏 + // const Padding( + // padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 12), + // child: Row( + // children: [ + // Icon(Icons.arrow_back_ios, color: Colors.white), + // Spacer(), + // Text( + // '房间选择', + // style: TextStyle(color: Colors.white, fontSize: 18), + // ), + // Spacer(flex: 2), + // ], + // ), + // ), + const Spacer(), + // 滚轮选择器 + SizedBox( + height: 360.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 滚轮列表 + ListWheelScrollView.useDelegate( + itemExtent: 120.rpx, + perspective: 0.003, + physics: const FixedExtentScrollPhysics(), + onSelectedItemChanged: (index) { + setState(() => selectedIndex = index); + }, + childDelegate: ListWheelChildBuilderDelegate( + builder: (context, index) { + if (index >= rooms.length) return null; + final isSelected = index == selectedIndex; + return Center( + child: Text( + rooms[index], + style: TextStyle( + fontSize: isSelected ? 36.rpx : 30.rpx, + color: isSelected + ? Colors.white + : const Color(0xFF929699), + ), + ), + ); + }, + childCount: rooms.length, + ), + ), + + // 上边线 + Positioned( + top: 120.rpx, + left: 60.rpx, + right: 60.rpx, + child: Container( + height: 1, + color: const Color(0xFF929699), + ), + ), + + // 下边线 + Positioned( + top: 240.rpx, + left: 60.rpx, + right: 60.rpx, + child: Container( + height: 1, + color: const Color(0xFF929699), + ), + ), + ], + ), + ), + const Spacer(), + // 完成按钮 + Padding( + padding: EdgeInsets.only( + left: 30.rpx, + right: 30.rpx, + bottom: 83.rpx, + ), + child: SizedBox( + width: double.infinity, + height: 50, + child: CustomCard( + borderRadius: 10, + gradientDirection: GradientDirection.vertical, + onTap: () { + // Get.toNamed("/applyRepairPage"); + }, + colors: const [ + Color(0xFFFCFCFC), + Color(0xFFF8FAF9), + Color(0XFFECF6F3), + Color(0XFFD9F0E9), + Color(0xFFCEECE3) + ], + child: Container( + width: double.infinity, + height: 90.rpx, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(6), + ), + child: Text("完成", + style: TextStyle( + color: const Color(0xFF003058), + fontSize: 30.rpx, + )), + ), + )), + ), + ], + ), + ), + ))); + }); + } +} diff --git a/lib/pages/device_control/score_page.dart b/lib/pages/device_control/score_page.dart new file mode 100644 index 0000000..2d1d249 --- /dev/null +++ b/lib/pages/device_control/score_page.dart @@ -0,0 +1,468 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/color/appConstants.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/CustomCard.dart'; +import 'package:vbvs_app/controller/mh/score_controller.dart' as mh; + +import '../../common/color/appFontsize.dart'; + +class ScorePage extends GetView { + BoxConstraints? bodysize; + final scaffoldKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + // UserInfoController userInfoController = Get.find(); + // userInfoController.model.user; + controller.model.score = 5; + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + // key: scaffoldKey, + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '评价', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + + body: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 1, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + // TitleComponentWidget( + // titleName: '评价', + // ), + Expanded( + child: Container( + width: bodysize!.maxWidth, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 30.rpx, 26.rpx, 30.rpx, 0), + child: Container( + width: bodysize!.maxWidth, + constraints: BoxConstraints( + minWidth: 346, + minHeight: 115, + ), + decoration: BoxDecoration( + color: Color(0xFF003058), + borderRadius: BorderRadius.circular(16), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 22, 27, 17, 22), + child: Container( + width: bodysize!.maxWidth, + decoration: BoxDecoration( + color: Color(0xFF003058), + borderRadius: BorderRadius.circular(16), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Align( + alignment: + AlignmentDirectional(0, 0), + child: Text( + '我要评价', + style: + FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: 30.rpx, + letterSpacing: 0, + color: Colors.white), + ), + ), + Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + InkWell( + onTap: () { + controller.model.score = 1; + controller.updateAll(); + }, + child: Obx(() { + return Icon( + Icons.star, + color: controller + .model.score! >= + 1 + ? stringToColor( + "#F8AE00") + : stringToColor( + "#D0D0D0"), + size: 40, + ); + }), + ), + InkWell( + onTap: () { + controller.model.score = 2; + controller.updateAll(); + }, + child: Obx(() { + return Icon( + Icons.star, + color: controller + .model.score! >= + 2 + ? stringToColor( + "#F8AE00") + : stringToColor( + "#D0D0D0"), + size: 40, + ); + }), + ), + InkWell( + onTap: () { + controller.model.score = 3; + controller.updateAll(); + }, + child: Obx(() { + return Icon( + Icons.star, + color: controller + .model.score! >= + 3 + ? stringToColor( + "#F8AE00") + : stringToColor( + "#D0D0D0"), + size: 40, + ); + }), + ), + InkWell( + onTap: () { + controller.model.score = 4; + controller.updateAll(); + }, + child: Obx(() { + return Icon( + Icons.star, + color: controller + .model.score! >= + 4 + ? stringToColor( + "#F8AE00") + : stringToColor( + "#D0D0D0"), + size: 40, + ); + }), + ), + InkWell( + onTap: () { + controller.model.score = 5; + controller.updateAll(); + }, + child: Obx(() { + return Icon( + Icons.star, + color: controller + .model.score! >= + 5 + ? stringToColor( + "#F8AE00") + : stringToColor( + "#D0D0D0"), + size: 40, + ); + }), + ), + ].divide(SizedBox(width: 10)), + ), + ].divide(SizedBox(height: 26)), + ), + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 30.rpx, 30.rpx, 30.rpx, 0), + child: Container( + width: bodysize!.maxWidth, + constraints: BoxConstraints( + minWidth: 346, + minHeight: 152, + ), + decoration: BoxDecoration( + color: Color(0xFF003058), + borderRadius: BorderRadius.circular(16.rpx), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 14, 14, 14, 21), + child: Container( + width: bodysize!.maxWidth, + decoration: BoxDecoration( + color: Color(0xFF003058), + borderRadius: + BorderRadius.circular(16.rpx), + ), + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Align( + alignment: + AlignmentDirectional(0, 0), + child: Obx(() { + String scoreText; + Color scoreColor; + if (controller.model.score == 1) { + scoreText = '差'; + scoreColor = + stringToColor("#E55E92"); + } else if (controller + .model.score == + 2) { + scoreText = '较差'; + scoreColor = + stringToColor("#E55E92"); + } else if (controller + .model.score == + 3) { + scoreText = '一般'; + scoreColor = + stringToColor("#07C160"); + } else if (controller + .model.score == + 4) { + scoreText = '优秀'; + scoreColor = + stringToColor("#F8AE00"); + } else if (controller + .model.score == + 5) { + scoreText = '完美'; + scoreColor = + stringToColor("#F8AE00"); + } else { + scoreText = + '未评分'; // 如果没有评分显示默认文字 + scoreColor = + Colors.grey; // 默认颜色 + } + return Text( + scoreText, + style: + FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: 30.rpx, + letterSpacing: 0, + color: scoreColor, + fontWeight: + FontWeight + .bold), + ); + }), + ), + Align( + alignment: + AlignmentDirectional(-1, 0), + child: Padding( + padding: EdgeInsetsDirectional + .fromSTEB(0, 17, 0, 0), + child: Text( + '再多的溢美之词,都比不上您真心的评价。我们愿付出200%的努力,只为您100%的满意~感谢您的支持与厚爱!', + style: FlutterFlowTheme.of( + context) + .bodyMedium + .override( + fontFamily: + 'Readex Pro', + fontSize: 26.rpx, + letterSpacing: 0, + color: + Color(0xFF9AA0B3)), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB( + 15, 0, 15, AppConstants.page_button_bottom_padding), + child: Container( + width: bodysize!.maxWidth, + height: bodysize!.maxHeight * 0.056, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.rpx), + ), + // child: Container( + // width: bodysize!.maxWidth, + // height: bodysize!.maxHeight * 0.056, + // decoration: BoxDecoration( + // color: FlutterFlowTheme.of(context) + // .secondaryBackground, + // borderRadius: BorderRadius.circular(12), + // ), + // child: FFButtonWidget( + // onPressed: () { + // // RepairListController repairListController = + // // Get.find(); + // // RepairInfoController repairInfoController = + // // Get.find(); + // // repairListController + // // .addScore( + // // repairInfoController + // // .model.applyRepairModel!.id!, + // // controller.model.score!) + // // .then((String msg) { + // // if (msg != null && msg.isNotEmpty) { + // // MyDialogController myDialogController = + // // Get.find(); + // // showToast("评价失败,请稍后再试"); + // // } else { + // // MyDialogController myDialogController = + // // Get.find(); + // // myDialogController + // // .showCustomDialog(context, "评价成功", + // // textColor: stringToColor("#71E2A3")) + // // .then((_) { + // // // 弹窗关闭后执行的代码 + // // // Get.toNamed("/userInfoPage"); + // // repairInfoController.model.applyRepairModel! + // // .score = controller.model.score!; + // // repairInfoController.updateAll(); + // // Get.back(); + // // }).catchError((error) { + // // // 处理弹窗显示错误的逻辑 + // // print("弹窗显示失败: $error"); + // // }); + // // } + // // }); + // }, + // text: '确定', + // options: FFButtonOptions( + // height: 40, + // padding: + // EdgeInsetsDirectional.fromSTEB(24, 0, 24, 0), + // iconPadding: + // EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0), + // color: Color(0xFFD3B684), + // textStyle: FlutterFlowTheme.of(context) + // .titleSmall + // .override( + // fontFamily: 'Readex Pro', + // color: Colors.white, + // fontSize: 13, + // letterSpacing: 0, + // ), + // elevation: 0, + // borderSide: BorderSide( + // color: Colors.transparent, + // width: 1, + // ), + // borderRadius: BorderRadius.circular(8), + // ), + // ), + // ), + + child: CustomCard( + borderRadius: 10, + gradientDirection: GradientDirection.vertical, + onTap: () { + Get.toNamed("/applyRepairPage"); + }, + colors: const [ + Color(0xFFFCFCFC), + Color(0xFFF8FAF9), + Color(0XFFECF6F3), + Color(0XFFD9F0E9), + Color(0xFFCEECE3) + ], + child: Container( + width: double.infinity, + height: 90.rpx, + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.rpx), + ), + child: Text( + "提交", + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: stringToColor("#011D33"), + letterSpacing: 0, + fontSize: 30.rpx, + ), + ), + ), + )), + ), + ], + ), + ), + ), + )); + }); + } +} diff --git a/lib/pages/device_control/searchWidget.dart b/lib/pages/device_control/searchWidget.dart new file mode 100644 index 0000000..1235648 --- /dev/null +++ b/lib/pages/device_control/searchWidget.dart @@ -0,0 +1,268 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutterflow_ui/flutterflow_ui.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; + +import '../../common/color/appFontsize.dart'; +import '../../common/util/MyUtils.dart'; + +class SearchWidget extends GetView { + final String? keyword; + final Color? color; + String? hint; + Function? onChange; + Function? findCallback; + + SearchWidget( + {required this.keyword, + required this.color, + this.hint = "请输入关键字", + this.findCallback, + this.onChange}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsetsDirectional.fromSTEB(25, 0, 25, 0), + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: themeController.currentColor.sc3, + borderRadius: BorderRadius.circular(20.rpx), + ), + child: Padding( + padding: EdgeInsetsDirectional.fromSTEB(35.rpx, 0, 35.rpx, 0), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), + child: Container( + width: 25.rpx, + height: 25.rpx, + // width: double.infinity, + decoration: BoxDecoration(), + child: SvgPicture.asset( + 'assets/img/icon/query.svg', + fit: BoxFit.cover, + color: stringToColor("#333333"), //固定 + ), + ), + ), + Expanded( + child: Container( + width: 100.rpx, + height: 80.rpx, + decoration: BoxDecoration( + color: + FlutterFlowTheme.of(context).secondaryBackground, + ), + child: Align( + alignment: AlignmentDirectional(-1, 0), + child: TextFormField( + autofocus: false, + obscureText: false, + decoration: InputDecoration( + isDense: true, + labelStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Inter', + fontSize: 26.rpx, + letterSpacing: 0.0, + ), + hintText: hint, + hintStyle: FlutterFlowTheme.of(context) + .labelMedium + .override( + fontFamily: 'Inter', + fontSize: 26.rpx, + letterSpacing: 0.0, + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Color(0x00000000), + width: 1.rpx, + ), + borderRadius: BorderRadius.circular(8.rpx), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Color(0x00000000), + width: 1.rpx, + ), + borderRadius: BorderRadius.circular(8.rpx), + ), + errorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 1.rpx, + ), + borderRadius: BorderRadius.circular(8.rpx), + ), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide( + color: FlutterFlowTheme.of(context).error, + width: 1.rpx, + ), + borderRadius: BorderRadius.circular(8.rpx), + ), + filled: false, + fillColor: themeController.currentColor.sc22, + ), + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Inter', + fontSize: 26.rpx, + letterSpacing: 0.0, + ), + cursorColor: + FlutterFlowTheme.of(context).primaryText, + // validator: _model + // .textControllerValidator + // .asValidator(context), + ), + ), + ), + ), + ].divide(SizedBox(width: 6.rpx)), + ), + ), + Padding( + padding: EdgeInsetsDirectional.fromSTEB(26.rpx, 0, 0, 0), + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + SizedBox( + height: 50.rpx, + child: VerticalDivider( + thickness: 2.rpx, + color: stringToColor("#333333"), //固定 + ), + ), + Text( + '搜索'.tr, + style: FlutterFlowTheme.of(context).bodyMedium.override( + fontFamily: 'Inter', + fontSize: 30.rpx, + letterSpacing: 0.0, + color: stringToColor("#333333"), //固定 + ), + ), + ].divide(SizedBox(width: 26.rpx)), + ), + ), + ], + ), + ), + ), + // Container( + // width: MediaQuery.sizeOf(context).width, + // height: 44, + // decoration: BoxDecoration( + // // color: Colors.red, + // borderRadius: BorderRadius.circular(50.rpx), + // ), + // child: Container( + // width: MediaQuery.sizeOf(context).width, + // height: 44, + // decoration: BoxDecoration( + // color: valueOrDefault( + // color, + // Color(0xFF821111), + // ), + // borderRadius: BorderRadius.circular(50), + // ), + // child: Stack( + // children: [ + // Align( + // alignment: AlignmentDirectional(0, 0), + // child: Padding( + // padding: EdgeInsetsDirectional.fromSTEB(0, 6, 0, 6), + // child: Container( + // padding: EdgeInsets.only(right: 30.rpx), + // width: double.infinity, + // height: 70.rpx, + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(10.rpx)), + // child: TextField( + // controller: TextEditingController(text: keyword), + // onChanged: (d) { + // onChange?.call(d); + // }, + // style: TextStyle( + // fontSize: 28.rpx, color: stringToColor("#C8CBD2")), + // decoration: InputDecoration( + // contentPadding: + // EdgeInsets.only(top: 0, bottom: 0, right: 20.rpx), + // border: OutlineInputBorder( + // borderSide: BorderSide.none, + // borderRadius: BorderRadius.circular(50.rpx)), + // filled: true, + // hintText: "$hint", + // hintStyle: TextStyle(color: stringToColor("#c8cbd2")), + // fillColor: stringToColor("#FFFFFF"), + // // prefixIcon: Icon( + // // Icons.search, + // // size: 42.rpx, + // // color: stringToColor("#D3B684"), + // // ), + // prefixIcon: Container( + // padding: EdgeInsets.all(15.rpx), // 可根据需求调整内边距 + // child: SvgPicture.asset( + // 'assets/images/search.svg', + // fit: BoxFit.contain, // 确保 SVG 图像不会超出边界 + // color: stringToColor("#D3B684"), + // ), + // ), + // ), + // ), + // ), + // )), + // Align( + // alignment: AlignmentDirectional(0.95, 0), + // child: Padding( + // padding: EdgeInsetsDirectional.fromSTEB(0, 5, 0, 5), + // child: InkWell( + // onTap: () { + // findCallback?.call(); + // }, + // child: Container( + // width: 50, + // // height: 50, + // height: MediaQuery.sizeOf(context).height * 1, + // decoration: BoxDecoration( + // color: Color(0xFFD3B684), + // borderRadius: BorderRadius.circular(50), + // ), + // child: Align( + // alignment: AlignmentDirectional(0, 0), + // child: Text( + // '搜索', + // style: + // FlutterFlowTheme.of(context).bodyMedium.override( + // fontFamily: 'Readex Pro', + // color: Colors.white, + // fontSize: AppFontsize.normal_text_size, + // letterSpacing: 0, + // ), + // ), + // ), + // ), + // ), + // ), + // ), + // ], + // ), + // ), + // ), + ); + } +} diff --git a/lib/pages/device_control/sleep_habit.dart b/lib/pages/device_control/sleep_habit.dart new file mode 100644 index 0000000..87e548a --- /dev/null +++ b/lib/pages/device_control/sleep_habit.dart @@ -0,0 +1,106 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/component/tool/ClickableContainer.dart'; + +class SleepHabitPage extends StatefulWidget { + @override + _SleepHabitPageState createState() => _SleepHabitPageState(); +} + +BoxConstraints? bodysize; + +class _SleepHabitPageState extends State { + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, cc) { + bodysize = cc; + return GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + iconTheme: const IconThemeData(color: Colors.white), + automaticallyImplyLeading: false, + titleSpacing: 0, + title: SizedBox( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '设备报修', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Padding( + padding: EdgeInsets.only( + left: 30.rpx, right: 30.rpx, top: 30.rpx), + child: Column( + children: [ + ClickableContainer( + backgroundColor: Color(0XFF003058), + highlightColor: Color(0XFF055466), + borderRadius: 16.rpx, + padding: EdgeInsets.only(top: 0), + onTap: () {}, + child: Container( + alignment: Alignment.center, + width: bodysize!.maxWidth * 1, + height: bodysize!.maxHeight * 0.056, + child: Text( + '柔性唤醒', + style: TextStyle( + fontSize: 26.rpx, color: Colors.white), + ))), + SizedBox(height: 20.rpx), + ClickableContainer( + backgroundColor: Color(0XFF003058), + highlightColor: Color(0XFF055466), + borderRadius: 16.rpx, + padding: EdgeInsets.only(top: 0), + onTap: () { + Get.toNamed('/syms'); + }, + child: Container( + alignment: Alignment.center, + width: bodysize!.maxWidth * 1, + height: bodysize!.maxHeight * 0.056, + child: Text( + '睡眠隐私', + style: TextStyle( + fontSize: 26.rpx, color: Colors.white), + ))) + ], + ))), + )), + ); + }); + } +} diff --git a/lib/pages/device_control/smys.dart b/lib/pages/device_control/smys.dart new file mode 100644 index 0000000..2d0cc83 --- /dev/null +++ b/lib/pages/device_control/smys.dart @@ -0,0 +1,380 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_switch/flutter_switch.dart'; +import 'package:vbvs_app/common/color/appColors.dart'; +import 'package:vbvs_app/common/util/FitTool.dart'; +import 'package:vbvs_app/common/util/MyUtils.dart'; +import 'package:vbvs_app/pages/common/selectDialog.dart'; + +import '../../controller/mh/sleeping_habit_controller.dart'; + +//睡眠隐私 +class Smys extends GetView { + Smys({super.key}); + + // get glController => Get.find(); + + getLine() { + return Container( + height: 1, + color: stringToColor("#152676"), + ); + } + + // updateParm( + // {int time = 2, bool isShowToast = true, Function? errorccCallback = null}) { + // ApiService.request + // .post( + // "/api/device/info/time/privacy/info?mac=${glController.model.deviceMain["mac"]}&time=${controller.model.smysStartTimeToString}-${controller.model.smysEndTimeToString}&type=${controller.model.smysIsStart ? '1' : '0'}") + // .then((d) { + // if (isShowToast) { + // showToast("操作成功", color: color_success); + // } + // }).catchError((d) { + // if (time > 0) { + // updateParm(time: time - 1, isShowToast: isShowToast, errorccCallback: errorccCallback); + // } else { + // errorccCallback?.call(); + // } + // }); + // } + + @override + Widget build(BuildContext context) { + SleepingHabitController controller = Get.find(); + + return LayoutBuilder( + builder: (context, boxConstraints) => GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/new_background.png'), // 本地图片 + fit: BoxFit.fill, // 填满整个 Container + ), + ), + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + iconTheme: IconThemeData(color: Colors.white), + titleSpacing: 0, + // leading: returnIconButtomAddCallback(() { + // controller.saveDataApi(); + // updateParm(isShowToast: false); + // }), + // leading: returnIconButtomNew, + title: Container( + width: double.infinity, + height: 180.rpx, + child: Stack( + alignment: Alignment.center, + children: [ + // 中间居中的标题 + Text( + '睡眠隐私', + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white, + fontSize: 30.rpx, + ), + ), + // 左侧图标 + Positioned( + left: 20.rpx, + child: returnIconButtomNew, + ), + ], + ), + ), + + actions: [], + centerTitle: false, + ), + body: SafeArea( + top: true, + child: Obx( + () => Container( + padding: EdgeInsets.only(left: 30.rpx, right: 30.rpx), + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * 1.123, + // decoration: BoxDecoration( + // color: Colors.transparent, + // image: DecorationImage( + // image: AssetImage("assets/images/background.png"), + // fit: BoxFit.cover, + // ), + // ), + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + width: double.infinity, + height: MediaQuery.sizeOf(context).height * 0.055, + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: const Color(0xFF929699), + width: 0.rpx), + ), + ), + constraints: BoxConstraints( + minHeight: 90.rpx, // 设置最小高度 + ), + child: Padding( + padding: EdgeInsets.fromLTRB( + 39.rpx, 0.rpx, 15.rpx, 0.rpx), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '睡眠隐私功能', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + Container( + + // height: + // MediaQuery.sizeOf(context).height * + // 0.04, + child: FlutterSwitch( + width: 70.rpx, + height: 36.rpx, + toggleSize: 30.rpx, + activeColor: Color(0XFF6BFDAC), + inactiveColor: Color(0XFF003058), + toggleColor: Color(0xFF011D33), + value: controller.model.smysIsStart, + onToggle: (val) { + controller.attr.update((getmodel) { + getmodel.model.smysIsStart = val; + }); + }, + ) + // Switch.adaptive( + // value: controller.model.smysIsStart, + // onChanged: (newValue) async { + // controller.attr.update((getmodel) { + // getmodel.model.smysIsStart = + // newValue; + // }); + // // updateParm(errorccCallback: () { + // // controller.attr.update((getmodel) { + // // getmodel.model.smysIsStart = !newValue; + // // }); + // // }); + // }, + // activeTrackColor: Color(0xFF6BFDAC), + // inactiveTrackColor: Color(0xFF003058), + // inactiveThumbColor: Color(0xFF011D33), + // trackOutlineWidth: MaterialStateProperty + // .resolveWith( + // (Set states) { + // if (states.contains( + // MaterialState.disabled)) { + // return null; + // } + // return null; // Use the default width. + // }), + // ), + + ), + ], + ), + )), + // getLine(), + Container( + width: double.infinity, + height: MediaQuery.sizeOf(context).height * 0.055, + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: const Color(0xFF929699), + width: 0.rpx), + ), + ), + constraints: BoxConstraints( + minHeight: 90.rpx, // 设置最小高度 + ), + child: Padding( + padding: EdgeInsets.fromLTRB( + 39.rpx, 0.rpx, 30.rpx, 0.rpx), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '开始时间', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + InkWell( + onTap: () async { + showDayTimeSelectionDialog(context, + dayTimeArr: + controller.model.smysStartTime, + title: "开始时间", checkChange: (d) { + controller.attr.update((getmodel) { + getmodel.model.smysStartTime = [ + int.parse("${d[0]}"), + int.parse("${d[1]}") + ]; + }); + // updateParm(); + }); + }, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Text( + "${controller.model.smysStartTimeToString}", + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: 36.rpx, + letterSpacing: 0, + ), + ), + SizedBox( + width: 16.rpx, + ), + Icon( + Icons.expand_more, + color: Colors.white, + size: 40.rpx, + ), + ], + ), + ), + ], + ), + )), + // getLine(), + Container( + width: double.infinity, + height: MediaQuery.sizeOf(context).height * 0.055, + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: const Color(0xFF929699), + width: 0.rpx), + ), + ), + constraints: BoxConstraints( + minHeight: 90.rpx, // 设置最小高度 + ), + child: Padding( + padding: EdgeInsets.fromLTRB( + 39.rpx, 0.rpx, 30.rpx, 0.rpx), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + '结束时间', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 30.rpx, + letterSpacing: 0, + ), + ), + InkWell( + onTap: () async { + showDayTimeSelectionDialog(context, + dayTimeArr: + controller.model.smysEndTime, + title: "结束时间", checkChange: (d) { + controller.attr.update((getmodel) { + getmodel.model.smysEndTime = [ + int.parse("${d[0]}"), + int.parse("${d[1]}") + ]; + }); + // updateParm(); + }); + }, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Text( + "${controller.model.smysEndTimeToString}", + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Colors.white, + fontSize: 36.rpx, + letterSpacing: 0, + ), + ), + SizedBox( + width: 16.rpx, + ), + Icon( + Icons.expand_more, + color: Colors.white, + size: 40.rpx, + ), + ], + ), + ), + ], + ), + ), + ), + // getLine(), + SizedBox( + height: 30.rpx, + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 25.rpx), + child: Container( + width: double.infinity, + decoration: BoxDecoration(), + child: Text( + '*注:开启睡眠隐私功能后,在设置的时间段内,将不会采集您的睡眠数据。', + style: FlutterFlowTheme.of(context) + .bodyMedium + .override( + fontFamily: 'Readex Pro', + color: Color(0xFF9EA4B7), + fontSize: 20.rpx, + letterSpacing: 0, + ), + ), + ), + ) + ], + ), + ), + ), + ), + ), + ), + )), + ); + } +} diff --git a/lib/pages/main_bottom/component/MessageWidgetWidget.dart b/lib/pages/main_bottom/component/MessageWidgetWidget.dart index 8725ff0..c54d559 100644 --- a/lib/pages/main_bottom/component/MessageWidgetWidget.dart +++ b/lib/pages/main_bottom/component/MessageWidgetWidget.dart @@ -35,7 +35,7 @@ class _MessageWidgetWidgetState extends State { return Stack( children: [ ClickableContainer( - backgroundColor: themeController.currentColor.sc5, + backgroundColor: Color(0xFF003058), highlightColor: themeController.currentColor.sc3, borderRadius: 20.rpx, padding: @@ -93,7 +93,7 @@ class _MessageWidgetWidgetState extends State { .toList(), ), ), - ].divide(SizedBox(width: 35.rpx)), + ].divide(SizedBox(width: 30.rpx)), ), ], ), diff --git a/lib/pages/main_bottom/component/main_page_b_bottom_change.dart b/lib/pages/main_bottom/component/main_page_b_bottom_change.dart new file mode 100644 index 0000000..9249970 --- /dev/null +++ b/lib/pages/main_bottom/component/main_page_b_bottom_change.dart @@ -0,0 +1,246 @@ +// import 'dart:io'; +// import 'package:flutter/material.dart'; +// import 'package:flutter/services.dart'; +// import 'package:get/get.dart'; +// import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; +// import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; +// import 'package:vbvs_app/controller/main_bottom/main_page_controller.dart'; +// import 'package:vbvs_app/controller/message/message_controller.dart'; +// import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; +// import 'package:vbvs_app/controller/user_info_controller.dart'; +// import 'package:vbvs_app/enum/LoginStatus.dart'; +// import 'package:vbvs_app/pages/common/bezier_bottom_navigation_bar.dart'; +// import 'package:vbvs_app/pages/main_bottom/e_page.dart'; +// import 'package:vbvs_app/pages/main_bottom/home_page.dart'; +// import 'package:vbvs_app/pages/main_bottom/message_page.dart'; +// import 'package:vbvs_app/pages/main_bottom/mine_page.dart'; + +// class MainPageBBottomChange extends StatefulWidget { +// const MainPageBBottomChange({super.key}); + +// @override +// State createState() => _MainPageBottomChangeState(); +// } + +// class _MainPageBottomChangeState extends State +// with SingleTickerProviderStateMixin { +// final GlobalController globalController = Get.find(); +// final ThemeController themeController = Get.find(); +// final MessageController messageController = Get.find(); +// final MainPageController controller = Get.find(); +// final UserInfoController userInfoController = Get.find(); + +// late AnimationController _animationController; +// late Animation _positionAnimation; + +// final List pages = [ +// const HomePage(), +// const EPage(), +// const MessagePage(), +// const MinePage(), +// ]; + +// final List titles = ['首页', '报告', '控制', '我的']; +// final List icons = [ +// Icons.home, +// Icons.android, +// Icons.message, +// Icons.person, +// ]; + +// int selectedIndex = 0; +// double currentPosition = 0.0; + +// DateTime? _lastBackPressedTime; + +// @override +// void initState() { +// super.initState(); +// selectedIndex = controller.model.currentIndex; +// currentPosition = selectedIndex.toDouble(); + +// _animationController = AnimationController( +// vsync: this, +// duration: const Duration(milliseconds: 300), +// ); + +// _positionAnimation = Tween( +// begin: currentPosition, +// end: currentPosition, +// ).animate(CurvedAnimation( +// parent: _animationController, +// curve: Curves.easeOut, +// )) +// ..addListener(() { +// setState(() {}); +// }); +// } + +// void _onTabTapped(int index) { +// bool isLoggedIn = userInfoController.model.login == LoginStatus.LOGIN.code; + +// if ((index == 1 || index == 2) && !isLoggedIn) { +// TopSlideNotification.show(context, text: "必须登录提示".tr); +// Future.delayed(const Duration(milliseconds: 100), () { +// Get.toNamed("/loginPage"); +// }); +// return; +// } + +// if (selectedIndex != index) { +// final begin = currentPosition; +// final end = index.toDouble(); +// _positionAnimation = Tween(begin: begin, end: end).animate( +// CurvedAnimation(parent: _animationController, curve: Curves.easeOut), +// )..addListener(() { +// setState(() {}); +// }); + +// _animationController.forward(from: 0.0); +// currentPosition = end; +// selectedIndex = index; + +// controller.model.currentIndex = index; +// controller.updateAll(); +// } +// } + +// @override +// void dispose() { +// _animationController.dispose(); +// super.dispose(); +// } + +// Future _handleBackPressed() async { +// final now = DateTime.now(); +// if (_lastBackPressedTime == null || +// now.difference(_lastBackPressedTime!) > const Duration(seconds: 2)) { +// _lastBackPressedTime = now; +// TopSlideNotification.show(context, text: "滑动退出提醒".tr); +// return false; +// } +// return true; +// } + +// @override +// Widget build(BuildContext context) { +// return PopScope( +// canPop: false, +// onPopInvokedWithResult: (disposition, result) async { +// if (Platform.isAndroid) { +// final exit = await _handleBackPressed(); +// if (exit) SystemNavigator.pop(); +// } +// }, +// child: Obx(() { +// final hideBar = globalController.model.hideBottomNavigationBar; +// return Scaffold( +// backgroundColor: Colors.transparent, +// body: pages[controller.model.currentIndex], +// bottomNavigationBar: hideBar +// ? null +// : BezierBottomNavigationBar( +// selectedIndex: selectedIndex, +// animatedPosition: _positionAnimation.value, +// icons: icons, +// titles: titles, +// onTap: _onTabTapped, +// ), +// ); +// }), +// ); +// } +// } +import 'package:flutter/material.dart'; +import 'package:vbvs_app/pages/common/bezier_bottom_navigation_bar.dart'; +import 'package:vbvs_app/pages/device_control/MattressControl.dart'; +import 'package:vbvs_app/pages/device_control/new_Home_page.dart'; +import 'package:vbvs_app/pages/device_control/new_mine_page.dart'; +import 'package:vbvs_app/pages/device_control/score_page.dart'; + +class MainPageBBottomChange extends StatefulWidget { + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State + with SingleTickerProviderStateMixin { + int selectedIndex = 0; + late AnimationController _controller; + late Animation _positionAnimation; + double currentPosition = 0.0; + + final List titles = ['首页', '报告', '控制', '我的']; + final List path = [ + "assets/images/bar_home.svg", + "assets/images/bar_heart.svg", + "assets/images/bar_control.svg", + "assets/images/bar_mine.svg" + ]; + + final List pages = [ + NewHomePage(), + // PeopleInfoPage(), + // Text('报告'), + ScorePage(), + // Smys(), + MattressControlPage(), + NewMinePage() + ]; + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, duration: const Duration(milliseconds: 300)); + currentPosition = selectedIndex.toDouble(); + _positionAnimation = Tween( + begin: currentPosition, end: currentPosition) + .animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut)) + ..addListener(() { + setState(() {}); // trigger rebuild for CustomPainter + }); + } + + void _onTabTapped(int index) { + setState(() { + final begin = currentPosition; + final end = index.toDouble(); + _positionAnimation = Tween(begin: begin, end: end).animate( + CurvedAnimation(parent: _controller, curve: Curves.easeOut), + )..addListener(() { + setState(() {}); + }); + _controller.forward(from: 0.0); + currentPosition = end; + selectedIndex = index; + }); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + Widget _buildPageContent() { + return Center(child: Text('页面 ${titles[selectedIndex]}')); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: const Color(0xFF011C33), + body: IndexedStack( + index: selectedIndex, + children: pages, + ), + bottomNavigationBar: BezierBottomNavigationBar( + selectedIndex: selectedIndex, + animatedPosition: _positionAnimation.value, + onTap: _onTabTapped, + path: path, + titles: titles, + ), + ); + } +} diff --git a/lib/pages/main_bottom/message_page.dart b/lib/pages/main_bottom/message_page.dart index f894327..160c355 100644 --- a/lib/pages/main_bottom/message_page.dart +++ b/lib/pages/main_bottom/message_page.dart @@ -407,6 +407,7 @@ class _MessagePageState extends State { ], ), ), + SizedBox(height: 17.rpx), ], ), diff --git a/lib/pages/main_bottom/mine_page.dart b/lib/pages/main_bottom/mine_page.dart index 6d6b5f2..90483c7 100644 --- a/lib/pages/main_bottom/mine_page.dart +++ b/lib/pages/main_bottom/mine_page.dart @@ -737,4 +737,5 @@ class _MinePageState extends State { ), ); } + } diff --git a/lib/routers/mh_routers.dart b/lib/routers/mh_routers.dart new file mode 100644 index 0000000..effab34 --- /dev/null +++ b/lib/routers/mh_routers.dart @@ -0,0 +1,110 @@ +import 'package:ef/ef.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:path/path.dart'; +import 'package:vbvs_app/controller/mh/muser_info_controller.dart'; + +import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; + +import 'package:vbvs_app/pages/device_control/HomeDeviceType.dart'; +import 'package:vbvs_app/pages/device_control/LanguagePage.dart'; +import 'package:vbvs_app/pages/device_control/address_list_page.dart'; +import 'package:vbvs_app/pages/device_control/apply_repair_page.dart'; +import 'package:vbvs_app/pages/device_control/book_info_page.dart'; +import 'package:vbvs_app/pages/device_control/book_success_page.dart'; +import 'package:vbvs_app/pages/device_control/device_people_info.dart'; +import 'package:vbvs_app/pages/device_control/edit_bed.dart'; +import 'package:vbvs_app/pages/device_control/edit_userinfo_page.dart'; +import 'package:vbvs_app/pages/device_control/experience_store_page.dart'; +import 'package:vbvs_app/pages/device_control/issue_list_page.dart'; +import 'package:vbvs_app/pages/device_control/my_experience_page.dart'; +import 'package:vbvs_app/pages/device_control/people_info.dart'; +import 'package:vbvs_app/pages/device_control/repair_history_page.dart'; +import 'package:vbvs_app/pages/device_control/repair_list.dart'; +import 'package:vbvs_app/pages/device_control/room_picker.dart'; +import 'package:vbvs_app/pages/device_control/sleep_habit.dart'; +import 'package:vbvs_app/pages/device_control/smys.dart'; + +import '../pages/device_control/bluetooth.dart'; +import '../pages/device_control/edit_address_page.dart'; +import '../pages/device_control/message_page.dart'; +import '../pages/device_control/new_settingPage.dart'; + +ThemeController themeController = Get.find(); + +var mhroutes = { + "/homeDeviceType": (contxt) => HomeDeviceType(), + "/editUserInfoPage": (contxt) => EditUserInfoPage(), + "/peopleInfoPage": (contxt) => PeopleInfoPage(), + "/repairHistoryListPage": (contxt) => RepairHistoryListPage(), + "/deviceRepairPage": (contxt) => DeviceRepairPage(), + "/settingPage": (contxt) => SettingPage(), + "/issueListpage": (contxt) => IssueListPage(), + "/messagePage": (contxt) => MessagePage(), + "/addressListPage": (contxt) => AddressListPage(), + "/editAddressPage": (contxt) => EditAddressPage(), + "/languagePage": (context) => LanguagePage(), + '/bluetoothPage': (context) => BluetoothPage(), + "/devicePeopleInfo": (context) => DevicePeopleInfo(), + "/sleepHabitPage": (context) => SleepHabitPage(), + '/syms': (context) => Smys(), + "/applyRepairPage": (context) => ApplyRepairPage(), + "/roomPickerPage": (context) => RoomPickerPage(), + "/editBedPage": (context) => EditBedPage(), + "/experienceStorePage": (context) => ExperienceStorePage(), + "/bookInfoPage": (context, {arguments}) => BookInfoPage(data: arguments), + "/bookSuccessPage": (contxt, {arguments}) => + BookSuccessPage(data: arguments["data"]), + "/myExperiencePage": (context) => MyExperiencePage(), +}; +var mhonGenerateRoute = (RouteSettings settings) { + final String? name = settings.name; // 获取路由名称,如 /news 或 /search + final Function? pageContentBuilder = mhroutes[name]; // 根据路由名称获取对应的页面构建器 + + if (pageContentBuilder != null) { + MUserInfoController userInfoController = Get.find(); + int loginStatus = userInfoController.model.login!; + + // 检查用户是否已登录,如果未登录且路由不是登录相关页面,跳转到登录页面 + // if (loginStatus != 1) { + // // 如果用户未登录且访问的不是登录页面等,展示提示并重定向 + // if (settings.name != "/loginPage" && + // settings.name != "/otherLoginPage" && + // settings.name != "/mianPageBottomChange") { + // TopSlideNotification.show( + // Get.context!, + // text: "必须登录提示".tr, + // textColor: themeController.currentColor.sc9, + // ); + + // // 创建新的 RouteSettings,并修改 name 为 /loginPage + // final updatedSettings = RouteSettings( + // name: "/loginPage", + // arguments: settings.arguments, + // ); + + // // 创建一个新的路由,跳转到登录页面 + // return CupertinoPageRoute( + // settings: updatedSettings, + // builder: (context) => pageContentBuilder!(context), + // ); + // } + // } + + // 如果有路由参数,传递参数 + if (settings.arguments != null) { + return CupertinoPageRoute( + settings: settings, + builder: (context) => + pageContentBuilder!(context, arguments: settings.arguments), + ); + } else { + // 没有路由参数时,直接构建页面 + return CupertinoPageRoute( + settings: settings, + builder: (context) => pageContentBuilder!(context), + ); + } + } + + return null; // 如果路由名称没有匹配的页面,返回 null +}; diff --git a/lib/routers/routers.dart b/lib/routers/routers.dart index 86a613a..3be65ba 100644 --- a/lib/routers/routers.dart +++ b/lib/routers/routers.dart @@ -21,6 +21,7 @@ import 'package:vbvs_app/pages/device_bind/wifi_page.dart'; import 'package:vbvs_app/pages/device_bind/wifi_page_person.dart'; import 'package:vbvs_app/pages/login/login.dart'; import 'package:vbvs_app/pages/login/other_login.dart'; +import 'package:vbvs_app/pages/main_bottom/component/main_page_b_bottom_change.dart'; import 'package:vbvs_app/pages/main_bottom/e_page.dart'; import 'package:vbvs_app/pages/main_bottom/follow_page.dart'; import 'package:vbvs_app/pages/main_bottom/help_page.dart';