diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ac4a906 --- /dev/null +++ b/.gitignore @@ -0,0 +1,72 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..e023651 --- /dev/null +++ b/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 20e59316b8b8474554b38493b8ca888794b0234a + channel: stable + +project_type: app diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 592ceee..e8efba1 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 592ceee..399e934 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..64ba749 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,72 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def parse_KV_file(file, separator='=') + file_abs_path = File.expand_path(file) + if !File.exists? file_abs_path + return []; + end + pods_ary = [] + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) { |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + pods_ary.push({:name => podname, :path => podpath}); + else + puts "Invalid plugin specification: #{line}" + end + } + return pods_ary +end + +target 'Runner' do + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + system('rm -rf .symlinks') + system('mkdir -p .symlinks/plugins') + + # Flutter Pods + generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') + if generated_xcode_build_settings.empty? + puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first." + end + generated_xcode_build_settings.map { |p| + if p[:name] == 'FLUTTER_FRAMEWORK_DIR' + symlink = File.join('.symlinks', 'flutter') + File.symlink(File.dirname(p[:path]), symlink) + pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) + end + } + + # Plugin Pods + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.map { |p| + symlink = File.join('.symlinks', 'plugins', p[:name]) + File.symlink(p[:path], symlink) + pod p[:name], :path => File.join(symlink, 'ios') + } +end + +# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. +install! 'cocoapods', :disable_input_output_paths => true + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['ENABLE_BITCODE'] = 'NO' + end + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..710faf1 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,22 @@ +PODS: + - Flutter (1.0.0) + - fluttertoast (0.0.2): + - Flutter + +DEPENDENCIES: + - Flutter (from `.symlinks/flutter/ios`) + - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: ".symlinks/flutter/ios" + fluttertoast: + :path: ".symlinks/plugins/fluttertoast/ios" + +SPEC CHECKSUMS: + Flutter: 58dd7d1b27887414a370fcccb9e645c08ffd7a6a + fluttertoast: b644586ef3b16f67fae9a1f8754cef6b2d6b634b + +PODFILE CHECKSUM: 7fb83752f59ead6285236625b82473f90b1cb932 + +COCOAPODS: 1.7.5 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index e37a20e..b9aadb2 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + C5699F19450F851984BE4151 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C140679DA081BAB2A51C030 /* libPods-Runner.a */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -39,11 +40,15 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 1A09C3911D41F417161EF6BF /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 28A5CC07B300F8AD51CCF47A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 6C140679DA081BAB2A51C030 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 918026E4C14AA88335D1D2FF /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; @@ -62,6 +67,7 @@ files = ( 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + C5699F19450F851984BE4151 /* libPods-Runner.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -87,7 +93,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, + B0B8CA5EC51FBC139F6947C1 /* Pods */, + FC7A97DAA5AB31C6BA3B2616 /* Frameworks */, ); sourceTree = ""; }; @@ -123,6 +130,25 @@ name = "Supporting Files"; sourceTree = ""; }; + B0B8CA5EC51FBC139F6947C1 /* Pods */ = { + isa = PBXGroup; + children = ( + 1A09C3911D41F417161EF6BF /* Pods-Runner.debug.xcconfig */, + 28A5CC07B300F8AD51CCF47A /* Pods-Runner.release.xcconfig */, + 918026E4C14AA88335D1D2FF /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + FC7A97DAA5AB31C6BA3B2616 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6C140679DA081BAB2A51C030 /* libPods-Runner.a */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -130,12 +156,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 35C6B75A06439A8C269F45AA /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + EA5DF780642D9F608B4C6A34 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -194,6 +222,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 35C6B75A06439A8C269F45AA /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -222,6 +272,21 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + EA5DF780642D9F608B4C6A34 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/lib/auth/index.dart b/lib/auth/index.dart new file mode 100644 index 0000000..38a53fc --- /dev/null +++ b/lib/auth/index.dart @@ -0,0 +1,135 @@ +import 'package:flutter/material.dart'; + +import 'package:apifm/apifm.dart' as Apifm; + +import 'package:loading/loading.dart'; +import 'package:loading/indicator/ball_pulse_indicator.dart'; + +import 'register.dart'; + +void main() => runApp(new IndexPage()); + +class IndexPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Auth Index Page', + color: Colors.white, + home: Scaffold( + backgroundColor: Colors.white, + body: Column( + children: [ + SizedBox(height: 120), + _Logo(), + Expanded( + child: _Image(), + ), + _Foot(), + ], + ), + ), + ); + } +} + +class _Logo extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Container( + width: 750, + height: 80, + child: FlutterLogo(), + ); + } +} + +class _Image extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Container( + width: 750, + child: Center( + child: _ImagePic(), + ), + ); + } +} + +class _ImagePic extends StatefulWidget { + @override + _ImagePicState createState() => new _ImagePicState(); +} + +class _ImagePicState extends State<_ImagePic> { + String picUrl; + + @override + void initState() { + super.initState(); + // 初始化 apifm 插件 + Apifm.init("gooking"); + // 读取系统参数设置 + Apifm.queryConfigValue('AUTH_INDEX_PIC').then((res) { + print(res); + if (res['code'] == 0) { + setState(() { + picUrl = res['data']; + }); + } + }); + } + + @override + Widget build(BuildContext context) { + if (picUrl == null) { + return Center( + child: Loading(indicator: BallPulseIndicator(), size: 100.0), + ); + } else { + return Image.network( + picUrl, + fit: BoxFit.cover, + ); + } + } +} + +class _Foot extends StatelessWidget { + @override + Widget build(BuildContext context) { + return new Container( + width: 750, + height: 200, + child: Column( + children: [ + SizedBox(height: 30), + RaisedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => RegisterPage()), + ); + }, + color: Colors.red, + textColor: Colors.white, + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 60), + child: Text('已有账号, 立即登录', style: TextStyle(fontSize: 16)), + ), + SizedBox(height: 20), + RaisedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => RegisterPage()), + ); + }, + color: Colors.red, + textColor: Colors.white, + padding: EdgeInsets.symmetric(vertical: 10, horizontal: 60), + child: const Text('没有账号, 我要注册', style: TextStyle(fontSize: 16)), + ), + ], + ), + ); + } +} diff --git a/lib/auth/register.dart b/lib/auth/register.dart new file mode 100644 index 0000000..5d4a4b6 --- /dev/null +++ b/lib/auth/register.dart @@ -0,0 +1,249 @@ +import 'package:flutter/material.dart'; +import 'package:apifm/apifm.dart' as Apifm; +import 'package:fluttertoast/fluttertoast.dart'; + +void main() => runApp(RegisterPage()); + +// 这个 widget 作用这个应用的顶层 widget. +//这个 widget 是无状态的,所以我们继承的是 [StatelessWidget]. +//对应的,有状态的 widget 可以继承 [StatefulWidget] +class RegisterPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + // 我们想使用 material 风格的应用,所以这里用 MaterialApp + return MaterialApp( + // 移动设备使用这个 title 来表示我们的应用。具体一点说,在 Android 设备里,我们点击 + // recent 按钮打开最近应用列表的时候,显示的就是这个 title。 + title: 'Welcome to Flutter', + // 应用的“主页” + home: _RegisterPageWidget(), + ); + } +} + +class _RegisterPageWidget extends StatefulWidget { + @override + _RegisterPageWidgetState createState() => _RegisterPageWidgetState(); +} + +class _RegisterPageWidgetState extends State<_RegisterPageWidget> { + //全局 Key 用来获取 Form 表单组件 + GlobalKey loginKey = GlobalKey(); + String mobile; + String imageCode; + String smsCode; + String password; + + var graphValidateCodeMap; + + @override + void initState() { + Apifm.init('gooking'); + changePicCode(); + super.initState(); + } + + void changePicCode() { + setState(() { + graphValidateCodeMap = Apifm.graphValidateCodeUrl(); + }); + } + + void showMessage(String name) { + showDialog( + context: context, + child: new AlertDialog(content: new Text(name), actions: [ + new FlatButton( + onPressed: () { + Navigator.pop(context); + }, + child: new Text('确定')) + ])); + } + + void getSmsCode() async { + loginKey.currentState.save(); + if (mobile == null || mobile.trim().length < 11) { + Fluttertoast.showToast(msg: "请输入手机号码", gravity: ToastGravity.CENTER, fontSize: 14); + return; + } + if (imageCode == null || imageCode.trim().length < 4) { + Fluttertoast.showToast(msg: "请输入图形验证码", gravity: ToastGravity.CENTER, fontSize: 14); + return; + } + var res = await Apifm.smsValidateCode(mobile, graphValidateCodeMap['key'], imageCode); + if (res['code'] == 0) { + Fluttertoast.showToast(msg: "短信发送成功,请注意查收!", gravity: ToastGravity.CENTER, fontSize: 14); + } else { + Fluttertoast.showToast(msg: res['msg'], gravity: ToastGravity.CENTER, fontSize: 14); + changePicCode(); + } + } + + void regist() async { + var loginForm = loginKey.currentState; + //验证 Form表单 + if (!loginForm.validate()) { + Fluttertoast.showToast(msg: "请认真填写表单", gravity: ToastGravity.CENTER, fontSize: 14); + return; + } + loginForm.save(); + if (mobile == null || mobile.trim().length < 11) { + Fluttertoast.showToast(msg: "请输入手机号码", gravity: ToastGravity.CENTER, fontSize: 14); + return; + } + if (imageCode == null || imageCode.trim().length < 4) { + Fluttertoast.showToast(msg: "请输入图形验证码", gravity: ToastGravity.CENTER, fontSize: 14); + return; + } + if (smsCode == null || smsCode.trim().length < 4) { + Fluttertoast.showToast(msg: "请输入短信验证码", gravity: ToastGravity.CENTER, fontSize: 14); + return; + } + if (password == null || password.trim().length < 4) { + Fluttertoast.showToast(msg: "请输入登录密码", gravity: ToastGravity.CENTER, fontSize: 14); + return; + } + var res = await Apifm.register_mobile({ + 'mobile': mobile, + 'pwd': password, + 'code': smsCode + }); + if (res['code'] == 0) { + Fluttertoast.showToast(msg: "注册成功,请登录", gravity: ToastGravity.CENTER, fontSize: 14); + } else { + Fluttertoast.showToast(msg: res['msg'], gravity: ToastGravity.CENTER, fontSize: 14); + changePicCode(); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + title: Text('注册新账号'), + centerTitle: true, + ), + body: Column( + children: [ + Container( + padding: EdgeInsets.all(16), + child: Form( + //设置globalKey,用于后面获取FormState + key: loginKey, + //开启自动校验 + autovalidate: true, + child: Column( + children: [ + TextFormField( + decoration: InputDecoration( + labelText: '输入手机号', + hintText: "用于接收短信验证码", + hintStyle: TextStyle( + color: Colors.grey, + fontSize: 13, + ), + prefixIcon: Icon(Icons.person), + ), + //当 Form 表单调用保存方法 Save时回调的函数。 + onSaved: (value) { + mobile = value; + }, + // 当用户确定已经完成编辑时触发 + onFieldSubmitted: (value) {}, + ), + Row( + children: [ + Expanded( + child: TextFormField( + decoration: InputDecoration( + labelText: '图片验证码', + prefixIcon: Icon(Icons.image), + ), + //当 Form 表单调用保存方法 Save时回调的函数。 + onSaved: (value) { + imageCode = value; + }, + // 当用户确定已经完成编辑时触发 + onFieldSubmitted: (value) {}, + ), + ), + Image.network( + graphValidateCodeMap['imageUrl'], + fit: BoxFit.fitHeight, + ), + ], + ), + Row( + children: [ + Expanded( + child: TextFormField( + decoration: InputDecoration( + labelText: '短信验证码', + prefixIcon: Icon(Icons.security), + ), + //当 Form 表单调用保存方法 Save时回调的函数。 + onSaved: (value) { + smsCode = value; + }, + // 当用户确定已经完成编辑时触发 + onFieldSubmitted: (value) {}, + ), + ), + RaisedButton( + padding: EdgeInsets.all(15), + child: Text( + "获取验证码", + style: TextStyle(fontSize: 12), + ), + textColor: Colors.white, + color: Theme.of(context).primaryColor, + onPressed: getSmsCode, + ), + ], + ), + TextFormField( + decoration: InputDecoration( + labelText: '请输入密码', + hintText: '你的登录密码', + hintStyle: TextStyle( + color: Colors.grey, + fontSize: 13, + ), + prefixIcon: Icon(Icons.lock), + ), + //是否是密码 + obscureText: true, + onSaved: (value) { + password = value; + }, + ) + ], + ), + ), + ), + Container( + padding: EdgeInsets.all(16), + child: Row( + children: [ + Expanded( + child: RaisedButton( + padding: EdgeInsets.all(15), + child: Text( + "立即注册", + style: TextStyle(fontSize: 18), + ), + textColor: Colors.white, + color: Theme.of(context).primaryColor, + onPressed: regist, + ), + ), + ], + ), + ) + ], + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index d769d09..5abde06 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,21 +1,6 @@ import 'package:flutter/material.dart'; import 'start_page.dart'; -void main() => runApp(new StartPage()); +import 'auth/register.dart'; -class MyApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter layout demo', - home: Scaffold( - appBar: AppBar( - title: Text('Flutter layout demo'), - ), - body: Center( - child: Text('Hello World'), - ), - ), - ); - } -} \ No newline at end of file +void main() => runApp(new RegisterPage()); \ No newline at end of file diff --git a/lib/start_page.dart b/lib/start_page.dart index 0f504cf..5427b7a 100644 --- a/lib/start_page.dart +++ b/lib/start_page.dart @@ -1,10 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_swiper/flutter_swiper.dart'; import 'package:apifm/apifm.dart' as Apifm; -import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:loading/loading.dart'; import 'package:loading/indicator/ball_pulse_indicator.dart'; -import 'index.dart'; +import './auth/index.dart'; void main() => runApp(new StartPage()); @@ -70,6 +69,7 @@ class _MyHomePageState extends State { return new Image.network(imagesList[index],fit: BoxFit.cover,); }, itemCount: imagesList.length, + loop: false, pagination: new SwiperPagination(), onTap: (index) { print(index); // 可以根据是否是最后一张图片,来跳转至主界面,一般会在最后一张图片上面设置一个按钮元素,引导用户去点击 diff --git a/pubspec.lock b/pubspec.lock index 8810184..53cc025 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -74,6 +74,13 @@ packages: description: flutter source: sdk version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.3" http: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8ef42e9..1766def 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,6 +26,7 @@ dependencies: flutter_swiper: ^1.1.6 apifm: ^0.0.4 loading: ^1.0.1 + fluttertoast: ^3.1.3 dev_dependencies: flutter_test: sdk: flutter