chatapp3-flutter/lib/modules/auth/account/sc_login_with_account_page.dart
2026-04-11 13:52:49 +08:00

397 lines
14 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:yumi/app_localizations.dart';
import 'package:yumi/ui_kit/components/sc_debounce_widget.dart';
import 'package:yumi/ui_kit/components/text/sc_text.dart';
import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart';
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
import 'package:yumi/ui_kit/components/sc_tts.dart';
import 'package:yumi/app/constants/sc_screen.dart';
import 'package:yumi/app/constants/sc_global_config.dart';
import 'package:yumi/app/config/business_logic_strategy.dart';
import 'package:yumi/app/routes/sc_routes.dart';
import 'package:yumi/app/routes/sc_fluro_navigator.dart';
import 'package:yumi/shared/tools/sc_loading_manager.dart';
import 'package:yumi/shared/tools/sc_version_utils.dart';
import 'package:yumi/shared/data_sources/sources/repositories/sc_user_repository_impl.dart';
import 'package:yumi/shared/business_logic/models/res/login_res.dart';
import 'package:provider/provider.dart';
import 'package:yumi/services/audio/rtc_manager.dart';
import 'package:yumi/services/audio/rtm_manager.dart';
///密码账户登录
class SCLoginWithAccountPage extends StatefulWidget {
const SCLoginWithAccountPage({super.key});
@override
SCLoginWithAccountPageState createState() => SCLoginWithAccountPageState();
}
class SCLoginWithAccountPageState extends State<SCLoginWithAccountPage>
with WidgetsBindingObserver {
///显示密码
bool showPass = false;
String account = "";
///账户控制器
TextEditingController accountController = TextEditingController();
///密码控制器
TextEditingController passController = TextEditingController();
@override
void initState() {
super.initState();
String account = DataPersistence.getString(
"Login_Account",
defaultValue: "123456",
);
String pwd = DataPersistence.getString("Login_Pwd", defaultValue: "123456");
if (account.isEmpty) {
account = "123456";
}
if (pwd.isEmpty) {
pwd = "123456";
}
accountController.text = account;
passController.text = pwd;
}
@override
Widget build(BuildContext context) {
final businessLogicStrategy = SCGlobalConfig.businessLogicStrategy;
final pagePadding = businessLogicStrategy.getLoginPagePadding();
return Scaffold(
resizeToAvoidBottomInset: false,
body: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Stack(
alignment: Alignment.topCenter,
children: [
Image.asset(
businessLogicStrategy.getLoginBackgroundImage(),
width: ScreenUtil().screenWidth,
height: ScreenUtil().screenHeight,
fit: BoxFit.cover,
),
SingleChildScrollView(
// 添加滚动视图
padding: EdgeInsets.only(
bottom:
MediaQuery.of(context).viewInsets.bottom + 20, // 添加底部内边距
),
child: Column(
children: [
SizedBox(height: pagePadding.top),
Image.asset(
businessLogicStrategy.getLoginAppIcon(),
width: 107.w,
height: 159.w,
),
SizedBox(height: 35.w),
Container(
margin: EdgeInsetsDirectional.only(start: 65.w),
alignment: AlignmentDirectional.centerStart,
child: text(
SCAppLocalizations.of(context)!.account,
fontSize: 16.sp,
textColor: businessLogicStrategy.getLoginLabelTextColor(),
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 10.w),
_buildAccountInput(businessLogicStrategy),
SizedBox(height: 10.w),
Container(
margin: EdgeInsetsDirectional.only(start: 65.w),
alignment: AlignmentDirectional.centerStart,
child: text(
SCAppLocalizations.of(context)!.password,
fontSize: 16.sp,
textColor: businessLogicStrategy.getLoginLabelTextColor(),
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 10.w),
_buildPassInput(businessLogicStrategy),
SizedBox(height: 80.w),
_buildLoginBtn(businessLogicStrategy),
],
),
),
],
),
),
);
}
///登录按钮
Widget _buildLoginBtn(BusinessLogicStrategy strategy) {
final buttonColor = strategy.getLoginButtonColor();
final buttonGradient = strategy.getLoginButtonGradient();
BoxDecoration buttonDecoration;
if (buttonGradient != null && buttonGradient.isNotEmpty) {
// 使用渐变
buttonDecoration = BoxDecoration(
gradient: LinearGradient(
colors: buttonGradient,
begin: Alignment.centerRight,
end: Alignment.centerLeft,
),
border: Border.all(color: Color(0xff077142), width: 1.w),
borderRadius: BorderRadius.circular(12), // 马甲包设计使用70px圆角
);
} else {
// 使用纯色
buttonDecoration = BoxDecoration(
color: buttonColor,
borderRadius: BorderRadius.all(Radius.circular(height(8))), // 原始应用8px圆角
);
}
return Row(
children: [
Expanded(
child: SCDebounceWidget(
child: Container(
alignment: Alignment.center,
margin: EdgeInsets.symmetric(horizontal: 60.w),
height: 42.w,
decoration: buttonDecoration,
child: text(
SCAppLocalizations.of(context)!.logIn,
textColor: strategy.getLoginButtonTextColor(),
fontSize: 16.sp,
fontWeight: FontWeight.w600,
),
),
onTap: () {
_login();
},
),
),
],
);
}
///账户输入框
Widget _buildAccountInput(BusinessLogicStrategy strategy) {
return Row(
children: <Widget>[
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 60.w),
padding: EdgeInsetsDirectional.only(
start: width(12),
end: width(12),
),
alignment: AlignmentDirectional.centerStart,
height: 45.w,
width: ScreenUtil().screenWidth,
decoration: strategy.getLoginInputDecoration(),
child: TextField(
controller: accountController,
onChanged: (text) {
setState(() {
account = text;
});
},
maxLength: 30,
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp("[0-9]")),
],
decoration: InputDecoration(
isDense: true,
filled: false,
focusColor: Colors.transparent,
hoverColor: Colors.transparent,
hintText: SCAppLocalizations.of(context)!.enterAccount,
hintStyle: TextStyle(
color: strategy.getLoginHintTextColor(),
fontSize: 14.sp,
fontWeight: FontWeight.w600,
),
contentPadding: EdgeInsets.only(top: 0.w),
counterText: '',
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
disabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
focusedErrorBorder: InputBorder.none,
// enabledBorder: UnderlineInputBorder(
// borderSide: BorderSide(width: 0.5,color: Colors.white,style: BorderStyle.solid),),
// focusedBorder: UnderlineInputBorder(
// borderSide: BorderSide(width: 0.5,color: Colors.white,style: BorderStyle.solid),),
// prefixIcon: Padding(padding: EdgeInsets.all(8.w), child: Image.asset("images/login/sc_icon_phone.png",width: 20.w, height: 20.w,fit: BoxFit.fill,),),
suffix: _buildPhoneCancel(),
),
style: TextStyle(
fontSize: 14.sp,
color: strategy.getLoginInputTextColor(),
fontWeight: FontWeight.w600,
textBaseline: TextBaseline.alphabetic,
),
),
),
),
],
);
}
_buildPhoneCancel() {
return Offstage(
offstage: accountController.text == "",
child: GestureDetector(
onTap: () {
setState(() {
accountController.text = '';
});
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Image.asset(
"sc_images/login/sc_icon_sc.png",
width: 15.w,
color: Colors.white,
),
),
),
);
}
///密码输入框
Widget _buildPassInput(BusinessLogicStrategy strategy) {
return Row(
children: <Widget>[
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 60.w),
padding: REdgeInsetsDirectional.only(
start: width(12),
end: width(12),
),
alignment: AlignmentDirectional.centerStart,
height: 45.w,
width: ScreenUtil().screenWidth,
decoration: strategy.getLoginInputDecoration(),
child: TextField(
controller: passController,
maxLength: 30,
maxLines: 1,
inputFormatters: [
FilteringTextInputFormatter.deny("[\u4e00-\u9fa5]"),
],
obscureText: !showPass,
textInputAction: TextInputAction.done,
onChanged: (s) {
setState(() {});
},
decoration: InputDecoration(
isDense: true,
filled: false,
focusColor: Colors.transparent,
hoverColor: Colors.transparent,
hintText: SCAppLocalizations.of(context)!.enterPassword,
hintStyle: TextStyle(
color: strategy.getLoginHintTextColor(),
fontSize: 14.sp,
fontWeight: FontWeight.w600,
),
counterText: '',
contentPadding: EdgeInsets.only(top: 0.w),
border: InputBorder.none,
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
disabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
focusedErrorBorder: InputBorder.none,
// enabledBorder: UnderlineInputBorder(
// borderSide: BorderSide(width: 0.5,color: Colors.white,style: BorderStyle.solid),),
// focusedBorder: UnderlineInputBorder(
// borderSide: BorderSide(width: 0.5,color: Colors.white,style: BorderStyle.solid),),
// prefixIcon: Padding(padding: EdgeInsets.all(8.w), child: Image.asset("images/login/sc_icon_pwd.png",width: 20.w, height: 20.w,fit: BoxFit.fill,),),
suffix: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
setState(() {
showPass = !showPass;
});
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Image.asset(
!showPass
? "sc_images/login/sc_icon_pass.png"
: "sc_images/login/sc_icon_pass1.png",
gaplessPlayback: true,
color: Colors.white,
width: 15.w,
),
),
),
),
style: TextStyle(
fontSize: 14.sp,
color: strategy.getLoginInputTextColor(),
fontWeight: FontWeight.w600,
),
),
),
),
],
);
}
///登录
_login() async {
String account = accountController.text;
String pass = passController.text;
if (account.isEmpty || pass.isEmpty) {
SCTts.show(
SCAppLocalizations.of(context)!.theAccountPasswordCannotBeEmpty,
);
return;
}
SCLoadingManager.show(context: context);
try {
final results = await Future.wait([
SCAccountRepository().loginForAccount(account, pass),
SCVersionUtils.checkReview(),
]);
var user = (results[0] as SocialChatLoginRes);
if (!mounted) {
return;
}
await Provider.of<RtcProvider>(
context,
listen: false,
).resetLocalRoomState(
fallbackRtmProvider: Provider.of<RtmProvider>(context, listen: false),
);
if (!mounted) {
return;
}
AccountStorage().setCurrentUser(user);
SCLoadingManager.hide();
DataPersistence.setString("Login_Account", account);
DataPersistence.setString("Login_Pwd", pass);
if (mounted) {
SCNavigatorUtils.push(context, SCRoutes.home, clearStack: true);
}
} catch (e) {
SCLoadingManager.hide();
// 可以添加错误处理逻辑
rethrow;
}
}
}