diff --git a/assets/images/edit_avatar.png b/assets/images/edit_avatar.png new file mode 100644 index 0000000..6dd92fb Binary files /dev/null and b/assets/images/edit_avatar.png differ diff --git a/lib/controller/mine/edit_info_controller.dart b/lib/controller/mine/edit_info_controller.dart index bcf3b24..ad85a60 100644 --- a/lib/controller/mine/edit_info_controller.dart +++ b/lib/controller/mine/edit_info_controller.dart @@ -1,14 +1,19 @@ import 'package:dating_touchme_app/controller/global.dart'; import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:dating_touchme_app/model/mine/education_data.dart'; +import 'package:dating_touchme_app/model/mine/occupation_data.dart'; import 'package:dating_touchme_app/model/mine/user_data.dart'; +import 'package:dating_touchme_app/network/user_api.dart'; import 'package:dating_touchme_app/pages/mine/auth_center_page.dart'; import 'package:dating_touchme_app/pages/mine/my_wallet_page.dart'; import 'package:dating_touchme_app/pages/mine/rose_page.dart'; +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; class EditInfoController extends GetxController { + late UserApi _userApi; final menuActive = 1.obs; @@ -28,10 +33,130 @@ class EditInfoController extends GetxController { final userData = GlobalData().userData.obs; + String height = ''; + final TextEditingController heightController = TextEditingController(); + + final educationList = [].obs; + + final incomeList = [].obs; + + final maritalList = [].obs; + + final propertyList = [].obs; + + final occupationList = [].obs; + + final occupationShowData = {}.obs; + @override void onInit() { super.onInit(); + + _userApi = Get.find(); + + getEducationList(); + getIncomeList(); + getMaritalList(); + getPropertyList(); + getOccupationList(); + } + + getEducationList() async { + try { + final response = await _userApi.getEducationList({}); + if (response.data.isSuccess && response.data.data != null) { + final data = response.data.data; + educationList.clear(); + educationList.addAll(data?.toList() ?? []); + } else { + // 响应失败,抛出异常 + throw Exception(response.data.message ?? '获取数据失败'); + } + } catch(e){ + print('学历列表获取失败: $e'); + SmartDialog.showToast('学历列表获取失败'); + rethrow; + } + } + + getIncomeList() async { + try { + final response = await _userApi.getIncomeList({}); + if (response.data.isSuccess && response.data.data != null) { + final data = response.data.data; + incomeList.clear(); + incomeList.addAll(data?.toList() ?? []); + } else { + // 响应失败,抛出异常 + throw Exception(response.data.message ?? '获取数据失败'); + } + } catch(e){ + print('收入列表获取失败: $e'); + SmartDialog.showToast('收入列表获取失败'); + rethrow; + } + } + + getMaritalList() async { + try { + final response = await _userApi.getMaritalStatusList({}); + if (response.data.isSuccess && response.data.data != null) { + final data = response.data.data; + maritalList.clear(); + maritalList.addAll(data?.toList() ?? []); + } else { + // 响应失败,抛出异常 + throw Exception(response.data.message ?? '获取数据失败'); + } + } catch(e){ + print('收入列表获取失败: $e'); + SmartDialog.showToast('收入列表获取失败'); + rethrow; + } } + getPropertyList() async { + try { + final response = await _userApi.getPropertyList({}); + if (response.data.isSuccess && response.data.data != null) { + final data = response.data.data; + propertyList.clear(); + propertyList.addAll(data?.toList() ?? []); + } else { + // 响应失败,抛出异常 + throw Exception(response.data.message ?? '获取数据失败'); + } + } catch(e){ + print('收入列表获取失败: $e'); + SmartDialog.showToast('收入列表获取失败'); + rethrow; + } + } + + getOccupationList() async { + try { + final response = await _userApi.getOccupationList({}); + if (response.data.isSuccess && response.data.data != null) { + final data = response.data.data; + occupationList.clear(); + occupationList.addAll(data?.toList() ?? []); + for(int i = 0; i < occupationList.length; i++){ + occupationShowData[occupationList[i].industry] = occupationList[i].occupationList?.map((e){ + return e.occupation; + }).toList(); + } + print(occupationShowData); + } else { + // 响应失败,抛出异常 + throw Exception(response.data.message ?? '获取数据失败'); + } + } catch(e){ + print('收入列表获取失败: $e'); + SmartDialog.showToast('收入列表获取失败'); + rethrow; + } + } + + } \ No newline at end of file diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index b5fefa0..ed5b33d 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -89,6 +89,7 @@ class Assets { static const String imagesDiscoverNol = 'assets/images/discover_nol.png'; static const String imagesDiscoverPre = 'assets/images/discover_pre.png'; static const String imagesEdit = 'assets/images/edit.png'; + static const String imagesEditAvatar = 'assets/images/edit_avatar.png'; static const String imagesEditAvatarsIcon = 'assets/images/edit_avatars_icon.png'; static const String imagesEmoji = 'assets/images/emoji.png'; static const String imagesEmojiTab = 'assets/images/emoji_tab.png'; diff --git a/lib/model/mine/education_data.dart b/lib/model/mine/education_data.dart new file mode 100644 index 0000000..960207d --- /dev/null +++ b/lib/model/mine/education_data.dart @@ -0,0 +1,18 @@ +class EducationData { + int? value; + String? desc; + + EducationData({this.value, this.desc}); + + EducationData.fromJson(Map json) { + value = json['value']; + desc = json['desc']; + } + + Map toJson() { + final Map data = new Map(); + data['value'] = this.value; + data['desc'] = this.desc; + return data; + } +} diff --git a/lib/model/mine/occupation_data.dart b/lib/model/mine/occupation_data.dart new file mode 100644 index 0000000..1b18bd5 --- /dev/null +++ b/lib/model/mine/occupation_data.dart @@ -0,0 +1,48 @@ +class OccupationData { + int? industryCode; + String? industry; + List? occupationList; + + OccupationData({this.industryCode, this.industry, this.occupationList}); + + OccupationData.fromJson(Map json) { + industryCode = json['industryCode']; + industry = json['industry']; + if (json['occupationList'] != null) { + occupationList = []; + json['occupationList'].forEach((v) { + occupationList!.add(new OccupationList.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = new Map(); + data['industryCode'] = this.industryCode; + data['industry'] = this.industry; + if (this.occupationList != null) { + data['occupationList'] = + this.occupationList!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class OccupationList { + int? occupationCode; + String? occupation; + + OccupationList({this.occupationCode, this.occupation}); + + OccupationList.fromJson(Map json) { + occupationCode = json['occupationCode']; + occupation = json['occupation']; + } + + Map toJson() { + final Map data = new Map(); + data['occupationCode'] = this.occupationCode; + data['occupation'] = this.occupation; + return data; + } +} diff --git a/lib/network/api_urls.dart b/lib/network/api_urls.dart index a5864ae..26ae64e 100644 --- a/lib/network/api_urls.dart +++ b/lib/network/api_urls.dart @@ -18,6 +18,11 @@ class ApiUrls { static const String pageVirtualAccountRecord = 'dating-agency-mall/user/page/virtual-account-record'; static const String getCertificationList = 'dating-agency-service/user/get/certification/item/all/list'; static const String submitOrder = 'dating-agency-mall/user/submit/order'; + static const String getEducationList = 'dating-agency-service/user/get/education/list'; + static const String getIncomeList = 'dating-agency-service/user/get/income/list'; + static const String getMaritalStatusList = 'dating-agency-service/user/get/marital/status/list'; + static const String getPropertyList = 'dating-agency-service/user/get/property/permits'; + static const String getOccupationList = 'dating-agency-service/user/get/occupation/list'; //首页相关接口 static const String getMarriageList = 'dating-agency-service/user/page/dongwo/marriage-information'; diff --git a/lib/network/user_api.dart b/lib/network/user_api.dart index 731b951..30d98ad 100644 --- a/lib/network/user_api.dart +++ b/lib/network/user_api.dart @@ -1,5 +1,7 @@ import 'package:dating_touchme_app/model/common/oss_data.dart'; +import 'package:dating_touchme_app/model/mine/education_data.dart'; import 'package:dating_touchme_app/model/mine/login_data.dart'; +import 'package:dating_touchme_app/model/mine/occupation_data.dart'; import 'package:dating_touchme_app/model/mine/rose_data.dart'; import 'package:dating_touchme_app/model/mine/rose_history_data.dart'; import 'package:dating_touchme_app/model/mine/user_base_data.dart'; @@ -84,4 +86,29 @@ abstract class UserApi { Future>> submitOrder( @Body() Map data, ); + + @GET(ApiUrls.getEducationList) + Future>>> getEducationList( + @Body() Map data, + ); + + @GET(ApiUrls.getIncomeList) + Future>>> getIncomeList( + @Body() Map data, + ); + + @GET(ApiUrls.getMaritalStatusList) + Future>>> getMaritalStatusList( + @Body() Map data, + ); + + @GET(ApiUrls.getPropertyList) + Future>>> getPropertyList( + @Body() Map data, + ); + + @GET(ApiUrls.getOccupationList) + Future>>> getOccupationList( + @Body() Map data, + ); } diff --git a/lib/network/user_api.g.dart b/lib/network/user_api.g.dart index 33890cb..0061c0f 100644 --- a/lib/network/user_api.g.dart +++ b/lib/network/user_api.g.dart @@ -512,6 +512,221 @@ class _UserApi implements UserApi { return httpResponse; } + @override + Future>>> getEducationList( + Map data, + ) async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + final _data = {}; + _data.addAll(data); + final _options = + _setStreamType>>>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + 'dating-agency-service/user/get/education/list', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl), + ), + ); + final _result = await _dio.fetch>(_options); + late BaseResponse> _value; + try { + _value = BaseResponse>.fromJson( + _result.data!, + (json) => json is List + ? json + .map( + (i) => EducationData.fromJson(i as Map), + ) + .toList() + : List.empty(), + ); + } on Object catch (e, s) { + errorLogger?.logError(e, s, _options); + rethrow; + } + final httpResponse = HttpResponse(_value, _result); + return httpResponse; + } + + @override + Future>>> getIncomeList( + Map data, + ) async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + final _data = {}; + _data.addAll(data); + final _options = + _setStreamType>>>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + 'dating-agency-service/user/get/income/list', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl), + ), + ); + final _result = await _dio.fetch>(_options); + late BaseResponse> _value; + try { + _value = BaseResponse>.fromJson( + _result.data!, + (json) => json is List + ? json + .map( + (i) => EducationData.fromJson(i as Map), + ) + .toList() + : List.empty(), + ); + } on Object catch (e, s) { + errorLogger?.logError(e, s, _options); + rethrow; + } + final httpResponse = HttpResponse(_value, _result); + return httpResponse; + } + + @override + Future>>> getMaritalStatusList( + Map data, + ) async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + final _data = {}; + _data.addAll(data); + final _options = + _setStreamType>>>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + 'dating-agency-service/user/get/marital/status/list', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl), + ), + ); + final _result = await _dio.fetch>(_options); + late BaseResponse> _value; + try { + _value = BaseResponse>.fromJson( + _result.data!, + (json) => json is List + ? json + .map( + (i) => EducationData.fromJson(i as Map), + ) + .toList() + : List.empty(), + ); + } on Object catch (e, s) { + errorLogger?.logError(e, s, _options); + rethrow; + } + final httpResponse = HttpResponse(_value, _result); + return httpResponse; + } + + @override + Future>>> getPropertyList( + Map data, + ) async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + final _data = {}; + _data.addAll(data); + final _options = + _setStreamType>>>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + 'dating-agency-service/user/get/property/permits', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl), + ), + ); + final _result = await _dio.fetch>(_options); + late BaseResponse> _value; + try { + _value = BaseResponse>.fromJson( + _result.data!, + (json) => json is List + ? json + .map( + (i) => EducationData.fromJson(i as Map), + ) + .toList() + : List.empty(), + ); + } on Object catch (e, s) { + errorLogger?.logError(e, s, _options); + rethrow; + } + final httpResponse = HttpResponse(_value, _result); + return httpResponse; + } + + @override + Future>>> getOccupationList( + Map data, + ) async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + final _data = {}; + _data.addAll(data); + final _options = + _setStreamType>>>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + 'dating-agency-service/user/get/occupation/list', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl), + ), + ); + final _result = await _dio.fetch>(_options); + late BaseResponse> _value; + try { + _value = BaseResponse>.fromJson( + _result.data!, + (json) => json is List + ? json + .map( + (i) => OccupationData.fromJson(i as Map), + ) + .toList() + : List.empty(), + ); + } on Object catch (e, s) { + errorLogger?.logError(e, s, _options); + rethrow; + } + final httpResponse = HttpResponse(_value, _result); + return httpResponse; + } + RequestOptions _setStreamType(RequestOptions requestOptions) { if (T != dynamic && !(requestOptions.responseType == ResponseType.bytes || diff --git a/lib/pages/mine/edit_info_page.dart b/lib/pages/mine/edit_info_page.dart index df62650..b23dc64 100644 --- a/lib/pages/mine/edit_info_page.dart +++ b/lib/pages/mine/edit_info_page.dart @@ -6,6 +6,7 @@ import 'package:dating_touchme_app/pages/mine/tag_setting_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; class EditInfoPage extends StatefulWidget { const EditInfoPage({super.key}); @@ -105,7 +106,11 @@ class _EditInfoPageState extends State { SizedBox( child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(85.w)), - child: Image.asset( + child: (controller.userData.value?.profilePhoto?.isNotEmpty ?? false) ? Image.network( + "${controller.userData.value?.profilePhoto ?? ""}", + width: 85.w, + height: 85.w, + ) : Image.asset( Assets.imagesUserAvatar, width: 85.w, height: 85.w, @@ -116,7 +121,7 @@ class _EditInfoPageState extends State { right: 8.w, bottom: 1.w, child: Image.asset( - Assets.imagesUserAvatar, + Assets.imagesEditAvatar, width: 17.w, height: 17.w, ), @@ -205,7 +210,13 @@ class _EditInfoPageState extends State { ], ), SizedBox(height: 2.w,), - SetItem(label: "昵称",), + SetItem(label: "昵称", child: Text( + controller.userData.value?.nickName ?? "", + style: TextStyle( + fontSize: 13.w, + fontWeight: FontWeight.w500 + ), + ),), Container( margin: EdgeInsets.only(bottom: 3.w), decoration: BoxDecoration( @@ -235,7 +246,7 @@ class _EditInfoPageState extends State { Row( children: [ Text( - "${controller.userData.value?.genderValue ?? ""}", + "${controller.userData.value?.genderCode == 0 ? "男" : "女"}", style: TextStyle( fontSize: 13.w, fontWeight: FontWeight.w500, @@ -244,7 +255,8 @@ class _EditInfoPageState extends State { ), SizedBox(width: 15.w,), Image.asset( - Assets.imagesMale, + controller.userData.value?.genderCode == 0 ? + Assets.imagesMale : Assets.imagesFemale, width: 13.w, height: 13.w, color: const Color.fromRGBO(218, 218, 218, 1) @@ -302,16 +314,153 @@ class _EditInfoPageState extends State { ], ), ), - SetItem(label: "身高",), - SetItem(label: "所在地", showRequired: false,), - SetItem(label: "家乡",), - SetItem(label: "学历",), - SetItem(label: "学校",), - SetItem(label: "职业",), + SetItem(label: "身高", child: Expanded( + child: TextField( + controller: controller.heightController, + keyboardType: TextInputType.number, + textAlign: TextAlign.end, + style: TextStyle( + fontSize: ScreenUtil().setWidth(13), + height: 1 + ), + decoration: InputDecoration( + contentPadding: EdgeInsets.symmetric( + vertical: 0, + horizontal: 0.w + ), + hintText: "请输入身高", + + hintStyle: TextStyle( + color: const Color.fromRGBO(191, 191, 191, 1) + + ), + + border: const OutlineInputBorder( + borderSide: BorderSide.none, // 这将移除边框 // 可选:设置圆角 + ), + // 如果你希望聚焦时和未聚焦时都没有边框,也可以设置 focusedBorder 和 enabledBorder + focusedBorder: const OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.all(Radius.circular(8.0)), + ), + enabledBorder: const OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.all(Radius.circular(8.0)), + ), + ), + onChanged: (value){ + controller.height = value; + setState(() { + + }); + }, + ), + ),), + SetItem(label: "所在地", child: SizedBox(),), + SetItem(label: "家乡", child: SizedBox(),), + SetItem(label: "学历", child: InkWell( + onTap: () { + TDPicker.showMultiPicker(context, title: '', + onConfirm: (selected) { + print(selected); + print(controller.educationList[selected[0]]); + setState(() { + + }); + Navigator.of(context).pop(); + }, data: [controller.educationList.map((e) => e.desc ?? "").toList()]); + }, + child: Text( + "请选择", + style: TextStyle( + fontSize: 13.w, + color: const Color.fromRGBO(191, 191, 191, 1) + ), + ), + ),), + SetItem(label: "职业", child: InkWell( + onTap: () { + TDPicker.showMultiLinkedPicker(context, title: '', + onConfirm: (selected) { + print(selected); + setState(() { + + }); + Navigator.of(context).pop(); + }, + data: controller.occupationShowData, + columnNum: 2, + initialData:[]); + }, + child: Text( + "请选择", + style: TextStyle( + fontSize: 13.w, + color: const Color.fromRGBO(191, 191, 191, 1) + ), + ), + ),), // SetItem(label: "公司", showRequired: false,), - // SetItem(label: "月收入",), - // SetItem(label: "婚姻状况", showRequired: false,), - // SetItem(label: "有无房产", showRequired: false,), + SetItem(label: "月收入", child: InkWell( + onTap: () { + TDPicker.showMultiPicker(context, title: '', + onConfirm: (selected) { + print(selected); + print(controller.incomeList[selected[0]]); + setState(() { + + }); + Navigator.of(context).pop(); + }, data: [controller.incomeList.map((e) => e.desc ?? "").toList()]); + }, + child: Text( + "请选择", + style: TextStyle( + fontSize: 13.w, + color: const Color.fromRGBO(191, 191, 191, 1) + ), + ), + ),), + SetItem(label: "婚姻状况", child: InkWell( + onTap: () { + TDPicker.showMultiPicker(context, title: '', + onConfirm: (selected) { + print(selected); + print(controller.maritalList[selected[0]]); + setState(() { + + }); + Navigator.of(context).pop(); + }, data: [controller.maritalList.map((e) => e.desc ?? "").toList()]); + }, + child: Text( + "请选择", + style: TextStyle( + fontSize: 13.w, + color: const Color.fromRGBO(191, 191, 191, 1) + ), + ), + ),), + SetItem(label: "有无房产", child: InkWell( + onTap: () { + TDPicker.showMultiPicker(context, title: '', + onConfirm: (selected) { + print(selected); + print(controller.propertyList[selected[0]]); + setState(() { + + }); + Navigator.of(context).pop(); + }, data: [controller.propertyList.map((e) => e.desc ?? "").toList()]); + }, + child: Text( + "请选择", + style: TextStyle( + fontSize: 13.w, + color: const Color.fromRGBO(191, 191, 191, 1) + ), + ), + ),), // SizedBox(height: 8.w,), // InkWell( // onTap: (){ @@ -702,7 +851,8 @@ class _EditInfoPageState extends State { class SetItem extends StatefulWidget { final String label; final bool showRequired; - const SetItem({super.key, required this.label, this.showRequired = true}); + final Widget child; + const SetItem({super.key, required this.label, this.showRequired = true, required this.child}); @override State createState() => _SetItemState(); @@ -746,22 +896,19 @@ class _SetItemState extends State { ] ), ), - Row( - children: [ - Text( - "未选择", - style: TextStyle( - fontSize: 13.w, - color: const Color.fromRGBO(191, 191, 191, 1) - ), - ), - SizedBox(width: 15.w,), - Icon( - Icons.keyboard_arrow_right, - size: 13.w, - color: const Color.fromRGBO(191, 191, 191, 1) - ) - ], + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + widget.child, + SizedBox(width: 15.w,), + Icon( + Icons.keyboard_arrow_right, + size: 13.w, + color: const Color.fromRGBO(191, 191, 191, 1) + ) + ], + ), ) ], ), diff --git a/lib/pages/mine/mine_page.dart b/lib/pages/mine/mine_page.dart index 7fe3c85..212a25a 100644 --- a/lib/pages/mine/mine_page.dart +++ b/lib/pages/mine/mine_page.dart @@ -69,14 +69,17 @@ class _MinePageState extends State with AutomaticKeepAliveClientMixin{ children: [ Row( children: [ - (controller.userData.value?.profilePhoto?.isNotEmpty ?? false) ? Image.network( - "${controller.userData.value?.profilePhoto ?? ""}", - width: 60.w, - height: 60.w, - ) : Image.asset( - Assets.imagesUserAvatar, - width: 60.w, - height: 60.w, + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(60.w)), + child: (controller.userData.value?.profilePhoto?.isNotEmpty ?? false) ? Image.network( + "${controller.userData.value?.profilePhoto ?? ""}", + width: 60.w, + height: 60.w, + ) : Image.asset( + Assets.imagesUserAvatar, + width: 60.w, + height: 60.w, + ), ), SizedBox(width: 14.w,), Column(