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)); } }