This commit is contained in:
wyf
2025-06-17 08:57:06 +08:00
parent 89d0bbcc00
commit d26a4797c3
6 changed files with 714 additions and 37 deletions

View File

@@ -0,0 +1,651 @@
import 'dart:async';
import 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:intl/intl.dart';
import 'package:vbvs_app/common/color/ServiceConstant.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/MyUtils.dart';
import 'package:vbvs_app/common/util/requestWithLog.dart';
import 'package:vbvs_app/component/tool/CustomCard.dart';
import 'package:vbvs_app/component/tool/TopSlideNotification.dart';
import 'package:vbvs_app/pages/common/selectDialog.dart';
import 'package:vbvs_app/pages/mh_page/device/controller/mht_bluetooth_controller.dart';
class MHTPeopleInfoPage extends StatefulWidget {
const MHTPeopleInfoPage({Key? key}) : super(key: key);
@override
State<MHTPeopleInfoPage> createState() => _MHTPeopleInfoPageState();
}
class _MHTPeopleInfoPageState extends State<MHTPeopleInfoPage> {
final MHTBlueToothController bluetoothController = Get.find();
final List<TextEditingController> _nameControllers = [];
final List<TextEditingController> _contactControllers = [];
List<Map<String, dynamic>> peopleList = [];
bool isLoading = true;
@override
void initState() {
super.initState();
_initializeData();
}
void _initializeData() async {
final device = bluetoothController.currentFullDevice;
//todo 初始化传感器id
// Initialize person A
peopleList.add({
'mac': device?.macA,
'gender': "",
'id':device!.macAID,
});
// Initialize person B if exists
if (device?.macB != null && device!.macB!.isNotEmpty) {
peopleList.add({
'mac': device.macB,
'gender': "",
'id':device!.macBID,
});
}
// Initialize controllers after data is loaded
_initializeControllers();
setState(() => isLoading = false);
}
void _initializeControllers() {
for (var person in peopleList) {
_nameControllers.add(TextEditingController(text: person["name"] ?? ""));
_contactControllers
.add(TextEditingController(text: person["contact"] ?? ""));
}
}
@override
void dispose() {
for (var controller in _nameControllers) {
controller.dispose();
}
for (var controller in _contactControllers) {
controller.dispose();
}
super.dispose();
}
Widget getLine() {
return Divider(
color: Color(0XFF929699),
thickness: 0.5.rpx,
height: 0,
);
}
String time_08_Formatter_pattern(dynamic date, String pattern) {
if (date == null || date.toString().isEmpty) return "-";
try {
String normalized = date.toString().replaceAll("/", "-");
DateTime dt = DateTime.parse(normalized);
return DateFormat(pattern).format(dt);
} catch (e) {
return "-";
}
}
Future<void> _savePersonData(
Map<String, dynamic> personData, BuildContext context) async {
String serviceAddress = ServiceConstant.service_address;
String serviceName = ServiceConstant.server_service;
String serviceApi = ServiceConstant.personnel_info;
String type = "user_message_setting";
String queryUrl = "${serviceAddress}${serviceName}${serviceApi}";
try {
var body = {
'mac': personData['mac'],
'name': personData['name'],
'gender': personData['gender'],
'height': personData['height'],
'weight': personData['weight'],
'birthday': personData['birthday'] is DateTime
? DateFormat('yyyy-MM-dd').format(personData['birthday'])
: personData['birthday'],
'contact': personData['contact'],
'id':personData['id'],
};
await requestWithLog(
logTitle: "保存用户信息",
method: MyHttpMethod.put,
queryUrl: queryUrl,
data: body,
onSuccess: (res) {
print(res);
},
onFailure: (res) {
TopSlideNotification.show(context,text: res.msg!,textColor: themeController.currentColor.sc9);
print(res);
},
);
// showToast("保存成功(${personData['mac']}", color: color_success);
} catch (e) {
print("Error saving person data: $e");
showToast("保存失败(${personData['mac']}");
}
}
@override
Widget build(BuildContext context) {
if (isLoading) {
return Center(child: CircularProgressIndicator());
}
return LayoutBuilder(
builder: (context, boxConstraints) => GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/new_background.png'),
fit: BoxFit.fill,
),
),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
elevation: 0,
surfaceTintColor: Colors.transparent,
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: CustomCard(
borderRadius: 16.rpx,
gradientDirection: GradientDirection.vertical,
onTap: () async {
// Save all people data
for (var person in peopleList) {
await _savePersonData(person, context);
}
TopSlideNotification.show(context, text: "保存成功");
Get.offNamed("/bindDeviceSuccess");
},
colors: const [
Color(0xFFFCFCFC),
Color(0xFFF8FAF9),
Color(0XFFECF6F3),
Color(0XFFD9F0E9),
Color(0xFFCEECE3)
],
child: Container(
width: 120.rpx,
height: 60.rpx,
alignment: Alignment.center,
child: Text(
"下一步",
style: TextStyle(
fontFamily: 'Readex Pro',
color: Color(0XFF011D33),
letterSpacing: 0,
fontSize: 30.rpx,
),
),
),
),
)
],
),
),
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,
child: SingleChildScrollView(
child: Column(
children: [
...List.generate(peopleList.length, (index) {
final person = peopleList[index];
return Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(
left: 18.rpx,
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(
child: Column(
children: [
getLine(),
Container(
width: double.infinity,
height: 90.rpx,
margin: EdgeInsets.only(
left: 40.rpx, right: 35.rpx),
decoration: BoxDecoration(),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'姓名',
style: TextStyle(
fontFamily: 'Readex Pro',
color: Color(0xFF9EA4B7),
fontSize: 30.rpx,
letterSpacing: 0,
),
),
Container(
width: 300.rpx,
child: TextField(
controller: _nameControllers[index],
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) {
setState(() {
peopleList[index]["name"] = value;
});
},
),
),
],
),
),
getLine(),
Container(
margin: EdgeInsets.only(
left: 40.rpx, right: 35.rpx),
width: double.infinity,
height: 90.rpx,
decoration: BoxDecoration(),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'性别',
style: TextStyle(
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: peopleList[index]
['gender'] ==
""
? 0
: 1, checkChange: (sindex) {
setState(() {
peopleList[index]['gender'] =
sindex == 0 ? "" : "";
});
}).then((d) {});
});
},
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Container(
width: 200.rpx,
child: Text(
'${peopleList[index]['gender']}',
textAlign: TextAlign.right,
style: TextStyle(
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: 90.rpx,
margin: EdgeInsets.only(
left: 40.rpx, right: 35.rpx),
decoration: BoxDecoration(),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'身高(cm)',
style: TextStyle(
fontFamily: 'Readex Pro',
color: Color(0xFF9EA4B7),
fontSize: 30.rpx,
letterSpacing: 0,
),
),
InkWell(
onTap: () {
FocusScope.of(context).unfocus();
Future.delayed(
const Duration(milliseconds: 250),
() {
showHeightPickerDialog(
context,
initialHeight: int.tryParse(
peopleList[index]
['height'] ??
'170') ??
170,
onConfirm: (int selectedHeight) {
setState(() {
peopleList[index]['height'] =
selectedHeight.toString();
});
},
);
});
},
child: Row(
children: [
Text(
peopleList[index]['height'] !=
null
? "${peopleList[index]['height']} cm"
: '',
style: TextStyle(
fontFamily: 'Readex Pro',
color: Colors.white,
fontSize: 30.rpx,
),
),
SizedBox(width: 16.rpx),
Icon(Icons.expand_more,
color: Colors.white,
size: 48.rpx),
],
),
),
],
),
),
getLine(),
Container(
width: double.infinity,
height: 90.rpx,
margin: EdgeInsets.only(
left: 40.rpx, right: 35.rpx),
decoration: BoxDecoration(),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'体重(kg)',
style: TextStyle(
fontFamily: 'Readex Pro',
color: Color(0xFF9EA4B7),
fontSize: 30.rpx,
letterSpacing: 0,
),
),
InkWell(
onTap: () {
FocusScope.of(context).unfocus();
Future.delayed(
const Duration(milliseconds: 250),
() {
showWeightPickerDialog(
context,
initialWeight: "0",
onConfirm: (int selectedWeight) {
setState(() {
peopleList[index]['weight'] =
selectedWeight.toString();
});
},
);
});
},
child: Row(
children: [
Text(
peopleList[index]['weight'] !=
null
? "${peopleList[index]['weight']} kg"
: '',
style: TextStyle(
fontFamily: 'Readex Pro',
color: Colors.white,
fontSize: 30.rpx,
),
),
SizedBox(width: 16.rpx),
Icon(Icons.expand_more,
color: Colors.white,
size: 48.rpx),
],
),
),
],
),
),
getLine(),
Container(
width: double.infinity,
height: 90.rpx,
margin: EdgeInsets.only(
left: 40.rpx, right: 35.rpx),
decoration: BoxDecoration(),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'生日',
style: TextStyle(
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: peopleList[index]
['birthday'] is DateTime
? peopleList[index]
['birthday']
: DateTime.tryParse(
peopleList[index][
'birthday'] ??
'') ??
DateTime.now(),
checkChange: (DateTime d) {
setState(() {
peopleList[index]['birthday'] =
d;
});
}).then((d) {});
});
},
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Container(
constraints: BoxConstraints(
minWidth: 200.rpx),
child: Text(
peopleList[index]['birthday'] !=
null
? time_08_Formatter_pattern(
peopleList[index]
['birthday'],
"yyyy年MM月dd日")
: '',
textAlign: TextAlign.right,
style: TextStyle(
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: 90.rpx,
margin: EdgeInsets.only(
left: 40.rpx, right: 35.rpx),
decoration: BoxDecoration(),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'联系人',
style: TextStyle(
fontFamily: 'Readex Pro',
color: Color(0xFF9EA4B7),
fontSize: 30.rpx,
letterSpacing: 0,
),
),
Container(
width: 300.rpx,
child: TextField(
controller:
_contactControllers[index],
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) {
setState(() {
peopleList[index]['contact'] =
value;
});
},
),
),
],
),
),
getLine(),
],
))
],
);
}),
SizedBox(height: 100.rpx),
],
),
),
),
),
),
),
),
);
}
}