541 lines
17 KiB
Dart
541 lines
17 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:environmental_protection/common/user_information.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:http/http.dart';
|
|
|
|
import 'common/full_page_struct.dart';
|
|
|
|
Future<Response> removePerson(int id) {
|
|
return GlobalInformation.getInstance().requester.delete(resolve("/api/family/member/$id"));
|
|
}
|
|
|
|
class PersonCard extends StatelessWidget {
|
|
final String name;
|
|
final String phone;
|
|
final DateTime? endDate;
|
|
final int id;
|
|
final String type;
|
|
final Function fetchFunction;
|
|
const PersonCard({super.key, required this.name, required this.phone, required this.endDate, required this.id, required this.fetchFunction, required this.type});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Card(
|
|
child: Padding(
|
|
padding: const EdgeInsetsDirectional.all(10),
|
|
child: ListTile(
|
|
title: Row(
|
|
children: [
|
|
Text(name),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: const Color.fromRGBO(210, 246, 231, 1),
|
|
borderRadius: BorderRadiusDirectional.circular(10)
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsetsDirectional.only(start: 10, end: 10, top: 2, bottom: 2),
|
|
child: Text(type, style: const TextStyle(color: Color.fromRGBO(31, 204, 143, 1)))
|
|
),
|
|
)
|
|
],
|
|
),
|
|
leading: const SizedBox(
|
|
width: 50,
|
|
height: 100,
|
|
child: Placeholder(),
|
|
),
|
|
subtitle: Flex(
|
|
direction: Axis.vertical,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(phone.replaceRange(3, 7, "****")),
|
|
Text(endDate == null ? "有效期:长期有效": "有效期:${endDate!.year}-${endDate!.month}-${endDate!.day}")
|
|
],
|
|
),
|
|
trailing: OutlinedButton(
|
|
onPressed: () {
|
|
removePerson(id).then((e){fetchFunction();});
|
|
},
|
|
style: const ButtonStyle(
|
|
foregroundColor: WidgetStatePropertyAll(Colors.red),
|
|
side: WidgetStatePropertyAll(BorderSide(color: Colors.red))
|
|
),
|
|
child: const Text(
|
|
"删除",
|
|
),
|
|
),
|
|
onTap: (){
|
|
Navigator.push(context, MaterialPageRoute(builder: (context) {
|
|
return FamilyPersonInformation(id: id, fetchFunction: fetchFunction);
|
|
}));
|
|
},
|
|
),
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
class MePage extends StatefulWidget {
|
|
const MePage({super.key});
|
|
|
|
@override
|
|
State<MePage> createState() => _MePageState();
|
|
}
|
|
|
|
class _MePageState extends State<MePage> {
|
|
List<Map<String, dynamic>> persons = [];
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_fetchFamilyData();
|
|
}
|
|
void _fetchFamilyData() async {
|
|
var data = await GlobalInformation().requester.get(resolve("/api/family/member/list"));
|
|
var jsonData = jsonDecode(data.body);
|
|
if (jsonData['code'] != 200){
|
|
return;
|
|
}
|
|
setState(() {
|
|
persons.clear();
|
|
jsonData['rows'].forEach((e){
|
|
persons.add(e);
|
|
});
|
|
});
|
|
}
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
var personsCard = persons.map((e){return PersonCard(name: e['name'], phone: e['telephone'], endDate: e['endDate'] == null ? null : DateTime.parse(e['endDate']), id: e['id'], fetchFunction: _fetchFamilyData, type: e['memberType'] == "1" ? "家属" : "租户");}).toList();
|
|
List<Widget> items = [];
|
|
items.addAll(personsCard);
|
|
items.add(Center(
|
|
child: ElevatedButton(
|
|
onPressed: (){
|
|
Navigator.push(context, MaterialPageRoute(builder: (context){
|
|
return AddFamilyPerson(fetchFunction: _fetchFamilyData);
|
|
}));
|
|
},
|
|
style: const ButtonStyle(
|
|
backgroundColor: WidgetStatePropertyAll(Colors.blueGrey)
|
|
),
|
|
child: const Padding(
|
|
padding: EdgeInsetsDirectional.only(start: 20, end: 20, top: 10, bottom: 10),
|
|
child: Text(
|
|
"+ 新增家庭成员",
|
|
style: TextStyle(
|
|
color: Colors.white
|
|
),
|
|
)
|
|
)
|
|
),
|
|
));
|
|
return FullPageStruct(
|
|
title: '家庭成员管理',
|
|
color: Colors.lightBlue,
|
|
child: ListView(
|
|
children: items,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class AddFamilyPerson extends StatefulWidget {
|
|
final Function fetchFunction;
|
|
const AddFamilyPerson({super.key, required this.fetchFunction});
|
|
|
|
@override
|
|
State<AddFamilyPerson> createState() => _AddFamilyPersonState();
|
|
}
|
|
|
|
class _AddFamilyPersonState extends State<AddFamilyPerson> {
|
|
final _formKey = GlobalKey<FormState>();
|
|
String? _selectedHouseId;
|
|
String? _name;
|
|
String? _gender;
|
|
String? _phone;
|
|
String? _idCard;
|
|
String? _memberType;
|
|
DateTime? _startDate;
|
|
DateTime? _endDate;
|
|
List<Map<String, dynamic>> _houseList = [];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_fetchHouseList();
|
|
}
|
|
|
|
Future<void> _fetchHouseList() async {
|
|
// 获取房屋列表数据
|
|
final response = await GlobalInformation.getInstance().requester.get(resolve("/api/house/list"));
|
|
if (response.statusCode == 200) {
|
|
final data = jsonDecode(response.body);
|
|
setState(() {
|
|
_houseList = List<Map<String, dynamic>>.from(data['data']);
|
|
});
|
|
} else {
|
|
if (mounted){
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('获取房屋列表失败')),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> _submit() async {
|
|
if (_formKey.currentState?.validate() ?? false) {
|
|
_formKey.currentState?.save();
|
|
|
|
// 发送添加家属请求
|
|
final response = await GlobalInformation.getInstance().requester.post(
|
|
resolve("/api/family/member"),
|
|
body: jsonEncode({
|
|
"houseId": _selectedHouseId,
|
|
"name": _name,
|
|
"sex": _gender,
|
|
"telephone": _phone,
|
|
"idCard": _idCard,
|
|
"memberType": _memberType,
|
|
"startDate": _startDate?.toIso8601String(),
|
|
"endDate": _endDate?.toIso8601String(),
|
|
}),
|
|
headers: {"Content-Type": "application/json"},
|
|
);
|
|
if (mounted){
|
|
if (response.statusCode == 200) {
|
|
// 处理成功逻辑
|
|
Navigator.of(context).pop();
|
|
widget.fetchFunction();
|
|
} else {
|
|
// 处理错误逻辑
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('添加家属失败,请稍后再试')),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FullPageStruct(
|
|
title: "新增家庭成员",
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Form(
|
|
key: _formKey,
|
|
child: ListView(
|
|
children: [
|
|
DropdownButtonFormField<String>(
|
|
decoration: const InputDecoration(labelText: '选择房屋'),
|
|
value: _selectedHouseId,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_selectedHouseId = value;
|
|
});
|
|
},
|
|
items: _houseList.map((house) {
|
|
return DropdownMenuItem(
|
|
value: house['id'].toString(),
|
|
child: Text(house['address'] ?? '未知地址'),
|
|
);
|
|
}).toList(),
|
|
validator: (value) =>
|
|
value == null ? '请选择房屋' : null,
|
|
),
|
|
TextFormField(
|
|
decoration: const InputDecoration(labelText: '姓名'),
|
|
onSaved: (value) => _name = value,
|
|
validator: (value) => value == null || value.isEmpty
|
|
? '请输入姓名'
|
|
: null,
|
|
),
|
|
DropdownButtonFormField<String>(
|
|
decoration: const InputDecoration(labelText: '性别'),
|
|
value: _gender,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_gender = value;
|
|
});
|
|
},
|
|
items: const [
|
|
DropdownMenuItem(value: "0", child: Text('男')),
|
|
DropdownMenuItem(value: "1", child: Text('女')),
|
|
],
|
|
validator: (value) => value == null ? '请选择性别' : null,
|
|
),
|
|
TextFormField(
|
|
decoration: const InputDecoration(labelText: '手机号'),
|
|
keyboardType: TextInputType.phone,
|
|
onSaved: (value) => _phone = value,
|
|
validator: (value) => value == null || value.isEmpty
|
|
? '请输入手机号'
|
|
: null,
|
|
),
|
|
TextFormField(
|
|
decoration: const InputDecoration(labelText: '身份证号'),
|
|
onSaved: (value) => _idCard = value,
|
|
validator: (value) => value == null || value.isEmpty
|
|
? '请输入身份证号'
|
|
: null,
|
|
),
|
|
DropdownButtonFormField<String>(
|
|
decoration: const InputDecoration(labelText: '住户类型'),
|
|
value: _memberType,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_memberType = value;
|
|
});
|
|
},
|
|
items: const [
|
|
DropdownMenuItem(value: "1", child: Text('业主')),
|
|
DropdownMenuItem(value: "2", child: Text('租户')),
|
|
],
|
|
validator: (value) =>
|
|
value == null ? '请选择住户类型' : null,
|
|
),
|
|
ElevatedButton(
|
|
onPressed: _submit,
|
|
child: const Text('保存'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
class FamilyPersonInformation extends StatefulWidget {
|
|
final int id;
|
|
final Function fetchFunction;
|
|
const FamilyPersonInformation({super.key, required this.id, required this.fetchFunction});
|
|
|
|
@override
|
|
State<FamilyPersonInformation> createState() => _FamilyPersonInformationState();
|
|
}
|
|
|
|
class _FamilyPersonInformationState extends State<FamilyPersonInformation> {
|
|
final _formKey = GlobalKey<FormState>();
|
|
String? _selectedHouseId;
|
|
String? _name;
|
|
String? _gender;
|
|
String? _phone;
|
|
String? _idCard;
|
|
String? _memberType;
|
|
List<Map<String, dynamic>> _houseList = [];
|
|
bool _isLoading = true;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_fetchFamilyMemberDetails();
|
|
_fetchHouseList();
|
|
}
|
|
|
|
Future<void> _fetchFamilyMemberDetails() async {
|
|
// 获取家庭成员详情
|
|
final response = await GlobalInformation.getInstance().requester.get(resolve("/api/family/member/${widget.id}"));
|
|
if (response.statusCode == 200) {
|
|
final data = jsonDecode(response.body)['data'];
|
|
setState(() {
|
|
_selectedHouseId = data['houseId'].toString();
|
|
_name = data['name'];
|
|
_gender = data['sex'];
|
|
_phone = data['telephone'];
|
|
_idCard = data['idCard'];
|
|
_memberType = data['memberType'];
|
|
_isLoading = false;
|
|
});
|
|
} else {
|
|
if (mounted){
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('获取家庭成员详情失败')),
|
|
);
|
|
}
|
|
setState(() {
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
Future<void> _fetchHouseList() async {
|
|
// 获取房屋列表
|
|
final response = await GlobalInformation.getInstance().requester.get(resolve("/api/house/list"));
|
|
if (response.statusCode == 200) {
|
|
final data = jsonDecode(response.body);
|
|
setState(() {
|
|
_houseList = List<Map<String, dynamic>>.from(data['data']);
|
|
});
|
|
} else {
|
|
if (mounted){
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('获取房屋列表失败')),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> _submit() async {
|
|
if (_formKey.currentState?.validate() ?? false) {
|
|
_formKey.currentState?.save();
|
|
|
|
// 发送保存家庭成员修改请求
|
|
final response = await GlobalInformation.getInstance().requester.put(
|
|
resolve("/api/family/member"),
|
|
body: jsonEncode({
|
|
"id": widget.id,
|
|
"houseId": _selectedHouseId,
|
|
"name": _name,
|
|
"sex": _gender,
|
|
"telephone": _phone,
|
|
"idCard": _idCard,
|
|
"memberType": _memberType,
|
|
}),
|
|
headers: {"Content-Type": "application/json"},
|
|
);
|
|
if (mounted){
|
|
if (response.statusCode == 200) {
|
|
// 处理成功逻辑
|
|
Navigator.of(context).pop();
|
|
widget.fetchFunction();
|
|
} else {
|
|
// 处理错误逻辑
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('保存失败,请稍后再试')),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> _deleteMember() async {
|
|
final response = await GlobalInformation.getInstance().requester.delete(
|
|
resolve("/api/family/member/${widget.id}"),
|
|
);
|
|
if (mounted){
|
|
if (response.statusCode == 200) {
|
|
Navigator.of(context).pop();
|
|
widget.fetchFunction();
|
|
} else {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('删除失败,请稍后再试')),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (_isLoading) {
|
|
return const FullPageStruct(
|
|
title: "家庭成员详情",
|
|
child: Center(child: CircularProgressIndicator()),
|
|
);
|
|
}
|
|
|
|
return FullPageStruct(
|
|
title: "家庭成员详情",
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Form(
|
|
key: _formKey,
|
|
child: ListView(
|
|
children: [
|
|
DropdownButtonFormField<String>(
|
|
decoration: const InputDecoration(labelText: '选择房屋'),
|
|
value: _selectedHouseId,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_selectedHouseId = value;
|
|
});
|
|
},
|
|
items: _houseList.map((house) {
|
|
return DropdownMenuItem(
|
|
value: house['id'].toString(),
|
|
child: Text(house['address'] ?? '未知地址'),
|
|
);
|
|
}).toList(),
|
|
validator: (value) =>
|
|
value == null ? '请选择房屋' : null,
|
|
),
|
|
TextFormField(
|
|
initialValue: _name,
|
|
decoration: const InputDecoration(labelText: '姓名'),
|
|
onSaved: (value) => _name = value,
|
|
validator: (value) => value == null || value.isEmpty
|
|
? '请输入姓名'
|
|
: null,
|
|
),
|
|
DropdownButtonFormField<String>(
|
|
decoration: const InputDecoration(labelText: '性别'),
|
|
value: _gender,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_gender = value;
|
|
});
|
|
},
|
|
items: const [
|
|
DropdownMenuItem(value: "0", child: Text('男')),
|
|
DropdownMenuItem(value: "1", child: Text('女')),
|
|
],
|
|
validator: (value) => value == null ? '请选择性别' : null,
|
|
),
|
|
TextFormField(
|
|
initialValue: _phone,
|
|
decoration: const InputDecoration(labelText: '手机号'),
|
|
keyboardType: TextInputType.phone,
|
|
onSaved: (value) => _phone = value,
|
|
validator: (value) => value == null || value.isEmpty
|
|
? '请输入手机号'
|
|
: null,
|
|
),
|
|
TextFormField(
|
|
initialValue: _idCard,
|
|
decoration: const InputDecoration(labelText: '身份证号'),
|
|
onSaved: (value) => _idCard = value,
|
|
validator: (value) => value == null || value.isEmpty
|
|
? '请输入身份证号'
|
|
: null,
|
|
),
|
|
DropdownButtonFormField<String>(
|
|
decoration: const InputDecoration(labelText: '住户类型'),
|
|
value: _memberType,
|
|
onChanged: (value) {
|
|
setState(() {
|
|
_memberType = value;
|
|
});
|
|
},
|
|
items: const [
|
|
DropdownMenuItem(value: "1", child: Text('业主')),
|
|
DropdownMenuItem(value: "2", child: Text('租户')),
|
|
],
|
|
validator: (value) =>
|
|
value == null ? '请选择住户类型' : null,
|
|
),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
OutlinedButton(
|
|
onPressed: _deleteMember,
|
|
style: OutlinedButton.styleFrom(
|
|
foregroundColor: Colors.red,
|
|
),
|
|
child: const Text('删除家庭成员'),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: _submit,
|
|
child: const Text('保存'),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
} |