diff --git a/application/admin/controller/Addon.php b/application/admin/controller/Addon.php index c9f6ba7..691fa44 100644 --- a/application/admin/controller/Addon.php +++ b/application/admin/controller/Addon.php @@ -46,11 +46,11 @@ class Addon extends Backend /** * 配置 */ - public function config($ids = null) + public function config($name = null) { - $name = $this->request->get("name"); + $name = $name ? $name : $this->request->get("name"); if (!$name) { - $this->error(__('Parameter %s can not be empty', $ids ? 'id' : 'name')); + $this->error(__('Parameter %s can not be empty', 'name')); } if (!preg_match("/^[a-zA-Z0-9]+$/", $name)) { $this->error(__('Addon name incorrect')); diff --git a/application/admin/library/Auth.php b/application/admin/library/Auth.php index ab123a3..73826e4 100644 --- a/application/admin/library/Auth.php +++ b/application/admin/library/Auth.php @@ -345,24 +345,33 @@ class Auth extends \fast\Auth if ($this->breadcrumb || !$path) { return $this->breadcrumb; } - $path_rule_id = 0; - foreach ($this->rules as $rule) { - $path_rule_id = $rule['name'] == $path ? $rule['id'] : $path_rule_id; + $titleArr = []; + $menuArr = []; + $urlArr = explode('/', $path); + foreach ($urlArr as $index => $item) { + $pathArr[implode('/', array_slice($urlArr, 0, $index + 1))] = $index; + } + if (!$this->rules && $this->id) { + $this->getRuleList(); } - if ($path_rule_id) { - $this->breadcrumb = Tree::instance()->init($this->rules)->getParents($path_rule_id, true); - foreach ($this->breadcrumb as $k => &$v) { - $v['url'] = url($v['name']); - $v['title'] = __($v['title']); + foreach ($this->rules as $rule) { + if (isset($pathArr[$rule['name']])) { + $rule['title'] = __($rule['title']); + $rule['url'] = url($rule['name']); + $titleArr[$pathArr[$rule['name']]] = $rule['title']; + $menuArr[$pathArr[$rule['name']]] = $rule; } + } + ksort($menuArr); + $this->breadcrumb = $menuArr; return $this->breadcrumb; } /** * 获取左侧和顶部菜单栏 * - * @param array $params URL对应的badge数据 + * @param array $params URL对应的badge数据 * @param string $fixedPage 默认页 * @return array */ diff --git a/application/config.php b/application/config.php index 64fda49..4b5f83f 100755 --- a/application/config.php +++ b/application/config.php @@ -258,24 +258,26 @@ return [ //FastAdmin配置 'fastadmin' => [ //是否开启前台会员中心 - 'usercenter' => true, + 'usercenter' => true, + //会员注册验证码类型email/mobile/wechat/text/false + 'user_register_captcha' => 'text', //登录验证码 - 'login_captcha' => true, + 'login_captcha' => true, //登录失败超过10次则1天后重试 - 'login_failure_retry' => true, + 'login_failure_retry' => true, //是否同一账号同一时间只能在一个地方登录 - 'login_unique' => false, + 'login_unique' => false, //是否开启IP变动检测 - 'loginip_check' => true, + 'loginip_check' => true, //登录页默认背景图 - 'login_background' => "/assets/img/loginbg.jpg", + 'login_background' => "/assets/img/loginbg.jpg", //是否启用多级菜单导航 - 'multiplenav' => false, + 'multiplenav' => false, //自动检测更新 - 'checkupdate' => false, + 'checkupdate' => false, //版本号 - 'version' => '1.0.0.20191101_beta', + 'version' => '1.0.0.20191212_beta', //API接口地址 - 'api_url' => 'https://api.fastadmin.net', + 'api_url' => 'https://api.fastadmin.net', ], ]; diff --git a/application/index/controller/User.php b/application/index/controller/User.php index 0b77b00..46bc2c6 100644 --- a/application/index/controller/User.php +++ b/application/index/controller/User.php @@ -2,7 +2,9 @@ namespace app\index\controller; +use addons\wechat\model\WechatCaptcha; use app\common\controller\Frontend; +use app\common\library\Ems; use app\common\library\Sms; use think\Config; use think\Cookie; @@ -100,8 +102,6 @@ class User extends Frontend 'username.length' => 'Username must be 3 to 30 characters', 'password.require' => 'Password can not be empty', 'password.length' => 'Password must be 6 to 30 characters', - //'captcha.require' => 'Captcha can not be empty', - //'captcha.captcha' => 'Captcha is incorrect', 'email' => 'Email is incorrect', 'mobile' => 'Mobile is incorrect', ]; @@ -110,11 +110,23 @@ class User extends Frontend 'password' => $password, 'email' => $email, 'mobile' => $mobile, - //'captcha' => $captcha, '__token__' => $token, ]; - $ret = Sms::check($mobile, $captcha, 'register'); - if (!$ret) { + //验证码 + $captchaResult = true; + $captchaType = config("fastadmin.user_register_captcha"); + if ($captchaType) { + if ($captchaType == 'mobile') { + $captchaResult = Sms::check($mobile, $captcha, 'register'); + } elseif ($captchaType == 'email') { + $captchaResult = Ems::check($mobile, $captcha, 'register'); + } elseif ($captchaType == 'wechat') { + $captchaResult = WechatCaptcha::check($captcha, 'register'); + } elseif ($captchaType == 'text') { + $captchaResult = \think\Validate::is($captcha, 'captcha'); + } + } + if (!$captchaResult) { $this->error(__('Captcha is incorrect')); } $validate = new Validate($rule, $msg); @@ -134,6 +146,7 @@ class User extends Frontend && !preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) { $url = $referer; } + $this->view->assign('captchaType', config('fastadmin.user_register_captcha')); $this->view->assign('url', $url); $this->view->assign('title', __('Register')); return $this->view->fetch(); diff --git a/application/index/view/common/captcha.html b/application/index/view/common/captcha.html new file mode 100644 index 0000000..8de71d7 --- /dev/null +++ b/application/index/view/common/captcha.html @@ -0,0 +1,27 @@ +<!--@formatter:off--> +{if "[type]" == 'email'} + <input type="text" name="captcha" class="form-control input-lg" data-rule="required;length(4);integer[+];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 btn-lg" data-url="{:url('api/email/send')}" data-type="email" data-event="[event]">发送验证码</a> + </span> +{elseif "[type]" == 'mobile'/} + <input type="text" name="captcha" class="form-control input-lg" data-rule="required;length(4);integer[+];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 btn-lg" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="[event]">发送验证码</a> + </span> +{elseif "[type]" == 'wechat'/} + {if get_addon_info('wechat')} + <input type="text" name="captcha" class="form-control input-lg" data-rule="required;length(4);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 btn-lg" data-url="{:addon_url('wechat/captcha/send')}" data-type="wechat" data-event="[event]">获取验证码</a> + </span> + {else/} + 请在后台插件管理中安装《<a href="https://www.fastadmin.net/store/wechat.html" target="_blank">微信管理插件</a>》 + {/if} +{elseif "[type]" == 'text' /} + <input type="text" name="captcha" class="form-control input-lg" data-rule="required;length(4)" /> + <span class="input-group-btn" style="padding:0;border:none;"> + <img src="{:captcha_src()}" width="100" height="40" onclick="this.src = '{:captcha_src()}?r=' + Math.random();"/> + </span> +{/if} +<!--@formatter:on--> \ No newline at end of file diff --git a/application/index/view/user/register.html b/application/index/view/user/register.html index 6c145c7..ac8ce6b 100644 --- a/application/index/view/user/register.html +++ b/application/index/view/user/register.html @@ -34,18 +34,18 @@ <p class="help-block"></p> </div> </div> + + {if $captchaType} <div class="form-group"> <label class="control-label">{:__('Captcha')}</label> <div class="controls"> <div class="input-group"> - <input type="text" name="captcha" class="form-control input-lg" data-rule="required;length(4);integer[+];remote({:url('api/validate/check_sms_correct')}, event=register, mobile:#mobile)" /> - <span class="input-group-btn" style="padding:0;border:none;"> - <a href="javascript:;" class="btn btn-info btn-captcha btn-lg" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="register">发送验证码</a> - </span> + {include file="common/captcha" event="register" type="$captchaType" /} </div> <p class="help-block"></p> </div> </div> + {/if} <div class="form-group"> <button type="submit" class="btn btn-primary btn-lg btn-block">{:__('Sign up')}</button> diff --git a/bower.json b/bower.json index 174f802..03875fe 100755 --- a/bower.json +++ b/bower.json @@ -22,7 +22,7 @@ "tableExport.jquery.plugin": "~1.10.3", "jquery-slimscroll": "~1.3.8", "jquery.cookie": "~1.4.1", - "Sortable": "~1.5.0", + "Sortable": "~1.10.0", "nice-validator": "~1.1.1", "art-template": "^3.1.3", "requirejs-plugins": "~1.0.3", diff --git a/public/assets/css/wechat/menu.css b/public/assets/css/wechat/menu.css deleted file mode 100644 index b0636f7..0000000 --- a/public/assets/css/wechat/menu.css +++ /dev/null @@ -1,342 +0,0 @@ -.weixin-menu-setting{ - margin:0; - margin-bottom:10px; - width:100%; -} -.mobile-head-title{ - color: #fff; - text-align: center; - padding-top: 33px; - font-size: 15px; - width: auto; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - word-wrap: normal; - margin: 0 40px 0 70px; -} -.weixin-body { - padding:0; - margin:0; - margin-left:337px; -} -.weixin-content,.no-weixin-content{ - background-color: #f4f5f9; - border: 1px solid #e7e7eb; - padding:15px; -} -.no-weixin-content{ - border:#fff; - background-color: #fff; - vertical-align: middle; - padding-top:200px; - text-align: center; -} -@media (max-width: 720px) { - .weixin-body { - margin-left:0; - margin-top:560px; - } -} -.weixin-menu-title{ - border-bottom: 1px solid #e7e7eb; - font-size: 16px; - padding: 0 20px; - line-height: 55px; - margin-bottom: 20px; -} -.mobile-menu-preview{ - display:block; - float:left; - position:relative; - width: 317px; - height: 550px; - background: transparent url(../../img/wx_mobile_header_bg.png) no-repeat 0 0; - background-position: 0 0; - border: 1px solid #e7e7eb; -} - -.mobile-menu-preview .menu-list { - position: absolute; - height:50px; - bottom: 0; - left: 0; - right: 0; - border-top: 1px solid #e7e7eb; - background: transparent url(../../img/wx_mobile_footer_bg.png) no-repeat 0 0; - background-position: 0 0; - background-repeat: no-repeat; - padding-left: 43px; - margin:0; -} -.menu-list .menu-item,.menu-list .add-item{ - line-height: 50px; - position: relative; - float: left; - text-align: center; - width: 33.33%; - list-style: none; -} -.ui-sortable-placeholder{ - background-color:#fff; -} -.menu-item a,.add-item a{ - display: block; - width: auto; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - word-wrap: normal; - color: #616161; - text-decoration: none; -} -.menu-item.current a.menu-link{ - border: 1px solid #44b549; - line-height: 48px; - background-color: #fff; - color: #44b549; -} -.menu-item .icon-menu-dot{ - background: url(../../img/wx_mobile_index.png) 0 0 no-repeat; - width: 7px; - height: 7px; - vertical-align: middle; - display: inline-block; - margin-right: 2px; - margin-top: -2px; - bottom: 60px; - background-color: #fafafa; - border-top-width: 0; -} -.menu-item .menu-link,.add-item .menu-link{ - border-left-width: 0; - border-left: 1px solid #e7e7eb; - text-align: center; -} - -.sub-menu-item a,.add-sub-item a{ - border: 1px solid #d0d0d0; - position:relative; - padding:0 0.5em; -} -.sub-menu-item.current a{ - border: 1px solid #44b549; - background-color: #fff; - color: #44b549; - z-index: 1; -} -.sub-menu-list li a:hover{ - background:#f1f1f1; -} -.menu-item.current .menu-link{ - border: 1px solid #44b549; - line-height: 48px; - background-color: #fff; - color: #44b549; -} -.sub-menu-box{ - position: absolute; - bottom: 60px; - left: 0; - width: 100%; - background-color: #fff; - border-top: none; -} -.sub-menu-list{ - line-height: 50px; - margin:0;padding:0; -} -.sub-menu-list li{ - line-height: 44px; - margin: -1px -1px 0; - list-style: none; -} -.sub-menu-box .arrow { - position: absolute; - left: 50%; - margin-left: -6px; -} - -.sub-menu-box .arrow-in { - bottom: -5px; - display: inline-block; - width: 0; - height: 0; - border-width: 6px; - border-style: dashed; - border-color: transparent; - border-bottom-width: 0; - border-top-color: #fafafa; - border-top-style: solid; -} -.sub-menu-box .arrow-out { - bottom: -6px; - display: inline-block; - width: 0; - height: 0; - border-width: 6px; - border-style: dashed; - border-color: transparent; - border-bottom-width: 0; - border-top-color: #d0d0d0; - border-top-style: solid; -} -.sub-menu-item.current{ - -} -.sub-menu-inner-add{ - display: block; - border-top: 1px solid #e7e7eb; - width: auto; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - word-wrap: normal; - cursor: pointer; -} -.weixin-icon{ - background: url(../../img/weixin_icon.png) 0 -4418px no-repeat; - width: 16px; - height: 16px; - vertical-align: middle; - display: inline-block; - line-height: 100px; - overflow: hidden; -} -.weixin-icon.add-gray { - background-position: 0 0; -} -.weixin-icon.sort-gray { - background: url(../../img/weixin_icon.png) 0 -32px no-repeat; - background-position: 0 -32px; - margin-top: -1px; - display:none; - width: 20px; -} -.weixin-icon.big-add-gray{ - background-position: -36px 0; - width: 36px; - height: 36px; - vertical-align: middle; -} -.menu-item a.menu-link:hover{ - -} - -.add-item.extra,.add-item.extra{ - float: none; - width: auto; - overflow: hidden; -} - -table.btn-bar{width:100%;} -table.btn-bar td{ text-align: center; } - -.item-info .item-head{ - position:relative; - padding: 0; - border-bottom: 1px solid #e7e7eb; -} -.item-info .item-delete{ - position:absolute; - top:0; - right:0; -} - -table.weixin-form td{ - vertical-align:middle; - height:24px; - line-height: 24px; - padding: 8px 0; -} - -#menu-content{ - background-color: #fff; - padding: 16px 20px; - border: 1px solid #e7e7eb; -} -.menu-content-tips{ - color: #8d8d8d; - padding-bottom: 10px; -} - -.form-item dl{ - position:relative; - margin:10px 0; -} -.form-item dl dt{ - width:90px; - height: 30px; - line-height: 30px; - text-align: right; - position:absolute; - vertical-align: middle; - top:0; - left:0; - bottom:0; - display:block; -} -.form-item dl dd{ - position:relative; - display:block; - margin-left: 90px; - line-height: 30px; -} -.form-item .input-box { - display: inline-block; - position: relative; - height: 30px; - line-height: 30px; - vertical-align: middle; - width: 278px; - font-size: 14px; - padding: 0 10px; - border: 1px solid #e7e7eb; - box-shadow: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - border-radius: 0; - -moz-border-radius: 0; - -webkit-border-radius: 0; - background-color: #fff; -} -.form-item .input-box input{ - width: 100%; - background-color: transparent; - border: 0; - outline: 0; - height:30px; -} - -.clickbox{ - text-align: center; - margin:40px 0; -} -.create-click{ - display: inline-block; - padding-top: 30px; - position: relative; - width:240px; - height: 120px; - border: 2px dotted #d9dadc; - text-align: center; - margin-bottom: 20px; - margin-left: 50px; -} -.create-click a{ - display:block; -} -.create-click a strong{ - display:block; -} - -.keytitle { - position:absolute; - width:100%; - text-align:center; - top:0px; - height:35px; - line-height:35px; - background:#f4f5f9; -} -dl.is-item dd>label {margin-left:5px;} \ No newline at end of file diff --git a/public/assets/img/weixin_icon.png b/public/assets/img/weixin_icon.png deleted file mode 100644 index 75bd668..0000000 Binary files a/public/assets/img/weixin_icon.png and /dev/null differ diff --git a/public/assets/img/wx_mobile_footer_bg.png b/public/assets/img/wx_mobile_footer_bg.png deleted file mode 100644 index 4a89d4b..0000000 Binary files a/public/assets/img/wx_mobile_footer_bg.png and /dev/null differ diff --git a/public/assets/img/wx_mobile_header_bg.png b/public/assets/img/wx_mobile_header_bg.png deleted file mode 100644 index 248cfb7..0000000 Binary files a/public/assets/img/wx_mobile_header_bg.png and /dev/null differ diff --git a/public/assets/img/wx_mobile_index.png b/public/assets/img/wx_mobile_index.png deleted file mode 100644 index db349df..0000000 Binary files a/public/assets/img/wx_mobile_index.png and /dev/null differ diff --git a/public/assets/js/backend.js b/public/assets/js/backend.js index 3432f34..596c2c5 100755 --- a/public/assets/js/backend.js +++ b/public/assets/js/backend.js @@ -140,7 +140,7 @@ define(['fast', 'template', 'moment'], function (Fast, Template, Moment) { $(document).on('click', '.btn-dialog,.dialogit', function (e) { var that = this; var options = $.extend({}, $(that).data() || {}); - var url = Backend.api.replaceids(that, $(that).attr('href')); + var url = Backend.api.replaceids(that, $(that).data("url") || $(that).attr('href')); var title = $(that).attr("title") || $(that).data("title") || $(that).data('original-title'); var button = Backend.api.gettablecolumnbutton(options); if (button && typeof button.callback === 'function') { @@ -152,7 +152,7 @@ define(['fast', 'template', 'moment'], function (Fast, Template, Moment) { Layer.close(index); }); } else { - Backend.api.open(url, title, options); + window[$(that).data("window") || 'self'].Backend.api.open(url, title, options); } return false; }); @@ -160,7 +160,7 @@ define(['fast', 'template', 'moment'], function (Fast, Template, Moment) { $(document).on('click', '.btn-addtabs,.addtabsit', function (e) { var that = this; var options = $.extend({}, $(that).data() || {}); - var url = Backend.api.replaceids(that, $(that).attr('href')); + var url = Backend.api.replaceids(that, $(that).data("url") || $(that).attr('href')); var title = $(that).attr("title") || $(that).data("title") || $(that).data('original-title'); var icon = $(that).attr("icon") || $(that).data("icon"); if (typeof options.confirm !== 'undefined') { diff --git a/public/assets/js/frontend.js b/public/assets/js/frontend.js index a90e189..0aef458 100644 --- a/public/assets/js/frontend.js +++ b/public/assets/js/frontend.js @@ -6,47 +6,60 @@ define(['fast', 'template', 'moment'], function (Fast, Template, Moment) { //发送验证码 $(document).on("click", ".btn-captcha", function (e) { var type = $(this).data("type") ? $(this).data("type") : 'mobile'; - var element = $(this).data("input-id") ? $("#" + $(this).data("input-id")) : $("input[name='" + type + "']", $(this).closest("form")); - var text = type === 'email' ? '邮箱' : '手机号码'; - if (element.val() === "") { - Layer.msg(text + "不能为空!"); - element.focus(); - return false; - } else if (type === 'mobile' && !element.val().match(/^1[3-9]\d{9}$/)) { - Layer.msg("请输入正确的" + text + "!"); - element.focus(); - return false; - } else if (type === 'email' && !element.val().match(/^[\w\+\-]+(\.[\w\+\-]+)*@[a-z\d\-]+(\.[a-z\d\-]+)*\.([a-z]{2,4})$/)) { - Layer.msg("请输入正确的" + text + "!"); - element.focus(); - return false; - } - var that = this; - element.isValid(function (v) { - if (v) { - $(that).addClass("disabled", true).text("发送中..."); - var data = {event: $(that).data("event")}; - data[type] = element.val(); - Frontend.api.ajax({url: $(that).data("url"), data: data}, function () { - clearInterval(si[type]); - var seconds = 60; - si[type] = setInterval(function () { - seconds--; - if (seconds <= 0) { - clearInterval(si); - $(that).removeClass("disabled").text("发送验证码"); - } else { - $(that).addClass("disabled").text(seconds + "秒后可再次发送"); - } - }, 1000); - }, function () { - $(that).removeClass("disabled").text('发送验证码'); - }); - } else { - Layer.msg("请确认已经输入了正确的" + text + "!"); - } - }); + 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' ? '邮箱' : '手机号码'; + if (element.val() === "") { + Layer.msg(text + "不能为空!"); + element.focus(); + return false; + } else if (type === 'mobile' && !element.val().match(/^1[3-9]\d{9}$/)) { + Layer.msg("请输入正确的" + text + "!"); + element.focus(); + return false; + } else if (type === 'email' && !element.val().match(/^[\w\+\-]+(\.[\w\+\-]+)*@[a-z\d\-]+(\.[a-z\d\-]+)*\.([a-z]{2,4})$/)) { + Layer.msg("请输入正确的" + text + "!"); + element.focus(); + return false; + } + element.isValid(function (v) { + if (v) { + var data = {event: $(btn).data("event")}; + data[type] = element.val(); + Frontend.api.sendcaptcha(btn, type, data); + } else { + Layer.msg("请确认已经输入了正确的" + text + "!"); + } + }); + } 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}); + }); + } return false; }); //tooltip和popover diff --git a/public/assets/js/require-backend.min.js b/public/assets/js/require-backend.min.js index 6038c71..056879a 100644 --- a/public/assets/js/require-backend.min.js +++ b/public/assets/js/require-backend.min.js @@ -5766,7 +5766,7 @@ define('backend',['fast', 'template', 'moment'], function (Fast, Template, Momen $(document).on('click', '.btn-dialog,.dialogit', function (e) { var that = this; var options = $.extend({}, $(that).data() || {}); - var url = Backend.api.replaceids(that, $(that).attr('href')); + var url = Backend.api.replaceids(that, $(that).data("url") || $(that).attr('href')); var title = $(that).attr("title") || $(that).data("title") || $(that).data('original-title'); var button = Backend.api.gettablecolumnbutton(options); if (button && typeof button.callback === 'function') { @@ -5778,7 +5778,7 @@ define('backend',['fast', 'template', 'moment'], function (Fast, Template, Momen Layer.close(index); }); } else { - Backend.api.open(url, title, options); + window[$(that).data("window") || 'self'].Backend.api.open(url, title, options); } return false; }); @@ -5786,7 +5786,7 @@ define('backend',['fast', 'template', 'moment'], function (Fast, Template, Momen $(document).on('click', '.btn-addtabs,.addtabsit', function (e) { var that = this; var options = $.extend({}, $(that).data() || {}); - var url = Backend.api.replaceids(that, $(that).attr('href')); + var url = Backend.api.replaceids(that, $(that).data("url") || $(that).attr('href')); var title = $(that).attr("title") || $(that).data("title") || $(that).data('original-title'); var icon = $(that).attr("icon") || $(that).data("icon"); if (typeof options.confirm !== 'undefined') { @@ -8953,7 +8953,7 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef }, dataFilter: function (data) { if (data.code === 1) { - return data.msg ? { "ok": data.msg } : ''; + return data.msg ? {"ok": data.msg} : ''; } else { return data.msg; } @@ -9100,7 +9100,9 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef showClose: true }; $('.datetimepicker', form).parent().css('position', 'relative'); - $('.datetimepicker', form).datetimepicker(options); + $('.datetimepicker', form).datetimepicker(options).on('dp.change', function (e) { + $(this, document).trigger("changed"); + }); }); } }, @@ -9141,7 +9143,7 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef $(this).on('cancel.daterangepicker', function (ev, picker) { $(this).val('').trigger('blur'); }); - $(this).daterangepicker($.extend({}, options, $(this).data()), callback); + $(this).daterangepicker($.extend(true, options, $(this).data()), callback); }); }); } @@ -9203,7 +9205,7 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef var refresh = function (name) { var data = {}; var textarea = $("textarea[name='" + name + "']", form); - var container = textarea.closest("dl"); + var container = $(".fieldlist[data-name='" + name + "']"); var template = container.data("template"); $.each($("input,select,textarea", container).serializeArray(), function (i, j) { var reg = /\[(\w+)\]\[(\w+)\]$/g; @@ -9231,42 +9233,44 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef textarea.val(JSON.stringify(result)); }; //监听文本框改变事件 - $(document).on('change keyup', ".fieldlist input,.fieldlist textarea,.fieldlist select", function () { - refresh($(this).closest("dl").data("name")); + $(document).on('change keyup changed', ".fieldlist input,.fieldlist textarea,.fieldlist select", function () { + refresh($(this).closest(".fieldlist").data("name")); }); //追加控制 $(".fieldlist", form).on("click", ".btn-append,.append", function (e, row) { - var container = $(this).closest("dl"); + var container = $(this).closest(".fieldlist"); + var tagName = container.data("tag") || "dd"; var index = container.data("index"); var name = container.data("name"); var template = container.data("template"); var data = container.data(); index = index ? parseInt(index) : 0; container.data("index", index + 1); - var row = row ? row : {}; + row = row ? row : {}; var vars = {index: index, name: name, data: data, row: row}; var html = template ? Template(template, vars) : Template.render(Form.config.fieldlisttpl, vars); - $(html).insertBefore($(this).closest("dd")); - $(this).trigger("fa.event.appendfieldlist", $(this).closest("dd").prev()); + $(html).insertBefore($(tagName + ":last", container)); + $(this).trigger("fa.event.appendfieldlist", $(this).closest(tagName).prev()); }); //移除控制 - $(".fieldlist", form).on("click", "dd .btn-remove", function () { - var container = $(this).closest("dl"); - $(this).closest("dd").remove(); + $(".fieldlist", form).on("click", ".btn-remove", function () { + var container = $(this).closest(".fieldlist"); + var tagName = container.data("tag") || "dd"; + $(this).closest(tagName).remove(); refresh(container.data("name")); }); - //拖拽排序 - $("dl.fieldlist", form).dragsort({ - itemSelector: 'dd', - dragSelector: ".btn-dragsort", - dragEnd: function () { - refresh($(this).closest("dl").data("name")); - }, - placeHolderTemplate: "<dd></dd>" - }); - //渲染数据 + //渲染数据&拖拽排序 $(".fieldlist", form).each(function () { var container = this; + var tagName = $(this).data("tag") || "dd"; + $(this).dragsort({ + itemSelector: tagName, + dragSelector: ".btn-dragsort", + dragEnd: function () { + refresh($(this).closest(".fieldlist").data("name")); + }, + placeHolderTemplate: $("<" + tagName + "/>") + }); var textarea = $("textarea[name='" + $(this).data("name") + "']", form); if (textarea.val() == '') { return true; @@ -10180,10 +10184,15 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr $(Table.config.disabledbtn, toolbar).toggleClass('disabled', !ids.length); }); // 绑定TAB事件 - $('.panel-heading ul[data-field] li a[data-toggle="tab"]').on('shown.bs.tab', function (e) { - var field = $(this).closest("ul").data("field"); + $('.panel-heading [data-field] a[data-toggle="tab"]').on('shown.bs.tab', function (e) { + var field = $(this).closest("[data-field]").data("field"); var value = $(this).data("value"); - $("select[name='" + field + "'] option[value='" + value + "']", table.closest(".bootstrap-table").find(".commonsearch-table")).prop("selected", true); + var object = $("[name='" + field + "']", table.closest(".bootstrap-table").find(".commonsearch-table")); + if (object.prop('tagName') == "SELECT") { + $("option[value='" + value + "']", object).prop("selected", true); + } else { + object.val(value); + } table.bootstrapTable('refresh', {pageNumber: 1}); return false; }); diff --git a/public/assets/js/require-form.js b/public/assets/js/require-form.js index c054900..7d429e0 100755 --- a/public/assets/js/require-form.js +++ b/public/assets/js/require-form.js @@ -20,7 +20,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U }, dataFilter: function (data) { if (data.code === 1) { - return data.msg ? { "ok": data.msg } : ''; + return data.msg ? {"ok": data.msg} : ''; } else { return data.msg; } @@ -167,7 +167,9 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U showClose: true }; $('.datetimepicker', form).parent().css('position', 'relative'); - $('.datetimepicker', form).datetimepicker(options); + $('.datetimepicker', form).datetimepicker(options).on('dp.change', function (e) { + $(this, document).trigger("changed"); + }); }); } }, @@ -270,7 +272,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U var refresh = function (name) { var data = {}; var textarea = $("textarea[name='" + name + "']", form); - var container = textarea.closest("dl"); + var container = $(".fieldlist[data-name='" + name + "']"); var template = container.data("template"); $.each($("input,select,textarea", container).serializeArray(), function (i, j) { var reg = /\[(\w+)\]\[(\w+)\]$/g; @@ -298,42 +300,44 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U textarea.val(JSON.stringify(result)); }; //监听文本框改变事件 - $(document).on('change keyup', ".fieldlist input,.fieldlist textarea,.fieldlist select", function () { - refresh($(this).closest("dl").data("name")); + $(document).on('change keyup changed', ".fieldlist input,.fieldlist textarea,.fieldlist select", function () { + refresh($(this).closest(".fieldlist").data("name")); }); //追加控制 $(".fieldlist", form).on("click", ".btn-append,.append", function (e, row) { - var container = $(this).closest("dl"); + var container = $(this).closest(".fieldlist"); + var tagName = container.data("tag") || "dd"; var index = container.data("index"); var name = container.data("name"); var template = container.data("template"); var data = container.data(); index = index ? parseInt(index) : 0; container.data("index", index + 1); - var row = row ? row : {}; + row = row ? row : {}; var vars = {index: index, name: name, data: data, row: row}; var html = template ? Template(template, vars) : Template.render(Form.config.fieldlisttpl, vars); - $(html).insertBefore($(this).closest("dd")); - $(this).trigger("fa.event.appendfieldlist", $(this).closest("dd").prev()); + $(html).insertBefore($(tagName + ":last", container)); + $(this).trigger("fa.event.appendfieldlist", $(this).closest(tagName).prev()); }); //移除控制 - $(".fieldlist", form).on("click", "dd .btn-remove", function () { - var container = $(this).closest("dl"); - $(this).closest("dd").remove(); + $(".fieldlist", form).on("click", ".btn-remove", function () { + var container = $(this).closest(".fieldlist"); + var tagName = container.data("tag") || "dd"; + $(this).closest(tagName).remove(); refresh(container.data("name")); }); - //拖拽排序 - $("dl.fieldlist", form).dragsort({ - itemSelector: 'dd', - dragSelector: ".btn-dragsort", - dragEnd: function () { - refresh($(this).closest("dl").data("name")); - }, - placeHolderTemplate: "<dd></dd>" - }); - //渲染数据 + //渲染数据&拖拽排序 $(".fieldlist", form).each(function () { var container = this; + var tagName = $(this).data("tag") || "dd"; + $(this).dragsort({ + itemSelector: tagName, + dragSelector: ".btn-dragsort", + dragEnd: function () { + refresh($(this).closest(".fieldlist").data("name")); + }, + placeHolderTemplate: $("<" + tagName + "/>") + }); var textarea = $("textarea[name='" + $(this).data("name") + "']", form); if (textarea.val() == '') { return true; diff --git a/public/assets/js/require-frontend.min.js b/public/assets/js/require-frontend.min.js index 78171e2..9ac07a6 100644 --- a/public/assets/js/require-frontend.min.js +++ b/public/assets/js/require-frontend.min.js @@ -5625,47 +5625,60 @@ define('frontend',['fast', 'template', 'moment'], function (Fast, Template, Mome //发送验证码 $(document).on("click", ".btn-captcha", function (e) { var type = $(this).data("type") ? $(this).data("type") : 'mobile'; - var element = $(this).data("input-id") ? $("#" + $(this).data("input-id")) : $("input[name='" + type + "']", $(this).closest("form")); - var text = type === 'email' ? '邮箱' : '手机号码'; - if (element.val() === "") { - Layer.msg(text + "不能为空!"); - element.focus(); - return false; - } else if (type === 'mobile' && !element.val().match(/^1[3-9]\d{9}$/)) { - Layer.msg("请输入正确的" + text + "!"); - element.focus(); - return false; - } else if (type === 'email' && !element.val().match(/^[\w\+\-]+(\.[\w\+\-]+)*@[a-z\d\-]+(\.[a-z\d\-]+)*\.([a-z]{2,4})$/)) { - Layer.msg("请输入正确的" + text + "!"); - element.focus(); - return false; - } - var that = this; - element.isValid(function (v) { - if (v) { - $(that).addClass("disabled", true).text("发送中..."); - var data = {event: $(that).data("event")}; - data[type] = element.val(); - Frontend.api.ajax({url: $(that).data("url"), data: data}, function () { - clearInterval(si[type]); - var seconds = 60; - si[type] = setInterval(function () { - seconds--; - if (seconds <= 0) { - clearInterval(si); - $(that).removeClass("disabled").text("发送验证码"); - } else { - $(that).addClass("disabled").text(seconds + "秒后可再次发送"); - } - }, 1000); - }, function () { - $(that).removeClass("disabled").text('发送验证码'); - }); - } else { - Layer.msg("请确认已经输入了正确的" + text + "!"); + 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' ? '邮箱' : '手机号码'; + if (element.val() === "") { + Layer.msg(text + "不能为空!"); + element.focus(); + return false; + } else if (type === 'mobile' && !element.val().match(/^1[3-9]\d{9}$/)) { + Layer.msg("请输入正确的" + text + "!"); + element.focus(); + return false; + } else if (type === 'email' && !element.val().match(/^[\w\+\-]+(\.[\w\+\-]+)*@[a-z\d\-]+(\.[a-z\d\-]+)*\.([a-z]{2,4})$/)) { + Layer.msg("请输入正确的" + text + "!"); + element.focus(); + return false; } - }); - + element.isValid(function (v) { + if (v) { + var data = {event: $(btn).data("event")}; + data[type] = element.val(); + Frontend.api.sendcaptcha(btn, type, data); + } else { + Layer.msg("请确认已经输入了正确的" + text + "!"); + } + }); + } 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}); + }); + } return false; }); //tooltip和popover diff --git a/public/assets/js/require-table.js b/public/assets/js/require-table.js index d7aa506..878c319 100644 --- a/public/assets/js/require-table.js +++ b/public/assets/js/require-table.js @@ -203,10 +203,15 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table $(Table.config.disabledbtn, toolbar).toggleClass('disabled', !ids.length); }); // 绑定TAB事件 - $('.panel-heading ul[data-field] li a[data-toggle="tab"]').on('shown.bs.tab', function (e) { - var field = $(this).closest("ul").data("field"); + $('.panel-heading [data-field] a[data-toggle="tab"]').on('shown.bs.tab', function (e) { + var field = $(this).closest("[data-field]").data("field"); var value = $(this).data("value"); - $("select[name='" + field + "'] option[value='" + value + "']", table.closest(".bootstrap-table").find(".commonsearch-table")).prop("selected", true); + var object = $("[name='" + field + "']", table.closest(".bootstrap-table").find(".commonsearch-table")); + if (object.prop('tagName') == "SELECT") { + $("option[value='" + value + "']", object).prop("selected", true); + } else { + object.val(value); + } table.bootstrapTable('refresh', {pageNumber: 1}); return false; });