From d9674f14e19534eef56fcfb60a92cd7a55b3cd0c Mon Sep 17 00:00:00 2001 From: YakumoChen Date: Fri, 7 Nov 2025 22:01:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=92=E7=89=88=E4=BF=AE=E6=94=B9=E8=B5=84?= =?UTF-8?q?=E6=96=99=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/edit_avatar.png | Bin 0 -> 2047 bytes lib/components/page_appbar.dart | 6 +- lib/config/app_config.dart | 2 +- lib/http/api.dart | 34 ++- lib/pages/edit_info_page.dart | 443 ++++++++++++++++++++++++++++++++ lib/pages/login_page.dart | 75 +++++- lib/pages/my_page.dart | 39 +-- lib/pages/signature_page.dart | 70 +++++ lib/router/app_router.dart | 12 + lib/router/route_paths.dart | 4 + 10 files changed, 644 insertions(+), 41 deletions(-) create mode 100644 assets/edit_avatar.png create mode 100644 lib/pages/edit_info_page.dart create mode 100644 lib/pages/signature_page.dart diff --git a/assets/edit_avatar.png b/assets/edit_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..6dd92fbb1e683b9bc916cd19d91f8f183d187cd2 GIT binary patch literal 2047 zcmVPx#1am@3R0s$N2z&@+hyVZwsYygZRCt{2TrF(lNECjK7C2hcE?T9aUXbF#W${Xu z7Db2bgJlyK5^jer2r0B#m(_+vCt0ckR$AC&rv@|&Y85plE1AuK__fo?*d9B!)12-j zNyZa<{Q3ROn>SXVWl&1>^y?t~)S1KhJ>otQb45}3wnm|}agmf1JN>EGa7qUNKv9%w z4d>boD5W~3^qMvgn^I~QkLZn{MPh_x)qOv;sTh4xBfY5aVzF4>+}tby0Kzc*h3%f_ zEdc-sAsPUHVHn5k|4h>?JU6WER#cbzZB392F^k1w2>>vg&E`l#RrtO?0FWZf0odM7 zZADNj(oWX##bU9ngOn@~LNvoLjtj_gwjrr9L6p*K$dH<*i4no~{Xq^GxYUym-zLA5-AW2Wdl}uz3B(gjEN)952q)bT?+8_}* zZ`oUwMTU11+9PR#>dd|1d`cE!82+j|#uAVeDT?xi@Ar;x$WpDk2392{VVWiwhEc0} z&t|i^>$)1#q*F?DUW!CENN0c4X?My>4vW*%Q>~6MAUw}oVwQoy#>0C>kjQJ5C5I5A z`My86zrP>x$JkgTkp%Yd_xsv51dA}6&G>uM`2dnvF^Bz8MYU|({@UyHJ_4*I1_>sF zXi1VJs;a6ADQ_{r&w235w(R zVLF}u1@M}kc`RaGrRJc~S!#@Zl<{gaIN1FW9_rPRi!jO5^;5!m+l z`1n-zX|t-XW&i-7*Xw<(;w4442)}dy#I9HNCT!dO%D3ei+#f%F{8M7=0Pym#WQ;jL zd2cE5XlSfA;vfKd<4g$AK79Caz_tZJ5amf<6K%9~A^?DTrxkf1glLbCk7G)yeSUuar)iqHX`1@^`T3tn zfQT%#dEIVTtvhfOMAmXC*Sg{R{=jwJGxT_@mt#GW>$+z=33qpQ&r%}mX=Q<{y$lAe z6Xg5;U^pCpX4_aV#CxRSaQK-e>HGKZe~(6^i!cmt+E_(tl^{ZhW}2psQnFgDo`N8V z#^dp&q9{{EQKsYZ_%e>;2P8^WRWNWBBxZxVHn<6 zmi1~q&GWqF(b186b#?WV?fdQ9w?CR1R~}lEAUNRVO zWmJUiqpGUPm&4Qzk*jY_f>`w`6R)s+d%fO4Uf(9r0j^N84Ke=x`?qjLUex!~r%xZ7 z8POVodyiU^AU1w^|Ngz2*Ox_^zD=Mtg5o%S!tXe#lmXkfN+zHT1U4?(P_d>AVHk$L zFt%B(R!=h11mE`u_@5+6k|sltEVL#;p64ymiya;w9^3QNM{7fm;<2ZikcDpK@ zvPEo@N+|D6_)RKhY7=qyjqKp+L>12` zsGr^_!xIstLj_y3Z^$Sv-`Jv%Rm53YiuMJ0hM7gyY<|NQ-QM0dR_WC?%G`^Ppwy!| zY+DmGg1dn4`vbv*JahL??q(LzuEKq;wwJX#EM#{3{3l4tAV*j{&O#=mxWTSzn)*Je zTh4ZL|5!ScS4ltYdqvw!vfEtv(7PTHp@bolmuzpqhB?YAUNgb*!P6&j3*WWzCWL5{$wcJF0ovFW&LZ!v3vClsKn#F{x5`4Jucp9~;3i*9Q9um9u3k-n zVCFPVUO&tmZ7W$w3P9l!RRk4OibtKV$3eTK7xm?nY?wdhUylRuk`6sRJ=G-F>>{Xv zn8rZYZ-m+fuBqh90^S5tqS_# createState() => _EditInfoPageState(); +} + +class _EditInfoPageState extends State { + + int menuActive = 1; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: PageAppbar(title: "编辑资料"), + body: SingleChildScrollView( + child: Column( + children: [ + Row( + children: [ + Expanded( + child: InkWell( + onTap: (){ + menuActive = 1; + setState(() { + + }); + }, + child: Container( + height: 98.w, + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1, + color: menuActive == 1 ? const Color.fromRGBO(117, 98, 249, 1) : const Color.fromRGBO(242, 242, 242, 1)) + ) + ), + child: Center( + child: Text( + "预览", + style: TextStyle( + fontSize: 27.w, + color: menuActive == 1 ? const Color.fromRGBO(117, 98, 249, 1) : const Color.fromRGBO(144, 144, 144, 1) + ), + ), + ), + ), + ), + ), + Expanded( + child: InkWell( + onTap: (){ + menuActive = 2; + setState(() { + + }); + }, + child: Container( + height: 98.w, + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1, + color: menuActive == 2 ? const Color.fromRGBO(117, 98, 249, 1) : const Color.fromRGBO(242, 242, 242, 1)) + ) + ), + child: Center( + child: Text( + "预览", + style: TextStyle( + fontSize: 27.w, + color: menuActive == 2 ? const Color.fromRGBO(117, 98, 249, 1) : const Color.fromRGBO(144, 144, 144, 1) + ), + ), + ), + ), + ), + ), + ], + ), + SizedBox(height: 52.w,), + Stack( + children: [ + SizedBox( + child: ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(170.w)), + child: Image.asset( + "assets/user_avatar.png", + width: 170.w, + height: 170.w, + ), + ), + ), + Positioned( + right: 17.w, + bottom: 2.w, + child: Image.asset( + "assets/edit_avatar.png", + width: 34.w, + height: 34.w, + ), + ) + ], + ), + SizedBox(height: 41.w,), + Container( + width: 750.w, + padding: EdgeInsets.only( + left: 29.w, + right: 40.w + ), + child: Column( + children: [ + Row( + children: [ + Text( + "个人相册", + style: TextStyle( + fontSize: 26.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ) + ], + ), + SizedBox(height: 10.w,), + Container( + width: 681.w, + margin: EdgeInsets.only(bottom: 70.w), + child: Wrap( + spacing: 10.w, + runSpacing: 10.w, + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(18.w)), + child: Image.network( + "https://fastly.picsum.photos/id/1003/400/400.jpg?hmac=aA6suLuxF9UGDuOSzWauxOJBgBT0XeUFVqMIIjO4hJU", + width: 141.w, + height: 141.w, + ), + ), + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(18.w)), + child: Image.network( + "https://fastly.picsum.photos/id/342/400/400.jpg?hmac=u_p3Kwp2J2A0XENzZfDKmtTzLjqsxLF48EUgImcL6v8", + width: 141.w, + height: 141.w, + ), + ), + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(18.w)), + child: Image.network( + "https://fastly.picsum.photos/id/935/400/400.jpg?hmac=d-_aU-UWnAMEk7lMRmhv-yD1sBBeSmiQ9fbTmcQqDT4", + width: 141.w, + height: 141.w, + ), + ), + Container( + width: 141.w, + height: 141.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(18.w)), + border: Border.all(width: 1, color: const Color.fromRGBO(224, 224, 224, 1)) + ), + child: Center( + child: Icon( + Icons.add, + size: 30.w, + color: const Color.fromRGBO(144, 144, 144, 1), + ), + ), + ) + ], + ), + ), + Row( + children: [ + Text( + "基本信息", + style: TextStyle( + fontSize: 26.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ) + ], + ), + SizedBox(height: 5.w,), + SetItem(label: "昵称",), + Container( + margin: EdgeInsets.only(bottom: 6.w), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(width: 1, color: const Color.fromRGBO(245, 245, 245, 1)) + ) + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + RichText( + text: TextSpan( + children: [ + TextSpan( + text: "性别", + style: TextStyle( + fontSize: 26.w, + color: const Color.fromRGBO(51, 51, 51, 1), + fontWeight: FontWeight.w500 + ) + ), + ] + ), + ), + Row( + children: [ + Text( + "男", + style: TextStyle( + fontSize: 26.w, + fontWeight: FontWeight.w500, + color: const Color.fromRGBO(51, 51, 51, 1) + ), + ), + SizedBox(width: 30.w,), + Image.asset( + "assets/male.png", + width: 26.w, + height: 26.w, + color: const Color.fromRGBO(218, 218, 218, 1) + ) + ], + ) + + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + RichText( + text: TextSpan( + children: [ + TextSpan( + text: "生日", + style: TextStyle( + fontSize: 26.w, + color: const Color.fromRGBO(51, 51, 51, 1), + fontWeight: FontWeight.w500 + ) + ), + TextSpan( + text: "*", + style: TextStyle( + fontSize: 26.w, + color: const Color.fromRGBO(224, 54, 54, 1), + fontWeight: FontWeight.w500 + ) + ), + ] + ), + ), + Row( + children: [ + Text( + "1989-06-30", + style: TextStyle( + fontSize: 26.w, + fontWeight: FontWeight.w500, + color: const Color.fromRGBO(51, 51, 51, 1) + ), + ), + SizedBox(width: 30.w,), + Icon( + Icons.keyboard_arrow_right, + size: 26.w, + color: const Color.fromRGBO(191, 191, 191, 1) + ) + ], + ) + ], + ), + ], + ), + ), + SetItem(label: "身高",), + SetItem(label: "所在地", showRequired: false,), + SetItem(label: "家乡",), + SetItem(label: "学历",), + SetItem(label: "职业",), + SetItem(label: "公司", showRequired: false,), + SetItem(label: "月收入",), + SetItem(label: "婚姻状况", showRequired: false,), + SetItem(label: "有无房产", showRequired: false,), + SizedBox(height: 16.w,), + InkWell( + onTap: (){ + context.pushNamed(RouteNames.signature); + }, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "交友心声", + style: TextStyle( + fontSize: 26.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ), + Icon( + Icons.keyboard_arrow_right, + size: 26.w, + color: const Color.fromRGBO(191, 191, 191, 1) + ) + ], + ), + Container( + margin: EdgeInsets.only(bottom: 6.w), + padding: EdgeInsets.only(bottom: 24.w), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(width: 1, color: const Color.fromRGBO(245, 245, 245, 1)) + ) + ), + child: Text( + "拒绝内耗,向阳而生,用热爱抵御岁月漫长,用真诚对待每一次相遇拒绝内耗,向阳而生,用热爱抵御岁月漫长,用真诚对待每一次相遇", + style: TextStyle( + fontSize: 26.w, + fontWeight: FontWeight.w500, + color: const Color.fromRGBO(51, 51, 51, 1) + ), + ), + ), + ], + ), + ), + SetItem(label: "个性标签", showRequired: false,), + SizedBox(height: 16.w,), + Row( + children: [ + Text( + "交友范围", + style: TextStyle( + fontSize: 26.w, + color: const Color.fromRGBO(144, 144, 144, 1) + ), + ) + ], + ), + SizedBox(height: 5.w,), + SetItem(label: "所在地", showRequired: false,), + SetItem(label: "年龄", showRequired: false,), + SetItem(label: "身高", showRequired: false,), + SetItem(label: "最低学历", showRequired: false,), + SetItem(label: "最低月收入", showRequired: false,), + ], + ), + ) + ], + ), + ), + ); + } +} + +class SetItem extends StatefulWidget { + final String label; + final bool showRequired; + const SetItem({super.key, required this.label, this.showRequired = true}); + + @override + State createState() => _SetItemState(); +} + +class _SetItemState extends State { + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only(bottom: 6.w), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(width: 1, color: const Color.fromRGBO(245, 245, 245, 1)) + ) + ), + child: InkWell( + child: SizedBox( + height: 83.w, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + RichText( + text: TextSpan( + children: [ + TextSpan( + text: widget.label, + style: TextStyle( + fontSize: 26.w, + color: const Color.fromRGBO(51, 51, 51, 1), + fontWeight: FontWeight.w500 + ) + ), + if(widget.showRequired) TextSpan( + text: "*", + style: TextStyle( + fontSize: 26.w, + color: const Color.fromRGBO(224, 54, 54, 1), + fontWeight: FontWeight.w500 + ) + ), + ] + ), + ), + Row( + children: [ + Text( + "未选择", + style: TextStyle( + fontSize: 26.w, + color: const Color.fromRGBO(191, 191, 191, 1) + ), + ), + SizedBox(width: 30.w,), + Icon( + Icons.keyboard_arrow_right, + size: 26.w, + color: const Color.fromRGBO(191, 191, 191, 1) + ) + ], + ) + ], + ), + ), + ), + ); + } +} + diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart index 2456aba..0f147ca 100644 --- a/lib/pages/login_page.dart +++ b/lib/pages/login_page.dart @@ -1,5 +1,9 @@ +import 'dart:async'; + +import 'package:dating_touchme_app/http/api.dart'; import 'package:dating_touchme_app/model/phone_code.dart'; import 'package:dating_touchme_app/router/route_paths.dart'; +import 'package:dating_touchme_app/utils/storage.dart'; import 'package:dating_touchme_app/utils/utils.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; @@ -23,6 +27,7 @@ class _LoginPageState extends State { String selectPhoneCode = "86"; int s = 0; + Timer? timer; bool checked = false; @@ -33,6 +38,29 @@ class _LoginPageState extends State { }); } + sendMsg() async { + var res = await Api().$getAuthCaptcha({ + "purpose":1, + "verifiableAccount":phone, + "verifiableAccountType":1 + }); + if(res["message"] == "successful"){ + toast("发送成功", context); + setState(() { + s = 60; + timer = Timer.periodic(const Duration(seconds: 1), (timer) { + setState(() { + s--; + if(s == 0){ + timer.cancel(); + } + }); + }); + }); + } else { + toast(res["msg"], context); + } + } @override Widget build(BuildContext context) { @@ -169,6 +197,9 @@ class _LoginPageState extends State { ), onChanged: (value){ phone = value; + setState(() { + + }); }, )), InputItem(child: TextField( @@ -197,7 +228,7 @@ class _LoginPageState extends State { // toast("请输入正确的手机号", context); // return; // } - // sendMsg(); + sendMsg(); }, child: Text( s > 0 ? "${s}s后再获取" : "获取验证码", @@ -222,6 +253,9 @@ class _LoginPageState extends State { ), onChanged: (value){ code = value; + setState(() { + + }); }, )), SizedBox(height: 12.w,), @@ -287,7 +321,34 @@ class _LoginPageState extends State { ), SizedBox(height: 175.w,), InkWell( - onTap: (){ + onTap: () async { + context.goNamed(RouteNames.completeInfo); + return; + if(phone == ""){ + toast("请输入手机号", context); + return; + } + if(code == ""){ + toast("请输入6位数字验证码", context); + return; + } + if(!checked) { + toast("请阅读并同意用户协议", context); + return; + } + var res = await Api().$login({ + "account":phone, + "accountType":2, + "captcha":code + }); + if(res["code"] == 200){ + // toast("登录成功", context); + // await Storage().removeStorage("token"); + // await Storage().setStorage("token", res["data"]["token"]); + } else { + toast(res["msg"], context); + } + context.goNamed(RouteNames.completeInfo); }, child: Container( @@ -295,7 +356,15 @@ class _LoginPageState extends State { height: 105.w, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(105.w)), - color: const Color.fromRGBO(217, 217, 217, 1) + color: const Color.fromRGBO(217, 217, 217, 1), + gradient: phone != "" && code != "" ? LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color.fromRGBO(131, 89, 255, 1), // 起始颜色 + Color.fromRGBO(61, 138, 224, 1), // 结束颜色 + ], + ) : null, ), child: Center( child: Text( diff --git a/lib/pages/my_page.dart b/lib/pages/my_page.dart index 8ffae4a..2fa0866 100644 --- a/lib/pages/my_page.dart +++ b/lib/pages/my_page.dart @@ -1,5 +1,7 @@ +import 'package:dating_touchme_app/router/route_paths.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:go_router/go_router.dart'; class MyPage extends StatefulWidget { const MyPage({super.key}); @@ -102,23 +104,28 @@ class _MyPageState extends State { ) ], ), - Row( - children: [ - Image.asset( - "assets/edit.png", - width: 20.w, - height: 20.w, - ), - SizedBox(width: 8.w,), - Text( - "编辑资料", - style: TextStyle( - fontSize: 24.w, - color: const Color.fromRGBO(55, 57, 72, 1), - fontWeight: FontWeight.w500 + InkWell( + onTap: (){ + context.pushNamed(RouteNames.editInfo); + }, + child: Row( + children: [ + Image.asset( + "assets/edit.png", + width: 20.w, + height: 20.w, ), - ) - ], + SizedBox(width: 8.w,), + Text( + "编辑资料", + style: TextStyle( + fontSize: 24.w, + color: const Color.fromRGBO(55, 57, 72, 1), + fontWeight: FontWeight.w500 + ), + ) + ], + ), ) ], ), diff --git a/lib/pages/signature_page.dart b/lib/pages/signature_page.dart new file mode 100644 index 0000000..2ccf5f1 --- /dev/null +++ b/lib/pages/signature_page.dart @@ -0,0 +1,70 @@ +import 'package:dating_touchme_app/components/page_appbar.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class SignaturePage extends StatefulWidget { + const SignaturePage({super.key}); + + @override + State createState() => _SignaturePageState(); +} + +class _SignaturePageState extends State { + + + String message = '拒绝内耗,向阳而生,用热爱抵御岁月漫长,用真诚对待每一次相遇拒绝内耗,向阳而生,用热爱抵御岁月漫长,用真诚对待每一次相遇'; + final TextEditingController _messageController = TextEditingController(); + + @override + void initState() { + super.initState(); + + _messageController.value = TextEditingValue( + text: message, + selection: TextSelection.fromPosition(TextPosition(offset: message.length)), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: PageAppbar(title: "交友心声",), + body: Container( + padding: EdgeInsets.all(35.w), + child: TextField( + controller: _messageController, + maxLength: 50, // 上限 + minLines: 5, // 多行 + maxLines: 5, // 自适应高度 + style: TextStyle( + fontSize: ScreenUtil().setWidth(26), + 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; + }, + ), + ), + ); + } +} diff --git a/lib/router/app_router.dart b/lib/router/app_router.dart index d8d05f1..1435a08 100644 --- a/lib/router/app_router.dart +++ b/lib/router/app_router.dart @@ -1,10 +1,12 @@ import 'package:dating_touchme_app/pages/complete_info.dart'; +import 'package:dating_touchme_app/pages/edit_info_page.dart'; import 'package:dating_touchme_app/pages/home_page.dart'; import 'package:dating_touchme_app/pages/live_room_page.dart'; import 'package:dating_touchme_app/pages/login_page.dart'; import 'package:dating_touchme_app/pages/message_page.dart'; import 'package:dating_touchme_app/pages/notify_page.dart'; import 'package:dating_touchme_app/pages/open_webview.dart'; +import 'package:dating_touchme_app/pages/signature_page.dart'; import 'package:dating_touchme_app/pages/test_page.dart'; import 'package:dating_touchme_app/pages/user_info_page.dart'; import 'package:dating_touchme_app/router/route_paths.dart'; @@ -82,6 +84,16 @@ class AppRouter { return MessagePage(id: id,); }, ), + GoRoute( + name: RouteNames.editInfo, + path: RoutePaths.editInfo, + builder: (context, state) => const EditInfoPage(), + ), + GoRoute( + name: RouteNames.signature, + path: RoutePaths.signature, + builder: (context, state) => const SignaturePage(), + ), GoRoute( name: RouteNames.test, path: RoutePaths.test, diff --git a/lib/router/route_paths.dart b/lib/router/route_paths.dart index dc6a53a..437f628 100644 --- a/lib/router/route_paths.dart +++ b/lib/router/route_paths.dart @@ -8,6 +8,8 @@ class RouteNames { static const liveRoom = 'liveRoom'; static const notify = 'notify'; static const message = 'message'; + static const editInfo = 'editInfo'; + static const signature = 'signature'; static const test = 'test'; } @@ -20,5 +22,7 @@ class RoutePaths { static const liveRoom = '/liveRoom'; static const notify = '/notify'; static const message = '/message'; + static const editInfo = '/editInfo'; + static const signature = '/signature'; static const test = '/test'; }