登录和注册页面

This commit is contained in:
toly
2021-01-17 13:23:02 +08:00
parent f2125d5e67
commit c87895ad4d
12 changed files with 431 additions and 90 deletions

12
lib/app/api/user_api.dart Normal file
View File

@@ -0,0 +1,12 @@
/// create by 张风捷特烈 on 2021/1/17
/// contact me by email 1981462002@qq.com
/// 说明:
class UserApi{
Future<String> register({String email,String code}){
}
}

View File

@@ -9,6 +9,7 @@ import 'package:flutter_unit/views/pages/gallery/gallery_page.dart';
import 'package:flutter_unit/views/pages/issues_point/issues_detail.dart';
import 'package:flutter_unit/views/pages/issues_point/issues_point_page.dart';
import 'package:flutter_unit/views/pages/login/login_page.dart';
import 'package:flutter_unit/views/pages/register/register_page.dart';
import 'package:flutter_unit/views/pages/search/serach_page.dart';
import 'package:flutter_unit/views/pages/setting/code_style_setting.dart';
import 'package:flutter_unit/views/pages/setting/font_setting.dart';
@@ -24,7 +25,6 @@ import 'package:flutter_unit/views/pages/setting/setting_page.dart';
import 'router_utils.dart';
class UnitRouter {
static const String widget_detail = '/widget_detail';
static const String detail = 'detail';
@@ -52,6 +52,7 @@ class UnitRouter {
static const String layout = 'LayoutUnitPage';
static const String about_me = 'AboutMePage';
static const String about_app = 'AboutAppPage';
static const String register = 'register';
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
@@ -83,11 +84,17 @@ class UnitRouter {
case version_info:
return Right2LeftRouter(child: VersionInfo());
case version_info:
return Right2LeftRouter(child: VersionInfo());
case issues_point:
return Right2LeftRouter(child: IssuesPointPage());
case login:
return Right2LeftRouter(child: LoginPage());
case register:
return Right2LeftRouter(child: RegisterPage());
case attr:
return Right2LeftRouter(child: AttrUnitPage());
case bug:

View File

@@ -0,0 +1,19 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'event.dart';
import 'state.dart';
/// create by 张风捷特烈 on 2021/1/17
/// contact me by email 1981462002@qq.com
/// 说明:
class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
RegisterBloc() : super(RegisterLoading());
@override
Stream<RegisterState> mapEventToState(RegisterEvent event) async* {
if (event is DoRegister) {
yield RegisterLoading();
}
}
}

View File

@@ -0,0 +1,24 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_unit/model/enums.dart';
import 'package:flutter_unit/storage/po/widget_po.dart';
import 'package:flutter_unit/model/widget_model.dart';
/// create by 张风捷特烈 on 2020-03-03
/// contact me by email 1981462002@qq.com
/// 说明:
abstract class RegisterEvent extends Equatable {
const RegisterEvent();
@override
List<Object> get props => [];
}
// 发送 邮箱验证
class DoRegister extends RegisterEvent {
final String email;
final String code;
DoRegister(this.email, this.code);
}

View File

@@ -0,0 +1,44 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_unit/model/enums.dart';
import 'package:flutter_unit/app/res/cons.dart';
import 'package:flutter_unit/model/widget_model.dart';
/// create by 张风捷特烈 on 2020-03-03
/// contact me by email 1981462002@qq.com
/// 说明: 主页 Widget 列表 状态类
abstract class RegisterState extends Equatable {
const RegisterState();
@override
List<Object> get props => [];
}
class RegisterLoading extends RegisterState {
@override
List<Object> get props => [];
}
class RegisterError extends RegisterState {
final String message;
const RegisterError(this.message);
@override
List<Object> get props => [message];
@override
String toString() {
return 'RegisterError{message: $message}';
}
}
class RegisterSuccess extends RegisterState {
final String username;
const RegisterSuccess(this.username);
@override
List<Object> get props => [username];
}

View File

@@ -0,0 +1,47 @@
import 'package:flutter/material.dart';
/// create by 张风捷特烈 on 2021/1/17
/// contact me by email 1981462002@qq.com
/// 说明:
class IconInput extends StatelessWidget {
final Widget textFiled;
final IconData icon;
IconInput({Key key,this.textFiled,this.icon}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.withOpacity(0.5),
width: 1.0,
),
borderRadius: BorderRadius.circular(10.0),
),
margin: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0),
child: Row(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
child: Icon(
icon,
color: Colors.grey,
),
),
Container(
height: 20.0,
width: 1.0,
color: Colors.grey.withOpacity(0.5),
margin: const EdgeInsets.only(left: 00.0, right: 10.0),
),
Expanded(
child: textFiled,
)
],
),
);
}
}

View File

@@ -1,26 +0,0 @@
import 'package:flutter/material.dart';
/// create by 张风捷特烈 on 2020/4/27
/// contact me by email 1981462002@qq.com
/// 说明:
class ArcClipper extends CustomClipper<Path> {
final double factor;
ArcClipper({this.factor = 0.618});
@override
Path getClip(Size size) => Path()
..moveTo(0, 0)
..relativeLineTo(size.width, 0)
..relativeLineTo(0, 0.8 * size.height)
..arcToPoint(
Offset(0.0, size.height * 0.618),
radius: const Radius.elliptical(50.0, 10.0),
rotation: 0.0,
)
..close();
@override
bool shouldReclip(ArcClipper oldClipper) => factor != oldClipper.factor;
}

View File

@@ -2,6 +2,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_unit/app/res/toly_icon.dart';
import 'package:flutter_unit/app/router/unit_router.dart';
import 'package:flutter_unit/views/components/permanent/feedback_widget.dart';
@@ -24,7 +25,7 @@ class _LoginFromState extends State<LoginFrom> {
children: <Widget>[
Text("FlutterUnit 登录",style: TextStyle(fontSize: 25),),
SizedBox(height: 5,),
Text("请使用github用户名登录",style: TextStyle(color: Colors.grey),),
Text("更多精彩,更多体验 ~",style: TextStyle(color: Colors.grey),),
SizedBox(height:20,),
buildUsernameInput(),
Stack(
@@ -45,17 +46,23 @@ class _LoginFromState extends State<LoginFrom> {
style: TextStyle(color: Color(0xff444444), fontSize: 14),
),
Spacer(),
Text(
"如何注册?",
style: TextStyle(
color: Colors.blue,
fontSize: 14,
decoration: TextDecoration.underline),
FeedbackWidget(
onEnd: (){
Navigator.of(context).pushNamed(UnitRouter.register);
},
child: Text(
"用户注册",
style: TextStyle(
color: Colors.blue,
fontSize: 14,
decoration: TextDecoration.underline),
),
)
],
),
_buildBtn(),
buildOtherLogin()
buildOtherLogin(),
const Spacer(flex: 4),
],
);
}
@@ -82,7 +89,7 @@ class _LoginFromState extends State<LoginFrom> {
borderRadius: BorderRadius.all(Radius.circular(20))),
color: Colors.blue,
onPressed: _doLogIn,
child: Text("登 录",
child: Text("进入 Unit 世界",
style: TextStyle(color: Colors.white, fontSize: 18)),
),
);

View File

@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_unit/app/res/toly_icon.dart';
import 'package:flutter_unit/views/pages/register/arc_clipper.dart';
import 'arc_clipper.dart';
import 'login_form.dart';
/// create by 张风捷特烈 on 2020/4/24
@@ -11,6 +10,8 @@ import 'login_form.dart';
class LoginPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
Size winSize = MediaQuery.of(context).size;
return
// BlocListener<AuthenticBloc, AuthenticState>(
@@ -21,11 +22,13 @@ class LoginPage extends StatelessWidget {
// },
// child:
Scaffold(
body: SingleChildScrollView(
child: Wrap(children: [
arcBackground(),
Scaffold(
body: SingleChildScrollView(
child: Wrap(children: [
UnitArcBackground(height: winSize.height * 0.32),
Container(
// color: Colors.green,
height: winSize.height * 0.68,
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.only(left: 20.0, right: 20, top: 20),
child:
@@ -34,10 +37,10 @@ class LoginPage extends StatelessWidget {
// builder: (_, state) {
// return
Stack(
alignment: Alignment.center,
children: [
LoginFrom(),
Stack(
alignment: Alignment.center,
children: [
LoginFrom(),
// if (state is LoginFailure)
// Positioned(
// bottom: 0,
@@ -48,56 +51,17 @@ class LoginPage extends StatelessWidget {
// LoadingView(
// text: "登录中...",
// )
],
)
],
)
// );
// },
// ),
// )
// ]
)]
)
]
// ),
),
));
}
Widget arcBackground() {
return ArcBackground(
image: AssetImage("assets/images/caver.webp"),
child: Padding(
padding: const EdgeInsets.all(50.0),
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.blue.withAlpha(88), shape: BoxShape.circle),
child: Icon(TolyIcon.icon_github,size: 100,)
),
),
);
}
}
class ArcBackground extends StatelessWidget {
final Widget child;
final ImageProvider image;
ArcBackground({this.child, this.image});
@override
Widget build(BuildContext context) {
return ClipPath(
clipper: ArcClipper(),
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: image,
fit: BoxFit.cover,
),
),
alignment: Alignment.center,
child: child,
),
);
));
}
}

View File

@@ -0,0 +1,77 @@
import 'package:flutter/material.dart';
import 'package:flutter_unit/views/components/permanent/circle_image.dart';
/// create by 张风捷特烈 on 2020/4/27
/// contact me by email 1981462002@qq.com
/// 说明:
class ArcClipper extends CustomClipper<Path> {
final double factor;
ArcClipper({this.factor = 0.618});
@override
Path getClip(Size size) => Path()
..moveTo(0, 0)
..relativeLineTo(size.width, 0)
..relativeLineTo(0, 0.8 * size.height)
..arcToPoint(
Offset(0.0, size.height * 0.618),
radius: const Radius.elliptical(50.0, 10.0),
rotation: 0.0,
)
..close();
@override
bool shouldReclip(ArcClipper oldClipper) => factor != oldClipper.factor;
}
class ArcBackground extends StatelessWidget {
final Widget child;
final ImageProvider image;
ArcBackground({this.child, this.image});
@override
Widget build(BuildContext context) {
return ClipPath(
clipper: ArcClipper(),
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: image,
fit: BoxFit.cover,
),
),
alignment: Alignment.center,
child: child,
),
);
}
}
class UnitArcBackground extends StatelessWidget {
final double height;
UnitArcBackground({Key key,this.height}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
height: height,
child: ArcBackground(
image: AssetImage("assets/images/caver.webp"),
child: Container(
padding: const EdgeInsets.all(30),
decoration: BoxDecoration(
color: Colors.blue.withAlpha(88), shape: BoxShape.circle),
child: CircleImage(
size: 100,
roundColor: Colors.blue,
image: AssetImage(
'assets/images/sabar.webp',
)),
),
),
);
}
}

View File

@@ -0,0 +1,116 @@
import 'package:flutter/material.dart';
import 'package:flutter_unit/views/components/permanent/icon_input.dart';
import 'arc_clipper.dart';
import 'send_code.dart';
/// create by 张风捷特烈 on 2020/4/24
/// contact me by email 1981462002@qq.com
/// 说明:
class RegisterPage extends StatefulWidget {
@override
_RegisterPageState createState() => _RegisterPageState();
}
class _RegisterPageState extends State<RegisterPage> {
final _usernameController = TextEditingController(text: '1981462002@qq.com');
final _passwordController = TextEditingController(text: '');
@override
Widget build(BuildContext context) {
Size winSize = MediaQuery.of(context).size;
return Scaffold(
body: SingleChildScrollView(
child: Wrap(children: [
UnitArcBackground(height: winSize.height * 0.32),
Container(
width: winSize.width,
height: winSize.height * 0.68,
padding: const EdgeInsets.only(left: 20.0, right: 20, top: 20),
child: Container(
// color: Colors.green,
child: Column(
children: <Widget>[
const Text(
"FlutterUnit 注册",
style: TextStyle(fontSize: 25),
),
const SizedBox(
height: 5,
),
const Text(
"更多精彩,更多体验 ~",
style: TextStyle(color: Colors.grey),
),
const Spacer(
flex: 1,
),
IconInput(
icon: Icons.person_outline,
textFiled: TextField(
controller: _usernameController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: '请输入邮箱',
hintStyle: TextStyle(color: Colors.grey),
),
),
),
const SizedBox(height: 10),
buildInputWithSend(),
const Spacer(flex: 1),
_buildBtn(),
const Spacer(flex: 4),
],
),
))
]),
));
}
Stack buildInputWithSend() {
return Stack(
alignment: Alignment(.8, 0),
children: [
IconInput(
icon: Icons.code_outlined,
textFiled: TextField(
controller: _passwordController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: '请输入验证码',
hintStyle: TextStyle(color: Colors.grey),
),
),
),
CountDownWidget(
onPress: () {
},
)
],
);
}
Widget _buildBtn() => Container(
margin: EdgeInsets.only(top: 10, left: 10, right: 10, bottom: 0),
height: 40,
width: MediaQuery.of(context).size.width,
child: RaisedButton(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20))),
color: Colors.blue,
onPressed: _doRegister,
child: Text("开启 Unit 新世界",
style: TextStyle(color: Colors.white, fontSize: 18)),
),
);
void _doRegister() {}
}

View File

@@ -0,0 +1,50 @@
import 'dart:async';
import 'package:flutter/material.dart';
/// create by 张风捷特烈 on 2021/1/17
/// contact me by email 1981462002@qq.com
/// 说明:
class CountDownWidget extends StatefulWidget {
final VoidCallback onPress;
CountDownWidget({Key key, this.onPress}) : super(key: key);
@override
_CountDownWidgetState createState() => _CountDownWidgetState();
}
class _CountDownWidgetState extends State<CountDownWidget> {
Timer timer;
int count = 60;
bool startTimer = false;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: startTimer?null:() {
timer = Timer.periodic(Duration(seconds: 1), _update);
setState(() {
startTimer = true;
});
},
child: Text(startTimer?'$count 秒后重试':'获取验证码'));
}
void _update(Timer timer) {
count--;
if (count == 0) {
timer.cancel();
startTimer = false;
count=5;
}
setState(() {});
}
}