作者 Karson

新增邮箱/手机/公众号/普通文本四种验证码

新增后台列表选项卡切换支持普通文本框
新增fieldlist支持普通HTML标签
修复datetimepicker不触发fieldlist响应的BUG
优化面包屑获取方式
移除冗余图片和样式
... ... @@ -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'));
... ...
... ... @@ -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
*/
... ...
... ... @@ -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',
],
];
... ...
... ... @@ -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();
... ...
<!--@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
... ...
... ... @@ -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>
... ...
... ... @@ -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",
... ...
.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
... ... @@ -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') {
... ...
... ... @@ -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
... ...
... ... @@ -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;
});
... ...
... ... @@ -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;
... ...
... ... @@ -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
... ...
... ... @@ -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;
});
... ...