更新验证码选择区号
This commit is contained in:
@@ -21,6 +21,8 @@ import 'package:vbvs_app/controller/time/countdown_controller.dart';
|
||||
import 'package:vbvs_app/controller/user_info_controller.dart';
|
||||
import 'package:vbvs_app/controller/weather/weather_controller.dart';
|
||||
import 'package:vbvs_app/model/api_response.dart';
|
||||
import 'package:vbvs_app/pages/person/select_time.dart';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
class OtherLoginPage extends StatefulWidget {
|
||||
const OtherLoginPage({super.key});
|
||||
@@ -106,7 +108,7 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
|
||||
// 登录成功移出网络检查监听
|
||||
Checknetwork.subscription?.cancel();
|
||||
if (Get.currentRoute != '/mianPageBottomChange') {
|
||||
Get.offAndToNamed("/mianPageBottomChange");
|
||||
Get.offAndToNamed("/mianPageBottomChange");
|
||||
}
|
||||
}
|
||||
// TODO 操作全部跳转页面前成功以后移除监听,防止重复监听,其他方式登录成功也需要移出监听
|
||||
@@ -122,7 +124,6 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -255,6 +256,22 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
|
||||
child: Padding(
|
||||
padding: EdgeInsetsDirectional.fromSTEB(
|
||||
0, 95.rpx, 0, 0),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: bodysize.maxHeight * 0.056,
|
||||
constraints: BoxConstraints(
|
||||
minHeight: 90.rpx,
|
||||
),
|
||||
// ✅ 在这里塞进去
|
||||
child: _buildLoginMethodSelector(bodysize),
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: AlignmentDirectional(-1, 0),
|
||||
child: Padding(
|
||||
padding: EdgeInsetsDirectional.fromSTEB(
|
||||
0, 26.rpx, 0, 0),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: bodysize.maxHeight * 0.056,
|
||||
@@ -279,128 +296,161 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsetsDirectional.fromSTEB(
|
||||
26.rpx, 0, 0, 0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () async {},
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
// constraints: BoxConstraints(
|
||||
// minWidth: 150.rpx,
|
||||
// ),
|
||||
child: Text(
|
||||
"+86",
|
||||
style: TextStyle(
|
||||
fontFamily: 'Readex Pro',
|
||||
Obx(() {
|
||||
if (userInfoController
|
||||
.select_login_method.value ==
|
||||
2) {
|
||||
return Container();
|
||||
}
|
||||
return Padding(
|
||||
padding:
|
||||
EdgeInsetsDirectional.fromSTEB(
|
||||
26.rpx, 0, 0, 0),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
await showCountryCodePickerDialog(
|
||||
context,
|
||||
initialCode: userInfoController
|
||||
.select_country_code
|
||||
.value, // ✅ 来自 controller
|
||||
onConfirm: (String code) {
|
||||
print("选中的区号:$code");
|
||||
userInfoController
|
||||
.select_country_code
|
||||
.value = code;
|
||||
userInfoController
|
||||
.updateAll();
|
||||
// setState / controller.update
|
||||
},
|
||||
title: "选择区号".tr,
|
||||
);
|
||||
},
|
||||
child: Obx(() {
|
||||
return Container(
|
||||
width: 80.rpx,
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
"${userInfoController.select_country_code.value}",
|
||||
style: TextStyle(
|
||||
fontFamily:
|
||||
'Readex Pro',
|
||||
color: themeController
|
||||
.currentColor.sc2,
|
||||
fontSize: AppConstants()
|
||||
.middler_text_fontSize,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30.rpx,
|
||||
child: VerticalDivider(
|
||||
thickness: 2.rpx,
|
||||
color: themeController
|
||||
.currentColor.sc4,
|
||||
),
|
||||
),
|
||||
].divide(SizedBox(width: 10.rpx)),
|
||||
),
|
||||
);
|
||||
}),
|
||||
Obx(() {
|
||||
return Expanded(
|
||||
child: Container(
|
||||
child: Align(
|
||||
alignment:
|
||||
AlignmentDirectional(-1, 0),
|
||||
child: TextFormField(
|
||||
onChanged: (value) {
|
||||
loginController.model.phone =
|
||||
value;
|
||||
},
|
||||
autofocus: false,
|
||||
obscureText: false,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
labelStyle: TextStyle(
|
||||
fontFamily: 'Inter',
|
||||
fontSize: 26.rpx,
|
||||
letterSpacing: 0.0,
|
||||
),
|
||||
hintText: userInfoController
|
||||
.select_login_method
|
||||
.value ==
|
||||
2
|
||||
? '输入邮箱'.tr
|
||||
: "输入手机号码".tr,
|
||||
hintStyle: TextStyle(
|
||||
fontFamily: 'Inter',
|
||||
fontSize: 26.rpx,
|
||||
letterSpacing: 0.0,
|
||||
color: themeController
|
||||
.currentColor.sc4,
|
||||
fontSize: AppConstants()
|
||||
.middler_text_fontSize,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
enabledBorder:
|
||||
OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Color(0x00000000),
|
||||
width: 1.rpx,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
8.rpx),
|
||||
),
|
||||
focusedBorder:
|
||||
OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Color(0x00000000),
|
||||
width: 1.rpx,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
8.rpx),
|
||||
),
|
||||
errorBorder:
|
||||
OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.red,
|
||||
width: 1.rpx,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
8.rpx),
|
||||
),
|
||||
focusedErrorBorder:
|
||||
OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.red,
|
||||
width: 1.rpx,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
8.rpx),
|
||||
),
|
||||
filled: false,
|
||||
fillColor: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30.rpx,
|
||||
child: VerticalDivider(
|
||||
thickness: 2.rpx,
|
||||
color: themeController
|
||||
.currentColor.sc4,
|
||||
),
|
||||
),
|
||||
].divide(SizedBox(width: 10.rpx)),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
child: Align(
|
||||
alignment:
|
||||
AlignmentDirectional(-1, 0),
|
||||
child: TextFormField(
|
||||
onChanged: (value) {
|
||||
loginController.model.phone =
|
||||
value;
|
||||
},
|
||||
autofocus: false,
|
||||
obscureText: false,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
labelStyle: TextStyle(
|
||||
fontFamily: 'Inter',
|
||||
fontSize: 26.rpx,
|
||||
letterSpacing: 0.0,
|
||||
),
|
||||
hintText: '其他手机登录页.输入内容'.tr,
|
||||
hintStyle: TextStyle(
|
||||
style: TextStyle(
|
||||
fontFamily: 'Inter',
|
||||
fontSize: 26.rpx,
|
||||
letterSpacing: 0.0,
|
||||
color: themeController
|
||||
.currentColor.sc4,
|
||||
.currentColor.sc3,
|
||||
),
|
||||
enabledBorder:
|
||||
OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Color(0x00000000),
|
||||
width: 1.rpx,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
8.rpx),
|
||||
),
|
||||
focusedBorder:
|
||||
OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Color(0x00000000),
|
||||
width: 1.rpx,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
8.rpx),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.red,
|
||||
width: 1.rpx,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
8.rpx),
|
||||
),
|
||||
focusedErrorBorder:
|
||||
OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.red,
|
||||
width: 1.rpx,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
8.rpx),
|
||||
),
|
||||
filled: false,
|
||||
fillColor: Colors.white,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontFamily: 'Inter',
|
||||
fontSize: 26.rpx,
|
||||
letterSpacing: 0.0,
|
||||
color: themeController
|
||||
cursorColor: themeController
|
||||
.currentColor.sc3,
|
||||
// validator: _model
|
||||
// .textControllerValidator
|
||||
// .asValidator(context),
|
||||
),
|
||||
cursorColor: themeController
|
||||
.currentColor.sc3,
|
||||
// validator: _model
|
||||
// .textControllerValidator
|
||||
// .asValidator(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -629,7 +679,6 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsetsDirectional.fromSTEB(0, 26.rpx, 0, 0),
|
||||
@@ -1071,4 +1120,179 @@ class _OtherLoginPageState extends State<OtherLoginPage> {
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLoginMethodSelector(BoxConstraints bodysize) {
|
||||
final userInfoController = Get.find<UserInfoController>();
|
||||
|
||||
// 文本样式
|
||||
final textStyle = TextStyle(
|
||||
fontSize: 28.rpx,
|
||||
fontWeight: FontWeight.w600,
|
||||
);
|
||||
|
||||
// 两个 tab 之间的间距
|
||||
final double gap = 60.rpx;
|
||||
// 左侧内边距
|
||||
final double leftPadding = 40.rpx;
|
||||
// 下划线和文字的垂直间距
|
||||
final double underlineGap = 20.rpx;
|
||||
// 下划线高度
|
||||
final double underlineHeight = 6.rpx;
|
||||
|
||||
return Align(
|
||||
alignment: AlignmentDirectional(-1, 0),
|
||||
child: Padding(
|
||||
padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: bodysize.maxHeight * 0.056,
|
||||
constraints: const BoxConstraints(minHeight: 90),
|
||||
child: Obx(() {
|
||||
final selectedIndex =
|
||||
userInfoController.select_login_method.value; // 1 or 2
|
||||
|
||||
// --- 计算文字宽高 ---
|
||||
final tp1 = TextPainter(
|
||||
text: TextSpan(text: '手机号登录'.tr, style: textStyle),
|
||||
textDirection: ui.TextDirection.ltr,
|
||||
)..layout();
|
||||
|
||||
final tp2 = TextPainter(
|
||||
text: TextSpan(text: '邮箱登录'.tr, style: textStyle),
|
||||
textDirection: ui.TextDirection.ltr,
|
||||
)..layout();
|
||||
|
||||
final double w1 = tp1.width;
|
||||
final double w2 = tp2.width;
|
||||
final double textHeight = tp1.height;
|
||||
|
||||
// --- 每个 tab 的起始 X ---
|
||||
final double startX1 = leftPadding;
|
||||
final double startX2 = leftPadding + w1 + gap;
|
||||
|
||||
// --- 下划线宽度(和文字等宽)---
|
||||
final double underlineWidth1 = w1;
|
||||
final double underlineWidth2 = w2;
|
||||
|
||||
// --- 下划线 left(始终居中文字)---
|
||||
final double underlineLeft1 = startX1;
|
||||
final double underlineLeft2 = startX2;
|
||||
|
||||
final double underlineLeft =
|
||||
selectedIndex == 1 ? underlineLeft1 : underlineLeft2;
|
||||
final double underlineWidth =
|
||||
selectedIndex == 1 ? underlineWidth1 : underlineWidth2;
|
||||
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
// ===== 文字行 =====
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: 0,
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(width: leftPadding),
|
||||
|
||||
// 手机号登录
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () =>
|
||||
userInfoController.select_login_method.value = 1,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 6.rpx),
|
||||
child: Obx(() {
|
||||
final selected =
|
||||
userInfoController.select_login_method.value ==
|
||||
1;
|
||||
return Text(
|
||||
'手机号登录'.tr,
|
||||
style: textStyle.copyWith(
|
||||
color: selected
|
||||
? themeController.currentColor.sc2
|
||||
: themeController.currentColor.sc4,
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(width: gap),
|
||||
|
||||
// 邮箱登录
|
||||
GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () =>
|
||||
userInfoController.select_login_method.value = 2,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 6.rpx),
|
||||
child: Obx(() {
|
||||
final selected =
|
||||
userInfoController.select_login_method.value ==
|
||||
2;
|
||||
return Text(
|
||||
'邮箱登录'.tr,
|
||||
style: textStyle.copyWith(
|
||||
color: selected
|
||||
? themeController.currentColor.sc2
|
||||
: themeController.currentColor.sc4,
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// ===== 下划线(文字正下方) =====
|
||||
AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 280),
|
||||
curve: Curves.easeOutCubic,
|
||||
left: underlineLeft,
|
||||
top: textHeight + underlineGap,
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 280),
|
||||
curve: Curves.easeOutCubic,
|
||||
width: underlineWidth,
|
||||
height: underlineHeight,
|
||||
decoration: BoxDecoration(
|
||||
color: themeController.currentColor.sc2,
|
||||
borderRadius: BorderRadius.circular(underlineHeight / 2),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLoginTab({
|
||||
required String text,
|
||||
required int index,
|
||||
required UserInfoController controller,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
controller.select_login_method.value = index;
|
||||
},
|
||||
child: Obx(() {
|
||||
final selected = controller.select_login_method.value == index;
|
||||
|
||||
return Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 28.rpx,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: selected
|
||||
? themeController.currentColor.sc2
|
||||
: themeController.currentColor.sc4,
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user