Forráskód Böngészése

新增手机验证码登录

Karson 2 éve
szülő
commit
a5fd9067c1

+ 1 - 1
application/admin/view/common/script.html

@@ -1 +1 @@
-<script src="__CDN__/assets/js/require{$Think.config.app_debug?'':'.min'}.js" data-main="__CDN__/assets/js/require-backend{$Think.config.app_debug?'':'.min'}.js?v={$site.version|htmlentities}"></script>
+<script src="__CDN__/assets/js/require.min.js" data-main="__CDN__/assets/js/require-backend{$Think.config.app_debug?'':'.min'}.js?v={$site.version|htmlentities}"></script>

+ 8 - 0
application/api/controller/Ems.php

@@ -30,9 +30,17 @@ class Ems extends Api
     public function send()
     {
         $email = $this->request->post("email");
+        $captcha = $this->request->post("captcha");
         $event = $this->request->post("event");
         $event = $event ? $event : 'register';
 
+        //发送前验证码
+        if (config('fastadmin.user_api_captcha')) {
+            if (!\think\Validate::is($captcha, 'captcha')) {
+                $this->error("验证码不正确");
+            }
+        }
+
         $last = Emslib::get($email, $event);
         if ($last && time() - $last['createtime'] < 60) {
             $this->error(__('发送频繁'));

+ 7 - 0
application/api/controller/Sms.php

@@ -25,9 +25,16 @@ class Sms extends Api
     public function send()
     {
         $mobile = $this->request->post("mobile");
+        $captcha = $this->request->post("captcha");
         $event = $this->request->post("event");
         $event = $event ? $event : 'register';
 
+        //发送前验证码
+        if (config('fastadmin.user_api_captcha')) {
+            if (!\think\Validate::is($captcha, 'captcha')) {
+                $this->error("验证码不正确");
+            }
+        }
         if (!$mobile || !\think\Validate::regex($mobile, "^1\d{10}$")) {
             $this->error(__('手机号不正确'));
         }

+ 4 - 3
application/api/controller/User.php

@@ -105,7 +105,7 @@ class User extends Api
      * @param string $password 密码
      * @param string $email    邮箱
      * @param string $mobile   手机号
-     * @param string $code     验证码
+     * @param string $captcha  验证码
      */
     public function register()
     {
@@ -113,7 +113,8 @@ class User extends Api
         $password = $this->request->post('password');
         $email = $this->request->post('email');
         $mobile = $this->request->post('mobile');
-        $code = $this->request->post('code');
+        $captcha = $this->request->post("captcha", $this->request->post('code'));
+
         if (!$username || !$password) {
             $this->error(__('Invalid parameters'));
         }
@@ -123,7 +124,7 @@ class User extends Api
         if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) {
             $this->error(__('Mobile is incorrect'));
         }
-        $ret = Sms::check($mobile, $code, 'register');
+        $ret = Sms::check($mobile, $captcha, 'register');
         if (!$ret) {
             $this->error(__('Captcha is incorrect'));
         }

+ 5 - 1
application/config.php

@@ -232,6 +232,8 @@ return [
     'captcha'                => [
         // 验证码字符集合
         'codeSet'  => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
+        // 验证码过期时间(s)
+        'expire'   => 600,
         // 验证码字体大小(px)
         'fontSize' => 18,
         // 是否画混淆曲线
@@ -265,7 +267,9 @@ return [
         //是否开启前台会员中心
         'usercenter'            => true,
         //会员注册验证码类型email/mobile/wechat/text/false
-        'user_register_captcha' => 'text',
+        'user_register_captcha' => 'mobile',
+        //是否启用发送前验证码(用于短信和邮件发送)
+        'user_api_captcha'      => true,
         //登录验证码
         'login_captcha'         => true,
         //登录失败超过10次则1天后重试

+ 51 - 3
application/index/controller/User.php

@@ -7,6 +7,7 @@ use app\common\controller\Frontend;
 use app\common\library\Ems;
 use app\common\library\Sms;
 use app\common\model\Attachment;
+use fast\Random;
 use think\Config;
 use think\Cookie;
 use think\Hook;
@@ -19,7 +20,7 @@ use think\Validate;
 class User extends Frontend
 {
     protected $layout = 'default';
-    protected $noNeedLogin = ['login', 'register', 'third'];
+    protected $noNeedLogin = ['login', 'mobilelogin', 'register', 'third'];
     protected $noNeedRight = ['*'];
 
     public function _initialize()
@@ -65,7 +66,7 @@ class User extends Frontend
      */
     public function register()
     {
-        $url = $this->request->request('url', '', 'trim');
+        $url = $this->request->request('url', '', 'trim|xss_clean');
         if ($this->auth->id) {
             $this->success(__('You\'ve logged in, do not login again'), $url ? $url : url('user/index'));
         }
@@ -144,7 +145,7 @@ class User extends Frontend
      */
     public function login()
     {
-        $url = $this->request->request('url', '', 'trim');
+        $url = $this->request->request('url', '', 'trim|xss_clean');
         if ($this->auth->id) {
             $this->success(__('You\'ve logged in, do not login again'), $url ? $url : url('user/index'));
         }
@@ -194,6 +195,53 @@ class User extends Frontend
     }
 
     /**
+     * 手机号验证码登录
+     */
+    public function mobilelogin()
+    {
+        $url = $this->request->request('url', '', 'trim|xss_clean');
+        if ($this->request->isPost()) {
+            $mobile = $this->request->post('mobile');
+            $captcha = $this->request->post('captcha');
+            if (!$mobile || !$captcha) {
+                $this->error(__('Invalid parameters'));
+            }
+            if (!Validate::regex($mobile, "^1\d{10}$")) {
+                $this->error(__('Mobile is incorrect'));
+            }
+            if (!Sms::check($mobile, $captcha, 'mobilelogin')) {
+                $this->error(__('Captcha is incorrect'));
+            }
+            $user = \app\common\model\User::getByMobile($mobile);
+            if ($user) {
+                if ($user->status != 'normal') {
+                    $this->error(__('Account is locked'));
+                }
+                //如果已经有账号则直接登录
+                $ret = $this->auth->direct($user->id);
+            } else {
+                $ret = $this->auth->register($mobile, Random::alnum(), '', $mobile, []);
+            }
+            if ($ret) {
+                Sms::flush($mobile, 'mobilelogin');
+                $data = ['userinfo' => $this->auth->getUserinfo()];
+                $this->success(__('Logged in successful'), $url);
+            } else {
+                $this->error($this->auth->getError());
+            }
+        }
+        //判断来源
+        $referer = $this->request->server('HTTP_REFERER');
+        if (!$url && (strtolower(parse_url($referer, PHP_URL_HOST)) == strtolower($this->request->host()))
+            && !preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) {
+            $url = $referer;
+        }
+        $this->view->assign('url', $url);
+        $this->view->assign('title', __('Login'));
+        return $this->view->fetch();
+    }
+
+    /**
      * 退出登录
      */
     public function logout()

+ 5 - 1
application/index/lang/zh-cn/user.php

@@ -19,8 +19,12 @@ return [
     'Change'                                     => '修改',
     'Click to edit'                              => '点击编辑',
     'Email/Mobile/Username'                      => '邮箱/手机/用户名',
+    'Sign in with account'                       => '使用账号密码登录',
+    'Sign in with mobile phone'                  => '使用手机验证码登录',
     'Sign up successful'                         => '注册成功',
     'Email active successful'                    => '邮箱激活成功',
+    'Please enter your mobile phone number'      => '请输入你的手机号',
+    'Please enter %s numbers'                    => '请输入%s位数字',
     'Username can not be empty'                  => '用户名不能为空',
     'Username must be 3 to 30 characters'        => '用户名必须3-30个字符',
     'Username must be 6 to 30 characters'        => '用户名必须6-30个字符',
@@ -61,7 +65,7 @@ return [
     'Logout successful'                          => '退出成功',
     'User center already closed'                 => '会员中心已经关闭',
     'Don\'t have an account? Sign up'            => '还没有账号?点击注册',
-    'Already have an account? Sign in'            => '已经有账号?点击登录',
+    'Already have an account? Sign in'           => '已经有账号?点击登录',
     'Operation failed'                           => '操作失败',
     'Invalid parameters'                         => '参数不正确',
     'Change password failure'                    => '修改密码失败',

+ 6 - 6
application/index/view/common/captcha.html

@@ -1,19 +1,19 @@
 <!--@formatter:off-->
 {if "[type]" == 'email'}
-    <input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_ems_correct')}, event=[event], email:#email)" />
+    <input type="text" name="captcha" class="form-control" placeholder="{:__('Please enter %s numbers', $Think.config.captcha.length)}" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_ems_correct')}, event=[event], email:#email)" />
     <span class="input-group-btn" style="padding:0;border:none;">
-        <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/ems/send')}" data-type="email" data-event="[event]">发送验证码</a>
+        <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/ems/send')}" data-type="email" data-event="[event]">{:__('Send verification code')}</a>
     </span>
 {elseif "[type]" == 'mobile'/}
-    <input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_sms_correct')}, event=[event], mobile:#mobile)" />
+    <input type="text" name="captcha" class="form-control" placeholder="{:__('Please enter %s numbers', $Think.config.captcha.length)}" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_sms_correct')}, event=[event], mobile:#mobile)" />
     <span class="input-group-btn" style="padding:0;border:none;">
-        <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="[event]">发送验证码</a>
+        <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="[event]">{:__('Send verification code')}</a>
     </span>
 {elseif "[type]" == 'wechat'/}
     {if get_addon_info('wechat')}
         <input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});remote({:addon_url('wechat/captcha/check')}, event=[event])" />
         <span class="input-group-btn" style="padding:0;border:none;">
-            <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:addon_url('wechat/captcha/send')}" data-type="wechat" data-event="[event]">获取验证码</a>
+            <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:addon_url('wechat/captcha/send')}" data-type="wechat" data-event="[event]">{:__('Send verification code')}</a>
         </span>
     {else/}
         请在后台插件管理中安装《微信管理插件》
@@ -24,4 +24,4 @@
         <img src="{:captcha_src()}" width="100" height="32" onclick="this.src = '{:captcha_src()}?r=' + Math.random();"/>
     </span>
 {/if}
-<!--@formatter:on-->
+<!--@formatter:on-->

+ 24 - 1
application/index/view/common/script.html

@@ -1 +1,24 @@
-<script src="__CDN__/assets/js/require{$Think.config.app_debug?'':'.min'}.js" data-main="__CDN__/assets/js/require-frontend{$Think.config.app_debug?'':'.min'}.js?v={$site.version|htmlentities}"></script>
+{if $Think.config.fastadmin.user_api_captcha}
+<script type="text/html" id="captchatpl">
+    <div class="p-4 form-section">
+        <form name="captcha-form" class="form-vertical" action="" method="post">
+            <div class="form-group mb-4">
+                <label class="control-label hidden">{:__('Captcha')}</label>
+                <div class="controls">
+                    <div class="input-group">
+                        <input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length})" />
+                        <span class="input-group-btn" style="padding:0;border:none;">
+                            <img src="{:captcha_src()}" width="107" height="32" onclick="this.src = '{:captcha_src()}?r=' + Math.random();"/>
+                        </span>
+                    </div>
+                    <span class="msg-box n-right" style="left:0;top:33px;text-align: left;" for="captcha"></span>
+                </div>
+            </div>
+            <div class="form-group">
+                <button class="btn btn-primary btn-block" type="submit">{:__('Submit')}</button>
+            </div>
+        </form>
+    </div>
+</script>
+{/if}
+<script src="__CDN__/assets/js/require.min.js" data-main="__CDN__/assets/js/require-frontend{$Think.config.app_debug?'':'.min'}.js?v={$site.version|htmlentities}"></script>

+ 37 - 5
application/index/view/user/login.html

@@ -1,19 +1,40 @@
 <div id="content-container" class="container">
     <div class="user-section login-section">
-        <div class="logon-tab clearfix"><a class="active">{:__('Sign in')}</a> <a href="{:url('user/register')}?url={$url|urlencode|htmlentities}">{:__('Sign up')}</a></div>
+        <div class="logon-tab clearfix"><a class="active">{:__('Sign in')}</a> <a href="{:url('user/register')}?url={$url|xss_clean|urlencode}">{:__('Sign up')}</a></div>
         <div class="login-main">
-            <form name="form" id="login-form" class="form-vertical" method="POST" action="">
+
+            <form name="form" id="login-form" class="form-vertical" method="POST" action="{:url('user/mobilelogin')}">
                 <!--@IndexLoginFormBegin-->
                 <input type="hidden" name="url" value="{$url|htmlentities}"/>
                 {:token()}
-                <div class="form-group">
+                <div class="form-group" data-login="mobile">
+                    <label class="control-label">{:__('Mobile')}</label>
+                    <div class="controls">
+                        <input type="text" id="mobile" name="mobile" data-rule="required;mobile" class="form-control" placeholder="{:__('Please enter your mobile phone number')}">
+                        <p class="help-block"></p>
+                    </div>
+                </div>
+                <div class="form-group" data-login="mobile">
+                    <label class="control-label">{:__('Captcha')}</label>
+                    <div class="controls">
+                        <div class="input-group">
+                            <input type="text" name="captcha" class="form-control" placeholder="{:__('Please enter %s numbers', $Think.config.captcha.length)}" maxlength="{$Think.config.captcha.length}" data-rule="required;length({$Think.config.captcha.length});integer[+]"/>
+                            <span class="input-group-btn" style="padding:0;border:none;">
+                                <a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="mobilelogin">{:__('Send verification code')}</a>
+                            </span>
+                        </div>
+                        <p class="help-block"></p>
+                    </div>
+                </div>
+
+                <div class="form-group hidden" data-login="account">
                     <label class="control-label" for="account">{:__('Account')}</label>
                     <div class="controls">
                         <input class="form-control" id="account" type="text" name="account" value="" data-rule="required" placeholder="{:__('Email/Mobile/Username')}" autocomplete="off">
                         <div class="help-block"></div>
                     </div>
                 </div>
-                <div class="form-group">
+                <div class="form-group hidden" data-login="account">
                     <label class="control-label" for="password">{:__('Password')}</label>
                     <div class="controls">
                         <input class="form-control" id="password" type="password" name="password" data-rule="required;password" placeholder="{:__('Password')}" autocomplete="off">
@@ -31,7 +52,18 @@
                 </div>
                 <div class="form-group">
                     <button type="submit" class="btn btn-primary btn-lg btn-block">{:__('Sign in')}</button>
-                    <a href="{:url('user/register')}?url={$url|urlencode|htmlentities}" class="btn btn-default btn-lg btn-block mt-3 no-border">{:__("Don't have an account? Sign up")}</a>
+                    <div class="row">
+                        <div class="col-xs-6 text-left py-2">
+                            <a href="javascript:" class="btn-switchlogin" data-type="mobile"
+                               data-account-action="{:url('user/login')}"
+                               data-mobile-action="{:url('user/mobilelogin')}"
+                               data-account-text='{:__("Sign in with account")}'
+                               data-mobile-text='{:__("Sign in with mobile phone")}'>{:__("Sign in with account")}</a>
+                        </div>
+                        <div class="col-xs-6 text-right py-2">
+                            <a href="{:url('user/register')}?url={$url|xss_clean|urlencode}">{:__("Don't have an account? Sign up")}</a>
+                        </div>
+                    </div>
                 </div>
                 <!--@IndexLoginFormEnd-->
             </form>

+ 4 - 4
application/index/view/user/register.html

@@ -1,11 +1,11 @@
 <div id="content-container" class="container">
     <div class="user-section login-section">
-        <div class="logon-tab clearfix"><a href="{:url('user/login')}?url={$url|urlencode|htmlentities}">{:__('Sign in')}</a> <a class="active">{:__('Sign up')}</a></div>
+        <div class="logon-tab clearfix"><a href="{:url('user/login')}?url={$url|xss_clean|urlencode}">{:__('Sign in')}</a> <a class="active">{:__('Sign up')}</a></div>
         <div class="login-main">
             <form name="form1" id="register-form" class="form-vertical" method="POST" action="">
                 <!--@IndexRegisterFormBegin-->
                 <input type="hidden" name="invite_user_id" value="0"/>
-                <input type="hidden" name="url" value="{$url|htmlentities}"/>
+                <input type="hidden" name="url" value="{$url|xss_clean}"/>
                 {:token()}
                 <div class="form-group">
                     <label class="control-label required">{:__('Email')}<span class="text-success"></span></label>
@@ -31,7 +31,7 @@
                 <div class="form-group">
                     <label class="control-label">{:__('Mobile')}</label>
                     <div class="controls">
-                        <input type="text" id="mobile" name="mobile" data-rule="required;mobile" class="form-control" placeholder="{:__('Mobile')}">
+                        <input type="text" id="mobile" name="mobile" data-rule="required;mobile" class="form-control" placeholder="{:__('Mobile')}" value="13241111111">
                         <p class="help-block"></p>
                     </div>
                 </div>
@@ -52,7 +52,7 @@
 
                 <div class="form-group">
                     <button type="submit" class="btn btn-primary btn-lg btn-block">{:__('Sign up')}</button>
-                    <a href="{:url('user/login')}?url={$url|urlencode|htmlentities}" class="btn btn-default btn-lg btn-block mt-3 no-border">{:__('Already have an account? Sign in')}</a>
+                    <a href="{:url('user/login')}?url={$url|xss_clean|urlencode}" class="btn btn-default btn-lg btn-block mt-3 no-border">{:__('Already have an account? Sign in')}</a>
                 </div>
                 <!--@IndexRegisterFormEnd-->
             </form>

+ 3 - 3
public/assets/js/backend/auth/rule.js

@@ -173,7 +173,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
                 var iconfunc = function () {
                     Layer.open({
                         type: 1,
-                        area: ['99%', '98%'], //宽高
+                        area: ['80%', '80%'], //宽高
                         content: Template('chooseicontpl', {iconlist: iconlist})
                     });
                 };
@@ -185,8 +185,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
                 });
                 $(document).on('click', ".btn-search-icon", function () {
                     if (iconlist.length == 0) {
-                        $.get(Config.site.cdnurl + "/assets/libs/font-awesome/less/variables.less", function (ret) {
-                            var exp = /fa-var-(.*):/ig;
+                        $.get(Config.site.cdnurl + "/assets/libs/font-awesome/css/font-awesome.css", function (ret) {
+                            var exp = /fa-(.*):before/ig;
                             var result;
                             while ((result = exp.exec(ret)) != null) {
                                 iconlist.push(result[1]);

+ 62 - 28
public/assets/js/frontend.js

@@ -1,34 +1,59 @@
 define(['fast', 'template', 'moment'], function (Fast, Template, Moment) {
     var Frontend = {
-        api: Fast.api,
-        init: function () {
-            var si = {};
+        api: {
             //发送验证码
+            sendcaptcha: function (btn, type, data, callback) {
+                $(btn).addClass("disabled", true).text("发送中...");
+                var si = {};
+                Frontend.api.ajax({url: $(btn).data("url"), data: data}, function (data, ret) {
+                    clearInterval(si[type]);
+                    var seconds = 60;
+                    si[type] = setInterval(function () {
+                        seconds--;
+                        if (seconds <= 0) {
+                            clearInterval(si);
+                            $(btn).removeClass("disabled").text("发送验证码");
+                        } else {
+                            $(btn).addClass("disabled").text(seconds + "秒后可再次发送");
+                        }
+                    }, 1000);
+                    if (typeof callback == 'function') {
+                        callback.call(this, data, ret);
+                    }
+                }, function () {
+                    $(btn).removeClass("disabled").text('发送验证码');
+                });
+            },
+            //准备验证码
+            preparecaptcha: function (btn, type, data) {
+                require(['form'], function (Form) {
+                    Layer.open({
+                        title: '请完成验证',
+                        type: 1,
+                        content: Template("captchatpl", {}),
+                        btnAlign: 'c',
+                        success: function (layero, index) {
+                            var form = $("form", layero);
+                            form.data("validator-options", {
+                                valid: function (ret) {
+                                    data.captcha = $("input[name=captcha]", form).val();
+                                    Frontend.api.sendcaptcha(btn, type, data, function (data, ret) {
+                                        Layer.close(index);
+                                    });
+                                    return true;
+                                }
+                            })
+                            Form.api.bindevent(form);
+                        }
+                    });
+                });
+            }
+        },
+        init: function () {
+            //点击发送验证码
             $(document).on("click", ".btn-captcha", function (e) {
                 var type = $(this).data("type") ? $(this).data("type") : 'mobile';
                 var btn = this;
-                Frontend.api.sendcaptcha = function (btn, type, data, callback) {
-                    $(btn).addClass("disabled", true).text("发送中...");
-
-                    Frontend.api.ajax({url: $(btn).data("url"), data: data}, function (data, ret) {
-                        clearInterval(si[type]);
-                        var seconds = 60;
-                        si[type] = setInterval(function () {
-                            seconds--;
-                            if (seconds <= 0) {
-                                clearInterval(si);
-                                $(btn).removeClass("disabled").text("发送验证码");
-                            } else {
-                                $(btn).addClass("disabled").text(seconds + "秒后可再次发送");
-                            }
-                        }, 1000);
-                        if (typeof callback == 'function') {
-                            callback.call(this, data, ret);
-                        }
-                    }, function () {
-                        $(btn).removeClass("disabled").text('发送验证码');
-                    });
-                };
                 if (['mobile', 'email'].indexOf(type) > -1) {
                     var element = $(this).data("input-id") ? $("#" + $(this).data("input-id")) : $("input[name='" + type + "']", $(this).closest("form"));
                     var text = type === 'email' ? '邮箱' : '手机号码';
@@ -47,9 +72,13 @@ define(['fast', 'template', 'moment'], function (Fast, Template, Moment) {
                     }
                     element.isValid(function (v) {
                         if (v) {
-                            var data = {event: $(btn).data("event")};
+                            var data = {event: $(btn).data("event"), id: $(btn).data("id")};
                             data[type] = element.val();
-                            Frontend.api.sendcaptcha(btn, type, data);
+                            if ($("#captchatpl").length === 0) {
+                                Frontend.api.sendcaptcha(btn, type, data);
+                            } else {
+                                Frontend.api.preparecaptcha(btn, type, data);
+                            }
                         } else {
                             Layer.msg("请确认已经输入了正确的" + text + "!");
                         }
@@ -57,7 +86,12 @@ define(['fast', 'template', 'moment'], function (Fast, Template, Moment) {
                 } else {
                     var data = {event: $(btn).data("event")};
                     Frontend.api.sendcaptcha(btn, type, data, function (data, ret) {
-                        Layer.open({title: false, area: ["400px", "430px"], content: "<img src='" + data.image + "' width='400' height='400' /><div class='text-center panel-title'>扫一扫关注公众号获取验证码</div>", type: 1});
+                        Layer.open({
+                            title: false,
+                            area: [Math.min($(window).width(), 400) + "px", "430px"],
+                            content: "<img src='" + data.image + "' width='400' height='400' /><div class='text-center panel-title'>扫一扫关注公众号获取验证码</div>",
+                            type: 1
+                        });
                     });
                 }
                 return false;

+ 16 - 3
public/assets/js/frontend/user.js

@@ -4,7 +4,8 @@ define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, und
             $.each(errors, function (i, j) {
                 Layer.msg(j);
             });
-        }
+        },
+        ignore: ':hidden'
     };
     var Controller = {
         login: function () {
@@ -26,7 +27,7 @@ define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, und
                 Layer.open({
                     type: 1,
                     title: __('Reset password'),
-                    area: ["450px", "355px"],
+                    area: [Math.min($(window).width(), 450) + "px", "355px"],
                     content: content,
                     success: function (layero) {
                         var rule = $("#resetpwd-form input[name='captcha']").data("rule");
@@ -45,6 +46,18 @@ define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, und
                     }
                 });
             });
+
+            //切换账号手机验证码登录
+            $(document).on("click", ".btn-switchlogin", function () {
+                var form = $(this).closest("form");
+                var current = $(this).data("type");
+                var type = current == 'mobile' ? 'account' : 'mobile';
+                var text = $(this).data(current + "-text");
+                $(this).text(text).data("type", type);
+                $("[data-login]").addClass("hidden");
+                $("[data-login='"+type+"']").removeClass("hidden");
+                form.attr("action", $(this).data(type + "-action"));
+            });
         },
         register: function () {
             //本地验证未通过时提示
@@ -85,7 +98,7 @@ define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, und
                 Layer.open({
                     type: 1,
                     title: "修改",
-                    area: ["400px", "250px"],
+                    area: [Math.min($(window).width(), 400) + "px", "250px"],
                     content: content,
                     success: function (layero) {
                         var form = $("form", layero);