import 'dart:async';
|
import 'dart:convert';
|
import 'dart:ui';
|
|
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/material.dart';
|
import 'package:flutter/services.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx;
|
import 'package:hanju/ui/mine/email_pwd_find.dart';
|
import 'package:hanju/ui/mine/email_register.dart';
|
import 'package:html/dom.dart' as dom;
|
import '../../api/http.dart';
|
import '../../model/user/user_info.dart';
|
import '../../ui/common/browser.dart';
|
import '../../ui/widget/button.dart';
|
import '../../utils/event_bus_util.dart';
|
import '../../utils/pageutils.dart';
|
import '../../utils/push_util.dart';
|
import '../../utils/string_util.dart';
|
import '../../utils/ui_constant.dart';
|
import '../../utils/ui_utils.dart';
|
import '../../utils/user_util.dart';
|
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
|
|
void main() {
|
runApp(MyApp());
|
}
|
|
class MyApp extends StatelessWidget {
|
// This widget is the root of your application.
|
@override
|
Widget build(BuildContext context) {
|
return MaterialApp(
|
title: '登录',
|
theme: ThemeData(primaryColor: Color(0xFFF5F5F5)),
|
home: EmailLoginPage(title: ''),
|
);
|
}
|
}
|
|
class EmailLoginPage extends StatefulWidget {
|
//阿里云一键登录
|
static const messageChannel =
|
BasicMessageChannel('AliyunPhoneNumberAuth', StandardMessageCodec());
|
|
EmailLoginPage({Key? key, required this.title}) : super(key: key);
|
|
// This widget is the home page of your application. It is stateful, meaning
|
// that it has a State object (defined below) that contains fields that affect
|
// how it looks.
|
|
// This class is the configuration for the state. It holds the values (in this
|
// case the title) provided by the parent (in this case the App widget) and
|
// used by the build method of the State. Fields in a Widget subclass are
|
// always marked "final".
|
|
final String title;
|
|
@override
|
_EmailLoginPageState createState() => _EmailLoginPageState();
|
}
|
|
class _EmailLoginPageState extends State<EmailLoginPage>
|
with SingleTickerProviderStateMixin {
|
bool oneKeyLogin = false;
|
bool checked = false;
|
TextEditingController? emailController = TextEditingController();
|
TextEditingController? codeController = TextEditingController();
|
String phone = "";
|
String code = "";
|
Timer? timer;
|
|
//重新发送验证码倒计时
|
int? reSendSMSTimeLeft;
|
|
@override
|
void initState() {
|
super.initState();
|
reSendSMSTimeLeft = -1;
|
//初始化微信登录监听
|
fluwx.weChatResponseEventHandler.distinct((a, b) => a == b).listen((res) {
|
if (res is fluwx.WeChatAuthResponse) {
|
int errCode = res.errCode;
|
if (errCode == 0) {
|
String? code = res.code;
|
//TODO 把微信登录返回的code传给后台,剩下的事就交给后台处理
|
} else if (errCode == -4) {
|
//showToast("用户拒绝授权");
|
} else if (errCode == -2) {
|
// showToast("用户取消授权");
|
}
|
}
|
});
|
}
|
|
bool _aliyunLogin = false;
|
|
void aliyunOneKeyLogin() async {
|
if (_aliyunLogin) {
|
return;
|
}
|
_aliyunLogin = true;
|
Future.delayed(const Duration(milliseconds: 1000), () {
|
_aliyunLogin = false;
|
});
|
|
showLoading(context);
|
|
Map value =
|
await EmailLoginPage.messageChannel.send({"method": "checkEnv"}) as Map;
|
dismissDialog(context);
|
if (value["code"] == 0) {
|
value = await EmailLoginPage.messageChannel.send({"method": "startLogin"})
|
as Map;
|
print("返回内容:${jsonEncode(value)}");
|
if (value["code"] == 0) {
|
Map<String, dynamic>? resultValue =
|
await UserApiUtil.login(context, "", "", value["token"]);
|
|
EmailLoginPage.messageChannel.send({"method": "closeLogin"});
|
|
if (resultValue == null) return;
|
|
if (resultValue["code"] == 0) {
|
UserInfo user = UserInfo.fromJson(resultValue["data"]);
|
_loginSuccess(user);
|
} else {
|
Fluttertoast.showToast(msg: value["msg"]);
|
}
|
} else if (value["code"] == 700000) {
|
//Fluttertoast.showToast(msg: "取消登录了");
|
}
|
} else {
|
Fluttertoast.showToast(msg: value["msg"]);
|
setState(() {
|
oneKeyLogin = false;
|
});
|
}
|
}
|
|
void qqLogin() async {
|
Map value = await UserUtil.loginQQ();
|
}
|
|
void _loginSuccess(UserInfo user) {
|
UserUtil.setUserInfo(user).then((value) {
|
print("登录成功");
|
eventBus.fire(LoginEventBus(true));
|
PushUtil.setAlias(user.id!.toString()).then((value) {
|
Navigator.pop(context);
|
});
|
});
|
}
|
|
@override
|
void dispose() {
|
if (timer != null) {
|
timer!.cancel();
|
}
|
super.dispose();
|
}
|
|
BoxDecoration getItemDecoration(Color bgColor, Color shadowColor) {
|
return BoxDecoration(
|
borderRadius: const BorderRadius.all(Radius.elliptical(10, 10)),
|
color: bgColor,
|
boxShadow: [
|
BoxShadow(
|
color: shadowColor,
|
blurRadius: 2.0,
|
offset: Offset(0.0, 5.0), //阴影y轴偏移量
|
spreadRadius: 1 //阴影扩散程度
|
)
|
]);
|
}
|
|
@override
|
Widget build(BuildContext context) {
|
return Scaffold(
|
resizeToAvoidBottomInset: false,
|
backgroundColor: Colors.white,
|
body: Stack(
|
children: [
|
Column(children: [
|
//登录内容区域
|
Expanded(
|
child: SingleChildScrollView(
|
child: Padding(
|
padding: EdgeInsets.fromLTRB(40, 120, 40, 14),
|
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
Image.asset(
|
"assets/imgs/login/ic_login_logo.png",
|
width: 131,
|
),
|
Container(
|
height: 70,
|
),
|
Container(
|
constraints: BoxConstraints(minHeight: 180),
|
child: getLoginContent()),
|
Row(
|
children: [
|
InkWell(
|
child: const Text(
|
"注册",
|
style: TextStyle(
|
color: ColorConstant.theme),
|
),
|
onTap: () {
|
NavigatorUtil.navigateToNextPage(
|
context,
|
EmailRegisterPage(title: ""),
|
(data) {
|
FocusScope.of(context).requestFocus(FocusNode());
|
});
|
},
|
),
|
Expanded(child: Container()),
|
InkWell(
|
child: const Text("找回密码?",
|
style: TextStyle(
|
color: ColorConstant.theme)),
|
onTap: () {
|
NavigatorUtil.navigateToNextPage(
|
context,
|
EmailFindPwdPage(title: ""),
|
(data) {
|
FocusScope.of(context).requestFocus(FocusNode());
|
});
|
|
},
|
),
|
],
|
)
|
])))),
|
//用户协议与隐私政策
|
Row(children: [
|
Container(
|
width: 25,
|
),
|
RoundCheckBox(
|
value: checked,
|
onChanged: (value) {
|
setState(() {
|
checked = value;
|
});
|
},
|
),
|
Expanded(
|
child: Container(
|
child: HtmlWidget(
|
"<p>登录即表明同意 <a href='${Constant.PROTOCOL_URL}'>用户协议</a> 和 <a href='${Constant.PRIVACY_URL}'>隐私政策</a> </p>",
|
textStyle:
|
const TextStyle(color: Color(0xFF999999)),
|
customStylesBuilder: (element) {
|
// print(element.localName);
|
// if (element.localName == 'a') {
|
// return {'color': 'red'};
|
// }
|
|
return null;
|
}, onTapUrl: (url) {
|
String? title = "";
|
if (url == Constant.PROTOCOL_URL) {
|
title = "用户协议";
|
} else {
|
title = "隐私政策";
|
}
|
|
NavigatorUtil.navigateToNextPage(
|
context,
|
BrowserPage(
|
title: title,
|
url: url,
|
),
|
(data) {});
|
|
return true;
|
}))),
|
])
|
]),
|
//关闭按钮
|
Positioned(
|
top: 30,
|
left: 20,
|
child: InkWell(
|
onTap: () {
|
Navigator.of(context).pop();
|
},
|
child: Icon(
|
Icons.close,
|
size: 30,
|
)))
|
],
|
));
|
}
|
|
Widget getLoginContent() {
|
return Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
Container(
|
alignment: Alignment.centerLeft,
|
padding: EdgeInsets.fromLTRB(20, 0, 5, 0),
|
decoration: BoxDecoration(
|
color: const Color(0xFFF5F5F5),
|
borderRadius: BorderRadius.circular(10)),
|
child: Row(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
Image.asset(
|
"assets/imgs/login/icon_email.png",
|
width: 17,
|
height: 15,
|
),
|
Container(width: 14),
|
Expanded(
|
child: TextField(
|
style: TextStyle(color: Color(0xFF333333), fontSize: 17),
|
onChanged: (value) {
|
setState(() {
|
phone = value;
|
});
|
},
|
textAlign: TextAlign.start,
|
keyboardType: TextInputType.emailAddress,
|
controller: emailController,
|
maxLength: 60,
|
decoration: InputDecoration(
|
counterText: "",
|
hintText: "请输入邮箱",
|
hintStyle:
|
TextStyle(color: Color(0xFFCCCCCC), fontSize: 17),
|
contentPadding: EdgeInsets.only(bottom: 3),
|
border: InputBorder.none,
|
focusedBorder: InputBorder.none,
|
),
|
)),
|
],
|
),
|
),
|
Container(height: 10),
|
Container(
|
alignment: Alignment.centerLeft,
|
padding: const EdgeInsets.fromLTRB(20, 0, 7, 0),
|
decoration: BoxDecoration(
|
color: const Color(0xFFF5F5F5),
|
borderRadius: BorderRadius.circular(10)),
|
child: Row(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
Image.asset(
|
"assets/imgs/login/icon_pwd.png",
|
width: 16.5,
|
),
|
Container(width: 14),
|
Expanded(
|
child: TextField(
|
style:const TextStyle(color: Color(0xFF333333), fontSize: 17),
|
onChanged: (value) {
|
setState(() {
|
phone = value;
|
});
|
},
|
textAlign: TextAlign.start,
|
keyboardType: TextInputType.visiblePassword,
|
controller: codeController,
|
maxLength: 32,
|
decoration: const InputDecoration(
|
counterText: "",
|
hintText: "请输入密码",
|
hintStyle:
|
TextStyle(color: Color(0xFFCCCCCC), fontSize: 17),
|
contentPadding: EdgeInsets.only(bottom: 3),
|
border: InputBorder.none,
|
focusedBorder: InputBorder.none,
|
),
|
)),
|
],
|
),
|
),
|
Container(height: 20),
|
MyFillButton(
|
"登 录",
|
10,
|
height: 45,
|
color: const Color(0xFFFF2B4B),
|
fontSize: 17,
|
enable: StringUtil.isEmail(emailController!.value.text) &&
|
codeController!.value.text.length >= 6,
|
|
onClick: () {
|
if (!(StringUtil.isEmail(emailController!.value.text) &&
|
codeController!.value.text.length >= 6)) {
|
return;
|
}
|
|
if (!checked) {
|
Fluttertoast.showToast(msg: "请同意用户协议与隐私政策");
|
return;
|
}
|
|
UserApiUtil.login(context, emailController!.value.text,
|
codeController!.value.text, "")
|
.then((value) {
|
print("结果: $value");
|
if (value!["code"] == 0) {
|
UserInfo user = UserInfo.fromJson(value["data"]);
|
_loginSuccess(user);
|
} else {
|
Fluttertoast.showToast(msg: value["msg"]);
|
}
|
});
|
},
|
),
|
],
|
);
|
}
|
}
|