diff --git a/assets/images/feedback_bg.png b/assets/images/feedback_bg.png new file mode 100644 index 0000000..1740ada Binary files /dev/null and b/assets/images/feedback_bg.png differ diff --git a/assets/images/feedback_icon.png b/assets/images/feedback_icon.png new file mode 100644 index 0000000..1c2322d Binary files /dev/null and b/assets/images/feedback_icon.png differ diff --git a/lib/controller/mine/rose_history_controller.dart b/lib/controller/mine/rose_history_controller.dart index 044bf56..3aba7e4 100644 --- a/lib/controller/mine/rose_history_controller.dart +++ b/lib/controller/mine/rose_history_controller.dart @@ -3,7 +3,7 @@ import 'package:dating_touchme_app/network/user_api.dart'; import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; -import 'package:dating_touchme_app/model/mine/user_prop_data.dart' as up; +import 'package:dating_touchme_app/model/mine/user_prop_consume_data.dart' as up; class RoseHistoryController extends GetxController { @@ -49,7 +49,7 @@ class RoseHistoryController extends GetxController { getPropList() async { try{ - final response = await _userApi.userPageUserProp( + final response = await _userApi.userPageUserPropConsumeRecord( pageNum: page.value, pageSize: size.value, ); diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index 2ce9b82..71d5e02 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -105,6 +105,8 @@ class Assets { static const String imagesEmptyIcon = 'assets/images/empty_icon.png'; static const String imagesErrorIcon = 'assets/images/error_icon.png'; static const String imagesExitRoom = 'assets/images/exit_room.png'; + static const String imagesFeedbackBg = 'assets/images/feedback_bg.png'; + static const String imagesFeedbackIcon = 'assets/images/feedback_icon.png'; static const String imagesFemale = 'assets/images/female.png'; static const String imagesFemaleEmpty = 'assets/images/female_empty.png'; static const String imagesFilterIcon = 'assets/images/filter_icon.png'; diff --git a/lib/model/mine/user_prop_consume_data.dart b/lib/model/mine/user_prop_consume_data.dart new file mode 100644 index 0000000..fb34d8f --- /dev/null +++ b/lib/model/mine/user_prop_consume_data.dart @@ -0,0 +1,60 @@ +class UserPropConsumeData { + List? records; + int? total; + int? size; + int? current; + int? pages; + + UserPropConsumeData( + {this.records, this.total, this.size, this.current, this.pages}); + + UserPropConsumeData.fromJson(Map json) { + if (json['records'] != null) { + records = []; + json['records'].forEach((v) { + records!.add(new Records.fromJson(v)); + }); + } + total = json['total']; + size = json['size']; + current = json['current']; + pages = json['pages']; + } + + Map toJson() { + final Map data = new Map(); + if (this.records != null) { + data['records'] = this.records!.map((v) => v.toJson()).toList(); + } + data['total'] = this.total; + data['size'] = this.size; + data['current'] = this.current; + data['pages'] = this.pages; + return data; + } +} + +class Records { + int? type; + int? num; + String? remark; + String? createTime; + + Records({this.type, this.num, this.remark, this.createTime}); + + Records.fromJson(Map json) { + type = json['type']; + num = json['num']; + remark = json['remark']; + createTime = json['createTime']; + } + + Map toJson() { + final Map data = new Map(); + data['type'] = this.type; + data['num'] = this.num; + data['remark'] = this.remark; + data['createTime'] = this.createTime; + return data; + } +} diff --git a/lib/network/api_urls.dart b/lib/network/api_urls.dart index 06241e9..eb91e0d 100644 --- a/lib/network/api_urls.dart +++ b/lib/network/api_urls.dart @@ -98,6 +98,8 @@ class ApiUrls { 'dating-agency-chat-audio/user/confirm/friend-apply'; static const String userPageUserProp = 'dating-agency-chat-audio/user/page/user-prop'; + static const String userPageUserPropConsumeRecord = + 'dating-agency-chat-audio/user/page/user-prop-consume-record'; //首页相关接口 static const String getMarriageList = diff --git a/lib/network/user_api.dart b/lib/network/user_api.dart index e641780..eff0898 100644 --- a/lib/network/user_api.dart +++ b/lib/network/user_api.dart @@ -13,6 +13,7 @@ import 'package:dating_touchme_app/model/mine/rose_history_data.dart'; import 'package:dating_touchme_app/model/mine/user_base_data.dart'; import 'package:dating_touchme_app/model/mine/user_count_data.dart'; import 'package:dating_touchme_app/model/mine/user_data.dart'; +import 'package:dating_touchme_app/model/mine/user_prop_consume_data.dart'; import 'package:dating_touchme_app/model/mine/user_prop_data.dart'; import 'package:dating_touchme_app/model/mine/user_rose_data.dart'; import 'package:dating_touchme_app/model/mine/wallet_account_data.dart'; @@ -256,4 +257,10 @@ abstract class UserApi { @Query('pageNum') required int pageNum, @Query('pageSize') required int pageSize, }); + + @GET(ApiUrls.userPageUserPropConsumeRecord) + Future>> userPageUserPropConsumeRecord({ + @Query('pageNum') required int pageNum, + @Query('pageSize') required int pageSize, + }); } diff --git a/lib/network/user_api.g.dart b/lib/network/user_api.g.dart index 05d71b0..7dc169b 100644 --- a/lib/network/user_api.g.dart +++ b/lib/network/user_api.g.dart @@ -1560,6 +1560,47 @@ class _UserApi implements UserApi { return httpResponse; } + @override + Future>> + userPageUserPropConsumeRecord({ + required int pageNum, + required int pageSize, + }) async { + final _extra = {}; + final queryParameters = { + r'pageNum': pageNum, + r'pageSize': pageSize, + }; + final _headers = {}; + const Map? _data = null; + final _options = + _setStreamType>>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + 'dating-agency-chat-audio/user/page/user-prop-consume-record', + 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) => UserPropConsumeData.fromJson(json as Map), + ); + } 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/feedback_page.dart b/lib/pages/mine/feedback_page.dart new file mode 100644 index 0000000..6163890 --- /dev/null +++ b/lib/pages/mine/feedback_page.dart @@ -0,0 +1,373 @@ +import 'package:dating_touchme_app/components/page_appbar.dart'; +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class FeedbackPage extends StatefulWidget { + const FeedbackPage({super.key}); + + @override + State createState() => _FeedbackPageState(); +} + +class _FeedbackPageState extends State { + + String message = ''; + final TextEditingController _messageController = TextEditingController(); + String phone = ''; + final TextEditingController _phoneController = TextEditingController(); + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Container( + width: 375.w, + height: 812.h, + color: Colors.white, + ), + Positioned( + top: -320.w, + left: -270.w, + child: Image.asset( + Assets.imagesFeedbackBg, + width: 971.75.w, + height: 781.25.w, + fit: BoxFit.cover, + ), + ), + Positioned( + top: 53.w, + left: 207.w, + child: Image.asset( + Assets.imagesFeedbackIcon, + width: 140.w, + height: 140.w, + ), + ), + Scaffold( + appBar: PageAppbar(title: "", backgroundColor: Colors.transparent,), + backgroundColor: Colors.transparent, + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.symmetric( + vertical: 22.w, + horizontal: 14.w + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "意见反馈", + style: TextStyle( + fontSize: 21.w, + fontWeight: FontWeight.w500 + ), + ), + SizedBox(height: 5.w,), + Text( + "Hi,给出你的小建议吧~", + style: TextStyle( + fontSize: 13.w, + fontWeight: FontWeight.w500 + ), + ), + ], + ), + ), + Expanded( + child: Container( + width: 375.w, + padding: EdgeInsets.symmetric( + vertical: 11.w, + horizontal: 14.w + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.vertical(top: Radius.circular(9.w)), + color: Colors.white + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16.w, + fontWeight: FontWeight.w500 + ), + children: [ + TextSpan( + text: "选择问题的类型", + style: TextStyle( + color: const Color.fromRGBO(51, 51, 51, 1) + ) + ), + TextSpan( + text: "*", + style: TextStyle( + color: const Color.fromRGBO(248, 85, 66, 1) + ) + ) + ] + ), + ), + SizedBox(height: 11.w,), + Wrap( + alignment: WrapAlignment.spaceBetween, + spacing: 10.w, + runSpacing: 10.w, + children: [ + TagItem(title: "举报投诉"), + TagItem(title: "账号与个人信息"), + TagItem(title: "现有功能建议"), + TagItem(title: "新功能或玩法建议"), + ], + ), + SizedBox(height: 20.w,), + RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16.w, + fontWeight: FontWeight.w500 + ), + children: [ + TextSpan( + text: "问题描述", + style: TextStyle( + color: const Color.fromRGBO(51, 51, 51, 1) + ) + ), + TextSpan( + text: "*", + style: TextStyle( + color: const Color.fromRGBO(248, 85, 66, 1) + ) + ) + ] + ), + ), + SizedBox(height: 11.w,), + Container( + padding: EdgeInsets.all(14.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8.w)), + color: const Color.fromRGBO(245, 245, 245, 1) + ), + child: TextField( + controller: _messageController, + maxLength: 500, // 上限 + minLines: 5, // 多行 + maxLines: 5, // 自适应高度 + style: TextStyle( + fontSize: ScreenUtil().setWidth(13), + height: 1 + ), + decoration: InputDecoration( + contentPadding: EdgeInsets.symmetric( + vertical: 0, + horizontal: 0 + ), + hintText: "请输入交友心声", + + 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){ + message = value; + }, + ), + ), + SizedBox(height: 10.w,), + Wrap( + alignment: WrapAlignment.spaceBetween, + spacing: 10.w, + runSpacing: 10.w, + children: [ + Container( + width: 70.w, + height: 70.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + border: Border.all(width: 1, color: const Color.fromRGBO(224, 224, 224, 1)) + ), + ), + Container( + width: 70.w, + height: 70.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + border: Border.all(width: 1, color: const Color.fromRGBO(224, 224, 224, 1)) + ), + ), + Container( + width: 70.w, + height: 70.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + border: Border.all(width: 1, color: const Color.fromRGBO(224, 224, 224, 1)) + ), + ), + Container( + width: 70.w, + height: 70.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + border: Border.all(width: 1, color: const Color.fromRGBO(224, 224, 224, 1)) + ), + ), + ], + ), + SizedBox(height: 10.w,), + Text( + "上传问题截图可以让问题快速解决!", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(189, 189, 189, 1) + ), + ), + SizedBox(height: 20.w,), + RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16.w, + fontWeight: FontWeight.w500 + ), + children: [ + TextSpan( + text: "联系方式", + style: TextStyle( + color: const Color.fromRGBO(51, 51, 51, 1) + ) + ), + ] + ), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: 13.w), + margin: EdgeInsets.only(top: 7.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8.w)), + color: const Color.fromRGBO(245, 245, 245, 1) + ), + child: TextField( + controller: _phoneController, + keyboardType: TextInputType.number, + style: TextStyle( + fontSize: ScreenUtil().setWidth(14), + height: 1 + ), + decoration: InputDecoration( + hintText: "留下手机号、QQ、邮箱,以便我们回复您", + contentPadding: EdgeInsets.symmetric( + vertical: 0, + horizontal: 0 + ), + + 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){ + phone = value; + setState(() { + + }); + }, + ), + ), + Container( + margin: EdgeInsets.symmetric(vertical: 30.w), + child: Container( + width: 350.w, + height: 45.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(45.w)), + gradient: LinearGradient( + begin: Alignment.centerLeft, // 90deg: 从左到右 + end: Alignment.centerRight, + colors: [ + Color.fromRGBO(131, 89, 255, 1), // 起点颜色 + Color.fromRGBO(77, 127, 231, 1), // 中间颜色 + Color.fromRGBO(61, 138, 224, 1), // 终点颜色 + ], + stops: [0.0, 0.7753, 1.0], // 对应 0%、77.53%、100% + ), + ), + child: Center( + child: Text( + "确认", + style: TextStyle( + fontSize: 18.w, + color: Colors.white, + fontWeight: FontWeight.w500 + ), + ), + ), + ), + ) + ], + ), + ), + ), + ) + ], + ), + ) + ], + ); + } +} + + + +class TagItem extends StatefulWidget { + final String title; + const TagItem({super.key, required this.title}); + + @override + State createState() => _TagItemState(); +} + +class _TagItemState extends State { + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric( + vertical: 9.w, + horizontal: 14.w + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8.w)), + border: Border.all(width: 1, color: const Color.fromRGBO(207, 207, 207, 1)) + ), + child: Text( + widget.title, + style: TextStyle( + fontSize: 13.w + ), + ), + ); + } +} + diff --git a/lib/pages/mine/rose_history_page.dart b/lib/pages/mine/rose_history_page.dart index 3c83dcd..9cf5a9d 100644 --- a/lib/pages/mine/rose_history_page.dart +++ b/lib/pages/mine/rose_history_page.dart @@ -6,7 +6,7 @@ import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; -import 'package:dating_touchme_app/model/mine/user_prop_data.dart' as up; +import 'package:dating_touchme_app/model/mine/user_prop_consume_data.dart' as up; class RoseHistoryPage extends StatelessWidget { @@ -249,7 +249,7 @@ class _ChatCouponItemState extends State { ), ), Text( - "${widget.item.startTime}", + "${widget.item.createTime}", style: TextStyle( fontSize: 11.w, color: const Color.fromRGBO(144, 144, 144, 1) diff --git a/lib/pages/mine/user_help_center_page.dart b/lib/pages/mine/user_help_center_page.dart index 92b525a..85d411c 100644 --- a/lib/pages/mine/user_help_center_page.dart +++ b/lib/pages/mine/user_help_center_page.dart @@ -1,6 +1,7 @@ import 'package:dating_touchme_app/components/page_appbar.dart'; import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:dating_touchme_app/pages/mine/feedback_page.dart'; import 'package:dating_touchme_app/pages/mine/help_info_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -272,7 +273,9 @@ class _UserHelpCenterPageState extends State { ), ) ], - ), + ).onTap((){ + Get.to(() => FeedbackPage()); + }), ), Container( width: 1,