新增searchList使用Ajax进行渲染

新增独立的管理员日志管理
新增Ajax-Bootstrap-Select插件
新增Shortcut快捷操作列表栏
修复语言包标识为数字时的BUG
移除管理员列表中的密码字段
完善表格完整示例
修复tagsinput选中后显示为数字的BUG
pull/323483/MERGE
Karson 2017-06-09 21:53:48 +08:00
parent 84c394aad2
commit 40667995b1
40 changed files with 650 additions and 192 deletions

View File

@ -1,4 +1,4 @@
<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
{%addList%}
<div class="form-group hide layer-footer">

View File

@ -1,4 +1,4 @@
<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
{%editList%}
<div class="form-group hide layer-footer">

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,5 @@
<?php
use app\admin\library\Auth;
use app\common\model\Category;
use app\common\model\Configvalue;
use fast\Form;
@ -99,32 +98,30 @@ function build_category_select($name, $type, $selected = null, $attr = [])
/**
* 生成表格操作按钮栏
* @param array $btns
* @param array $btns 按钮组
* @param array $attr 按钮属性值
* @return string
*/
function build_toolbar($btns = NULL)
function build_toolbar($btns = NULL, $attr = [])
{
$btns = $btns ? $btns : ['refresh', 'add', 'edit', 'delete'];
$btns = is_array($btns) ? $btns : explode(',', $btns);
$addbtn = __('Add');
$editbtn = __('Edit');
$deletebtn = __('Delete');
$btnAttr = [
'refresh' => ['javascript:;', 'btn btn-primary btn-refresh', 'fa fa-refresh', ''],
'add' => ['javascript:;', 'btn btn-success btn-add', 'fa fa-plus', __('Add')],
'edit' => ['javascript:;', 'btn btn-success btn-edit btn-disabled disabled', 'fa fa-pencil', __('Edit')],
'delete' => ['javascript:;', 'btn btn-danger btn-del btn-disabled disabled', 'fa fa-trash', __('Delete')],
];
$btnAttr = array_merge($btnAttr, $attr);
$html = [];
if (in_array('refresh', $btns))
foreach ($btns as $k => $v)
{
$html[] = '<a class="btn btn-primary btn-refresh" ><i class="fa fa-refresh"></i></a>';
if (!isset($btnAttr[$v]))
{
continue;
}
if (in_array('add', $btns))
{
$html[] = '<a class="btn btn-success btn-add" ><i class="fa fa-plus"></i> ' . $addbtn . '</a>';
}
if (in_array('edit', $btns))
{
$html[] = '<a class="btn btn-success btn-edit btn-disabled disabled" ><i class="fa fa-pencil"></i> ' . $editbtn . '</a>';
}
if (in_array('delete', $btns))
{
$html[] = '<a class="btn btn-danger btn-del btn-disabled disabled" ><i class="fa fa-trash"></i> ' . $deletebtn . '</a>';
list($href, $class, $icon, $text) = $btnAttr[$v];
$html[] = '<a href="' . $href . '" class="' . $class . '" ><i class="' . $icon . '"></i> ' . $text . '</a>';
}
return implode(' ', $html);
}

View File

@ -37,7 +37,8 @@ class Ajax extends Backend
return;
}
$searchfield = 'name';
$field = substr($field, 0, -3);
$fieldArr = explode('_', $field);
$field = $fieldArr[0];
switch ($field)
{
case 'category':
@ -56,11 +57,6 @@ class Ajax extends Backend
->field("id,{$searchfield} AS name")
->select();
foreach ($searchlist as $k => &$v)
{
$v['name'] = $v['name'] . "[id:{$v['id']}]";
}
unset($v);
$this->code = 1;
$this->data = ['searchlist' => $searchlist];
}

View File

@ -76,7 +76,7 @@ class Index extends Backend
$result = $this->auth->login($username, $password, $keeplogin ? 86400 : 0);
if ($result === true)
{
$this->success(__('Login successful'), $url, ['url' => $url]);
$this->success(__('Login successful'), $url, ['url' => $url, 'id' => $this->auth->id, 'username' => $username, 'avatar' => $this->auth->avatar]);
return;
}
else

View File

@ -66,6 +66,7 @@ class Admin extends Backend
$list = $this->model
->where($where)
->where('id', 'in', $childrenAdminIds)
->field(['password', 'salt', 'token'], true)
->order($sort, $order)
->limit($offset, $limit)
->select();

View File

@ -0,0 +1,148 @@
<?php
namespace app\admin\controller\auth;
use app\common\controller\Backend;
use fast\Tree;
/**
* 管理员日志
*
* @icon fa fa-users
* @remark 管理员可以查看自己所拥有的权限的管理员日志
*/
class Adminlog extends Backend
{
protected $model = null;
//当前登录管理员所有子节点组别
protected $childrenIds = [];
public function _initialize()
{
parent::_initialize();
$this->model = model('AdminLog');
$groups = $this->auth->getGroups();
// 取出所有分组
$grouplist = model('AuthGroup')->all(['status' => 'normal']);
$objlist = [];
foreach ($groups as $K => $v)
{
// 取出包含自己的所有子节点
$childrenlist = Tree::instance()->init($grouplist)->getChildren($v['id'], TRUE);
$obj = Tree::instance()->init($childrenlist)->getTreeArray($v['pid']);
$objlist = array_merge($objlist, Tree::instance()->getTreeList($obj));
}
$groupdata = [];
foreach ($objlist as $k => $v)
{
$groupdata[$v['id']] = $v['name'];
}
$this->childrenIds = array_keys($groupdata);
$this->view->assign('groupdata', $groupdata);
}
/**
* 查看
*/
public function index()
{
if ($this->request->isAjax())
{
$childrenAdminIds = model('AuthGroupAccess')
->field('uid')
->where('group_id', 'in', $this->childrenIds)
->column('uid');
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->where($where)
->where('admin_id', 'in', $childrenAdminIds)
->order($sort, $order)
->count();
$list = $this->model
->where($where)
->where('admin_id', 'in', $childrenAdminIds)
->order($sort, $order)
->limit($offset, $limit)
->select();
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
}
/**
* 详情
*/
public function detail($ids)
{
$row = $this->model->get(['id' => $ids]);
if (!$row)
$this->error(__('No Results were found'));
$this->view->assign("row", $row->toArray());
return $this->view->fetch();
}
/**
* 添加
* @internal
*/
public function add()
{
$this->code = -1;
}
/**
* 编辑
* @internal
*/
public function edit($ids = NULL)
{
$this->code = -1;
}
/**
* 删除
*/
public function del($ids = "")
{
$this->code = -1;
if ($ids)
{
$childrenGroupIds = $this->childrenIds;
$adminList = $this->model->where('id', 'in', $ids)->where('admin_id', 'in', function($query) use($childrenGroupIds) {
$query->name('auth_group_access')->field('uid');
})->select();
if ($adminList)
{
$deleteIds = [];
foreach ($adminList as $k => $v)
{
$deleteIds[] = $v->id;
}
if ($deleteIds)
{
$this->model->destroy($deleteIds);
$this->code = 1;
}
}
}
return;
}
/**
* 批量更新
* @internal
*/
public function multi($ids = "")
{
// 管理员禁止批量操作
$this->code = -1;
}
}

View File

@ -221,6 +221,10 @@ class Auth extends \fast\Auth
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']);
}
}
return $this->breadcrumb;
}

View File

@ -20,13 +20,13 @@
<div class="form-group">
<label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="nickname" name="row[nickname]" value="" data-rule="required" />
<input type="text" class="form-control" id="nickname" name="row[nickname]" value="" data-rule="required;username" />
</div>
</div>
<div class="form-group">
<label for="password" class="control-label col-xs-12 col-sm-2">{:__('Password')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="password" class="form-control" id="password" name="row[password]" value="" data-rule="required" />
<input type="password" class="form-control" id="password" name="row[password]" value="" data-rule="required;password" />
</div>
</div>
<div class="form-group">

View File

@ -26,7 +26,7 @@
<div class="form-group">
<label for="password" class="control-label col-xs-12 col-sm-2">{:__('Password')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="password" class="form-control" id="password" name="row[password]" value="" />
<input type="password" class="form-control" id="password" name="row[password]" value="" data-rule="password" />
</div>
</div>
<div class="form-group">

View File

@ -0,0 +1,22 @@
<table class="table table-striped">
<thead>
<tr>
<th>标题</th>
<th>内容</th>
</tr>
</thead>
<tbody>
{volist name="row" id="vo" }
<tr>
<td>{$key}</td>
<td>{$vo}</td>
</tr>
{/volist}
</tbody>
</table>
<div class="hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="reset" class="btn btn-primary btn-embossed btn-close" onclick="Layer.closeAll();">{:__('Close')}</button>
</div>
</div>

View File

@ -0,0 +1,21 @@
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh,delete')}
</div>
<table id="table" class="table table-striped table-bordered table-hover" width="100%">
</table>
</div>
</div>
</div>
</div>
</div>

View File

@ -9,7 +9,7 @@
<div class="form-group">
<label for="username" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="name" name="row[name]" value="" required="required" />
<input type="text" class="form-control" id="name" name="row[name]" value="" data-rule="required" />
</div>
</div>
<div class="form-group">

View File

@ -9,7 +9,7 @@
<div class="form-group">
<label for="username" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="name" name="row[name]" value="{$row.name}" required="required" />
<input type="text" class="form-control" id="name" name="row[name]" value="{$row.name}" data-rule="required" />
</div>
</div>
<div class="form-group">

View File

@ -18,13 +18,13 @@
<div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="name" name="row[name]" value="" required="required" />
<input type="text" class="form-control" id="name" name="row[name]" value="" data-rule="required" />
</div>
</div>
<div class="form-group">
<label for="module" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="title" name="row[title]" value="" required="required" />
<input type="text" class="form-control" id="title" name="row[title]" value="" data-rule="required" />
</div>
</div>
<div class="form-group">
@ -39,7 +39,7 @@
<div class="form-group">
<label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="weigh" name="row[weigh]" value="0" required="required" />
<input type="text" class="form-control" id="weigh" name="row[weigh]" value="0" data-rule="required" />
</div>
</div>
<div class="form-group">

View File

@ -14,13 +14,13 @@
<div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="name" name="row[name]" value="{$row.name}" required="required" />
<input type="text" class="form-control" id="name" name="row[name]" value="{$row.name}" data-rule="required" />
</div>
</div>
<div class="form-group">
<label for="action" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="title" name="row[title]" value="{$row.title}" required="required" />
<input type="text" class="form-control" id="title" name="row[title]" value="{$row.title}" data-rule="required" />
</div>
</div>
<div class="form-group">

View File

@ -68,10 +68,10 @@
<a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-language"></i></a>
<ul class="dropdown-menu">
<li class="{$config['language']=='zh-cn'?'active':''}">
<a href="?lang=zh-cn">简体中文</a>
<a href="?ref=addtabs&lang=zh-cn">简体中文</a>
</li>
<li class="{$config['language']=='en'?'active':''}">
<a href="?lang=en">English</a>
<a href="?ref=addtabs&lang=en">English</a>
</li>
</ul>
</li>
@ -100,13 +100,13 @@
<li class="user-body">
<div class="row">
<div class="col-xs-4 text-center">
<a href="#">Followers</a>
<a href="http://www.fastadmin.net" target="_blank">官网</a>
</div>
<div class="col-xs-4 text-center">
<a href="#">Sales</a>
<a href="http://forum.fastadmin.net" target="_blank">论坛</a>
</div>
<div class="col-xs-4 text-center">
<a href="#">Friends</a>
<a href="http://doc.fastadmin.net" target="_blank">文档</a>
</div>
</div>
</li>

View File

@ -1,8 +1,8 @@
<table class="table table-striped">
<thead>
<tr>
<th>标题</th>
<th>内容</th>
<th>{:__('Title')}</th>
<th>{:__('Content')}</th>
</tr>
</thead>
<tbody>

View File

@ -7,6 +7,8 @@
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh,delete')}
<a class="btn btn-info btn-disabled disabled btn-selected" href="javascript:;"><i class="fa fa-leaf"></i> 获取选中项</a>
<a class="btn btn-warning btn-singlesearch" href="javascript:;"><i class="fa fa-leaf"></i> 单独设置搜索条件</a>
<div class="dropdown btn-group">
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> <?= __('More') ?></a>
<ul class="dropdown-menu text-left" role="menu">

View File

@ -9,6 +9,9 @@
background:url('http://img.infinitynewtab.com/wallpaper/{:date("Ymd")%4000}.jpg');
background-size:cover;
}
a {
color:#fff;
}
.login-panel{margin-top:150px;}
.login-screen {
max-width:400px;
@ -70,16 +73,18 @@
<div class="login-form">
<img id="profile-img" class="profile-img-card" src="__CDN__/assets/img/avatar.png" />
<p id="profile-name" class="profile-name-card"></p>
<form action="" method="post" id="login-form">
<div id="errtips" class="hide"></div>
{:token()}
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></div>
<input type="text" class="form-control" id="pd-form-username" placeholder="" name="username" autocomplete="off" value="admin" />
<input type="text" class="form-control" id="pd-form-username" placeholder="{:__('Username')}" name="username" autocomplete="off" value="" data-rule="{:__('Username')}:required;username" />
</div>
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span></div>
<input type="password" class="form-control" id="pd-form-password" placeholder="" name="password" autocomplete="off" value="123456" />
<input type="password" class="form-control" id="pd-form-password" placeholder="{:__('Password')}" name="password" autocomplete="off" value="" data-rule="{:__('Password')}:required;password" />
</div>
<div class="form-group">

View File

@ -24,7 +24,7 @@
</ol>
<ol class="breadcrumb pull-right">
{foreach $breadcrumb as $vo}
<li>{$vo.title}</li>
<li><a href="javascript:;" data-url="{$vo.url}">{$vo.title}</a></li>
{/foreach}
</ol>
</div>

View File

@ -2,13 +2,13 @@
<div class="form-group">
<label for="c-category_id" class="control-label col-xs-12 col-sm-2">{:__('Category_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-category_id" class="form-control typeahead" name="row[category_id]" type="text" value="0">
<input id="c-category_id" class="form-control typeahead" name="row[category_id]" type="text" value="0" data-rule="required">
</div>
</div>
<div class="form-group">
<label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-title" class="form-control" name="row[title]" type="text" value="">
<input id="c-title" class="form-control" name="row[title]" type="text" value="" data-rule="required" >
</div>
</div>
<div class="form-group">
@ -27,7 +27,7 @@
<label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="form-inline">
<input id="c-image" class="form-control" size="50" name="row[image]" type="text" value="">
<input id="c-image" class="form-control" size="50" name="row[image]" type="text" value="" data-rule="required">
<span><button id="plupload-image" class="btn btn-danger plupload" data-input-id="c-image" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-multiple="false" data-input-id="c-image"><i class="fa fa-list-ul"></i> {:__('Choose')}</button></span>
<ul class="row list-inline plupload-preview" id="p-image"></ul>

View File

@ -3,13 +3,13 @@
<div class="form-group">
<label for="c-category_id" class="control-label col-xs-12 col-sm-2">{:__('Category_id')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-category_id" class="form-control typeahead" name="row[category_id]" type="text" value="{$row.category_id}">
<input id="c-category_id" class="form-control typeahead" name="row[category_id]" type="text" value="{$row.category_id}" data-rule="required">
</div>
</div>
<div class="form-group">
<label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-title" class="form-control" name="row[title]" type="text" value="{$row.title}">
<input id="c-title" class="form-control" name="row[title]" type="text" value="{$row.title}" data-rule="required" >
</div>
</div>
<div class="form-group">

View File

@ -17,6 +17,8 @@ if (!function_exists('__'))
*/
function __($name, $vars = [], $lang = '')
{
if (is_numeric($name))
return $name;
if (!is_array($vars))
{
$vars = func_get_args();

View File

@ -91,16 +91,6 @@ class Backend extends Controller
// 定义是否AJAX请求
!defined('IS_AJAX') && define('IS_AJAX', $this->request->isAjax());
// 非选项卡时重定向
if (!$this->request->isPost() && !IS_AJAX && !IS_ADDTABS && !IS_DIALOG && input("ref") == 'addtabs')
{
$url = preg_replace_callback("/([\?|&]+)ref=addtabs(&?)/i", function($matches) {
return $matches[2] == '&' ? $matches[1] : '';
}, $this->request->url());
$this->redirect('index/index', [], 302, ['referer' => $url]);
exit;
}
$this->auth = Auth::instance();
// 设置当前请求的URI
@ -126,6 +116,16 @@ class Backend extends Controller
}
}
// 非选项卡时重定向
if (!$this->request->isPost() && !IS_AJAX && !IS_ADDTABS && !IS_DIALOG && input("ref") == 'addtabs')
{
$url = preg_replace_callback("/([\?|&]+)ref=addtabs(&?)/i", function($matches) {
return $matches[2] == '&' ? $matches[1] : '';
}, $this->request->url());
$this->redirect('index/index', [], 302, ['referer' => $url]);
exit;
}
// 设置面包屑导航数据
$breadcrumb = $this->auth->getBreadCrumb($path);
array_pop($breadcrumb);

View File

@ -33,7 +33,8 @@
"typeahead.js": "^0.11.1",
"bootstrap-tagsinput": "^0.8.0",
"nice-validator": "^1.0.10",
"art-template": "^3.0.1"
"art-template": "^3.0.1",
"ajax-bootstrap-select": "^1.3.8"
},
"devDependencies": {
"dragsort": "https://github.com/karsonzhang/dragsort.git",

View File

@ -46,6 +46,12 @@ body {
/*width: 70%;*/
max-width: 885px;
}
.form-group .bootstrap-tagsinput {
display: inherit;
}
.form-group .bootstrap-tagsinput span.twitter-typeahead {
width: auto;
}
#header {
background: #fff;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(0, 0, 0, 0.05);
@ -77,6 +83,16 @@ body {
top: 62px;
right: 12px;
}
.bootstrap-select .status {
background: #f0f0f0;
clear: both;
color: #999;
font-size: 12px;
font-weight: 500;
line-height: 1;
margin-bottom: -5px;
padding: 10px 20px;
}
/*
* RIBBON
*/
@ -279,6 +295,10 @@ body {
.sidebar-menu > li .badge {
margin-top: 0;
}
.sidebar-collapse .user-panel > .image img {
width: 25px;
height: 25px;
}
#treeview .jstree-container-ul .jstree-node {
display: block;
clear: both;

File diff suppressed because one or more lines are too long

View File

@ -215,13 +215,7 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang', 'moment'], function ($
$colorNums = colorArr.length;
badgeList = {};
$.each(params, function (k, v) {
if (k.indexOf('/') > -1)
{
$url = Backend.api.fixurl(k);
} else
{
$url = k;
}
if ($.isArray(v))
{
@ -238,7 +232,7 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang', 'moment'], function ($
badgeList[$url] = $nums > 0 ? '<small class="' + $class + ' pull-right bg-' + $color + '">' + $nums + '</small>' : '';
});
$.each(badgeList, function (k, v) {
var anchor = top.window.$(".treeview li a[addtabs][url='" + k + "']");
var anchor = top.window.$("li a[addtabs][url='" + k + "']");
if (anchor) {
top.window.$(".pull-right-container", anchor).html(v);
top.window.$(".nav-addtabs li a[node-id='" + anchor.attr("addtabs") + "'] .pull-right-container").html(v);
@ -356,10 +350,30 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang', 'moment'], function ($
Backend.api.open(Backend.api.fixurl($(this).attr('href')), $(this).attr('title'));
e.preventDefault();
});
//点击包含.btn-addtabs的元素时事件
$(document).on('click', '.btn-addtabs,.addtabsit', function (e) {
Backend.api.addtabs($(this).attr("href"), $(this).attr("title"));
e.preventDefault();
});
//点击加入到Shortcut
$(document).on('click', '#ribbon ol li:last a[data-url]', function (e) {
e.preventDefault();
var fastjump = top.window.$(".fastmenujump");
if (fastjump) {
var url = $(this).data("url");
var text = $(this).text();
if (fastjump.find("option[value='" + url + "']").size() == 0) {
fastjump.append("<option value='" + url + "'>" + $(this).text() + "</option>");
var shortcut = localStorage.getItem("shortcut");
shortcut = shortcut ? JSON.parse(shortcut) : {};
shortcut[url] = text;
localStorage.setItem("shortcut", JSON.stringify(shortcut));
Toastr.success(__('Operation completed'));
}
} else {
Toastr.error(__('Operation failed'));
}
});
}
};
//将Layer暴露到全局中去

View File

@ -0,0 +1,76 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: function () {
// 初始化表格参数配置
Table.api.init({
extend: {
index_url: 'auth/adminlog/index',
add_url: '',
edit_url: '',
del_url: 'auth/adminlog/del',
multi_url: 'auth/adminlog/multi',
}
});
var table = $("#table");
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
columns: [
[
{field: 'state', checkbox: true, },
{field: 'id', title: 'ID', operate: false},
{field: 'username', title: __('Username'), formatter: Table.api.formatter.search},
{field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '模糊搜索,*表示任意字符', style: 'width:200px'},
{field: 'url', title: __('Url'), align: 'left', formatter: Controller.api.formatter.url},
{field: 'ip', title: __('IP'), events: Controller.api.events.ip, formatter: Controller.api.formatter.ip},
{field: 'browser', title: __('Browser'), operate: false, events: Controller.api.events.browser, formatter: Controller.api.formatter.browser},
{field: 'createtime', title: __('Create time'), formatter: Table.api.formatter.datetime, operate: 'BETWEEN', type: 'datetime', addclass: 'datetimepicker', data: 'data-date-format="YYYY-MM-DD HH:mm:ss"'},
{field: 'operate', title: __('Operate'), events: Controller.api.events.operate, formatter: Controller.api.formatter.operate}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
},
formatter: {
url: function (value, row, index) {
return '<div class="input-group input-group-sm" style="width:250px;"><input type="text" class="form-control input-sm" value="' + value + '"><span class="input-group-btn input-group-sm"><a href="' + value + '" target="_blank" class="btn btn-default btn-sm"><i class="fa fa-link"></i></a></span></div>';
},
ip: function (value, row, index) {
return '<a class="btn btn-xs btn-ip bg-success"><i class="fa fa-map-marker"></i> ' + value + '</a>';
},
browser: function (value, row, index) {
return '<a class="btn btn-xs btn-browser">' + row.useragent.split(" ")[0] + '</a>';
},
operate: function (value, row, index) {
return '<a class="btn btn-info btn-xs btn-detail">' + __('Detail') + '</a> '
+ Table.api.formatter.operate(value, row, index, $("#table"));
},
},
events: {
ip: {
'click .btn-ip': function (e, value, row, index) {
var options = $("#table").bootstrapTable('getOptions');
//这里我们手动将数据填充到表单然后提交
$("#commonSearchContent_" + options.idTable + " form [name='ip']").val(value);
$("#commonSearchContent_" + options.idTable + " form").trigger('submit');
}
},
operate: $.extend({
'click .btn-detail': function (e, value, row, index) {
Backend.api.open('auth/adminlog/detail/ids/' + row['id'], __('Detail'));
}
}, Table.api.events.operate)
}
}
};
return Controller;
});

View File

@ -22,17 +22,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
[
{field: 'state', checkbox: true, },
{field: 'id', title: 'ID', operate: false},
//使用Table.api.formatter.search可直接响应搜索
//直接响应搜索
{field: 'username', title: __('Username'), formatter: Table.api.formatter.search},
{field: 'title', title: __('Title'),
operate: 'LIKE %...%',
placeholder: '模糊搜索,*表示任意字符',
style: 'width:200px',
process: function (value, arg) {
return value.replace(/\*/g, '%');
}
},
{field: 'url', title: __('Url'), align: 'left', formatter: Controller.api.formatter.url},
//模糊搜索
{field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '模糊搜索,*表示任意字符', style: 'width:200px'},
//通过Ajax渲染searchList
{field: 'url', title: __('Url'), align: 'left', searchList: $.getJSON('ajax/typeahead?search=a&field=row[user_id]'), formatter: Controller.api.formatter.url},
//点击IP时同时执行搜索此IP,同时普通搜索使用下拉列表的形式
{field: 'ip', title: __('IP'), searchList: ['127.0.0.1', '127.0.0.2'], events: Controller.api.events.ip, formatter: Controller.api.formatter.ip},
//browser是一个不存在的字段
@ -54,6 +49,16 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
// 为表格绑定事件
Table.api.bindevent(table);
//指定搜索条件
$(document).on("click", ".btn-singlesearch", function () {
table.bootstrapTable('refresh', {query: {filter: JSON.stringify({url: '/admin/index/login.html'}), op: JSON.stringify({url: '='})}});
});
//获取选中项
$(document).on("click", ".btn-selected", function () {
Layer.alert(JSON.stringify(table.bootstrapTable('getSelections')));
});
},
add: function () {
Controller.api.bindevent();
@ -80,7 +85,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
//返回字符串加上Table.api.formatter.operate的结果
//默认需要按需显示排序/编辑/删除按钮,则需要在Table.api.formatter.operate将table传入
//传入了table以后如果edit_url为空则不显示编辑按钮,如果del_url为空则不显显删除按钮
return '<a class="btn btn-info btn-xs btn-detail">' + __('Detail') + '</a> '
return '<a class="btn btn-info btn-xs btn-detail"><i class="fa fa-list"></i> ' + __('Detail') + '</a> '
+ Table.api.formatter.operate(value, row, index, $("#table"));
},
},

View File

@ -26,12 +26,12 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'upload'], function (
[
{field: 'id', title: 'ID'},
{field: 'title', title: __('Title')},
{field: 'url', title: __('Url'), align: 'left', formatter: Table.api.formatter.url},
{field: 'url', title: __('Url'), align: 'left', formatter: Controller.api.formatter.url},
{field: 'ip', title: __('ip')},
{field: 'username', title: __('Userame')},
{field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime},
]
]
],
commonSearch: false
});
// 为表格绑定事件
@ -47,6 +47,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'upload'], function (
var url = Backend.api.cdnurl(response.url);
$(".profile-user-img").prop("src", url);
};
},
api: {
formatter: {
url: function (value, row, index) {
return '<div class="input-group input-group-sm" style="width:250px;"><input type="text" class="form-control input-sm" value="' + value + '"><span class="input-group-btn input-group-sm"><a href="' + value + '" target="_blank" class="btn btn-default btn-sm"><i class="fa fa-link"></i></a></span></div>';
},
},
}
};
return Controller;

View File

@ -140,6 +140,17 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
}
});
var shortcut = localStorage.getItem("shortcut");
shortcut = shortcut ? JSON.parse(shortcut) : {};
$.each(shortcut, function (i, j) {
$("select.fastmenujump").append("<option value='" + i + "'>" + j + "</option>");
});
$(document).on("change", "select.fastmenujump", function () {
if (!$(this).val())
return;
Backend.api.addtabs($(this).val(), $("option:selected", this).text());
});
//绑定tabs事件
$('#nav').addtabs({iframeHeight: "100%"});
@ -189,7 +200,7 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
//Fix the problem with right sidebar and layout boxed
if (cls == "layout-boxed")
AdminLTE.controlSidebar._fix($(".control-sidebar-bg"));
if ($('body').hasClass('fixed') && cls == 'fixed') {
if ($('body').hasClass('fixed') && cls == 'fixed' && false) {
AdminLTE.pushMenu.expandOnHover();
AdminLTE.layout.activate();
}
@ -328,7 +339,29 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
$(window).resize();
},
login: function () {
var lastlogin = localStorage.getItem("lastlogin");
if (lastlogin) {
lastlogin = JSON.parse(lastlogin);
$("#profile-img").attr("src", Backend.api.cdnurl(lastlogin.avatar));
$("#pd-form-username").val(lastlogin.username);
}
//让错误提示框居中
Backend.config.toastr.positionClass = "toast-top-center";
//本地验证未通过时提示
$("#login-form").data("validator-options", {
invalid: function (form, errors) {
$.each(errors, function (i, j) {
Toastr.error(j);
});
},
target: '#errtips'
});
//为表单绑定事件
Form.api.bindevent($("#login-form"), null, function (data) {
localStorage.setItem("lastlogin", JSON.stringify({id: data.id, username: data.username, avatar: data.avatar}));
location.href = Backend.api.fixurl(data.url);
});
}

View File

@ -25,14 +25,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
{field: 'state', checkbox: true},
{field: 'id', title: __('Id'), operate: false},
{field: 'category_id', title: __('Category_id'), operate: '='},
{field: 'title', title: __('Title'),
operate: 'LIKE %...%',
placeholder: '标题,模糊搜索,*表示任意字符',
style: 'width:200px',
process: function (value, arg) {
return value.replace(/\*/g, '%'); //仅演示用法
}
},
{field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '关键字,模糊搜索'},
{field: 'keywords', title: __('Keywords'), operate: 'LIKE %...%', placeholder: '关键字,模糊搜索'},
{field: 'flag', title: __('Flag'), formatter: Table.api.formatter.flag, operate: false},
{field: 'image', title: __('Image'), formatter: Table.api.formatter.image, operate: false},
@ -42,7 +35,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
{field: 'weigh', title: __('Weigh'), operate: false},
{field: 'status', title: __('Status'), formatter: Table.api.formatter.status, searchList: {'normal': __('Normal'), 'hidden': __('Hidden')}, style: 'min-width:100px;'},
{field: 'createtime', title: __('Create Time'), formatter: Table.api.formatter.datetime, operate: 'BETWEEN', type: 'datetime', addclass: 'datetimepicker', data: 'data-date-format="YYYY-MM-DD"'},
{field: 'operate', title: __('Operate'), events: Controller.api.events.operate, formatter: Controller.api.formatter.operate}
{field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate}
]
],
//普通搜索
@ -61,40 +54,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
},
api: {
bindevent: function () {
$("form[role=form]").validator({
rules: {
mobile: [/^1[3-9]\d{9}$/, "请填写有效的手机号"],
chinese: [/^[\u0391-\uFFE5]+$/, "请填写中文字符"],
// 使用函数定义规则
phone: function (elem, param) {
return /^1[3458]\d{9}$/.test($(elem).val()) || '请检查手机号格式';
},
image: function (elem, param) {
return /^\/(.*)\.(jpg|jpeg|png|gif)$/.test($(elem).val()) || '请上传有并行的图片文件';
}
},
messages: {
},
fields: {
'row[title]': "required;length(3~16)",
'row[image]': "required;image",
'row[views]': "required;range[0~100]",
'row[content]': "required"
},
});
Form.api.bindevent($("form[role=form]"));
},
formatter: {
operate: function (value, row, index) {
return '<a class="btn btn-info btn-xs btn-detail">' + __('Detail') + '</a> ' + Table.api.formatter.operate(value, row, index);
},
},
events: {
operate: $.extend({
'click .btn-detail': function (e, value, row, index) {
Backend.api.open("page/detail/" + value, __('Detail'));
}
}, Table.api.events.operate)
}
}
};

View File

@ -76,16 +76,26 @@
ColumnsForSearch.push(vObjCol);
htmlForm.push('<div class="form-group" style="margin:5px">');
htmlForm.push(sprintf('<label for="%s" class="control-label" style="padding:0 10px">%s</label>', vObjCol.field, vObjCol.title));
//htmlForm.push('<div class="col-sm-2">');
//htmlForm.push(sprintf('<select class="form-control" name="field-%s" data-name="%s">%s</select>', vObjCol.field, vObjCol.field, selectHtml));
vObjCol.operate = (typeof vObjCol.operate === 'undefined' || $.inArray(vObjCol.operate, opList) === -1) ? '=' : vObjCol.operate;
htmlForm.push(sprintf('<input type="hidden" class="form-control operate" name="field-%s" data-name="%s" value="%s" readonly>', vObjCol.field, vObjCol.field, vObjCol.operate));
//htmlForm.push('</div>');
//htmlForm.push('<div class="col-sm-8">');
var style = typeof vObjCol.style === 'undefined' ? '' : sprintf('style="%s"', vObjCol.style);
if (vObjCol.searchList) {
if (typeof vObjCol.searchList == 'function') {
if (typeof vObjCol.searchList === 'object' && typeof vObjCol.searchList.then === 'function') {
htmlForm.push(sprintf('<select class="form-control" name="%s" %s>%s</select>', vObjCol.field, style, sprintf('<option value="">%s</option>', that.options.formatCommonChoose())));
(function (vObjCol, options) {
$.when(vObjCol.searchList).done(function (ret) {
if (ret.data && ret.data.searchlist && $.isArray(ret.data.searchlist)) {
var optionList = [];
$.each(ret.data.searchlist, function (key, value) {
var isSelect = value.id === vObjCol.defaultValue ? 'selected' : '';
optionList.push(sprintf("<option value='" + value.id + "' %s>" + value.name + "</option>", isSelect));
});
$("#commonSearchForm_" + options.idTable + " select[name='" + vObjCol.field + "']").append(optionList.join(''));
}
});
})(vObjCol, that.options);
} else if (typeof vObjCol.searchList == 'function') {
htmlForm.push(vObjCol.searchList.call(this, vObjCol));
} else {
var isArray = vObjCol.searchList.constructor === Array;
@ -112,7 +122,6 @@
}
}
//htmlForm.push('</div>');
htmlForm.push('</div>');
}
}
@ -273,17 +282,13 @@
}
});
var searchquery = getSearchQuery(this);
this.options.queryParams = function (params) {
return {
search: params.search,
sort: params.sort,
order: params.order,
filter: JSON.stringify(searchquery.filter),
op: JSON.stringify(searchquery.op),
offset: params.offset,
limit: params.limit,
};
var searchQuery = getSearchQuery(this);
var queryParams = this.options.queryParams;
this.options.queryParams = function () {
var params = queryParams.apply(this, arguments);
params.filter = JSON.stringify($.extend(params.filter || {}, searchQuery.filter));
params.op = JSON.stringify($.extend(params.op || {}, searchQuery.op));
return params;
};
};

View File

@ -29,6 +29,7 @@ require.config({
'bootstrap-dialog': '../libs/bootstrap3-dialog/dist/js/bootstrap-dialog.min',
'bootstrap-datetimepicker': '../libs/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min',
'bootstrap-select': '../libs/bootstrap-select/dist/js/bootstrap-select.min',
'bootstrap-select-ajax': '../libs/ajax-bootstrap-select/dist/js/ajax-bootstrap-select.min',
'bootstrap-table': '../libs/bootstrap-table/dist/bootstrap-table.min',
'bootstrap-table-export': '../libs/bootstrap-table/dist/extensions/export/bootstrap-table-export.min',
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile',

View File

@ -43,6 +43,7 @@ require.config({
'bootstrap-dialog': '../libs/bootstrap3-dialog/dist/js/bootstrap-dialog.min',
'bootstrap-datetimepicker': '../libs/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min',
'bootstrap-select': '../libs/bootstrap-select/dist/js/bootstrap-select.min',
'bootstrap-select-ajax': '../libs/ajax-bootstrap-select/dist/js/ajax-bootstrap-select.min',
'bootstrap-table': '../libs/bootstrap-table/dist/bootstrap-table.min',
'bootstrap-table-export': '../libs/bootstrap-table/dist/extensions/export/bootstrap-table-export.min',
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile',
@ -6634,13 +6635,7 @@ define('backend',['jquery', 'bootstrap', 'toastr', 'layer', 'lang', 'moment'], f
$colorNums = colorArr.length;
badgeList = {};
$.each(params, function (k, v) {
if (k.indexOf('/') > -1)
{
$url = Backend.api.fixurl(k);
} else
{
$url = k;
}
if ($.isArray(v))
{
@ -6657,7 +6652,7 @@ define('backend',['jquery', 'bootstrap', 'toastr', 'layer', 'lang', 'moment'], f
badgeList[$url] = $nums > 0 ? '<small class="' + $class + ' pull-right bg-' + $color + '">' + $nums + '</small>' : '';
});
$.each(badgeList, function (k, v) {
var anchor = top.window.$(".treeview li a[addtabs][url='" + k + "']");
var anchor = top.window.$("li a[addtabs][url='" + k + "']");
if (anchor) {
top.window.$(".pull-right-container", anchor).html(v);
top.window.$(".nav-addtabs li a[node-id='" + anchor.attr("addtabs") + "'] .pull-right-container").html(v);
@ -6775,10 +6770,30 @@ define('backend',['jquery', 'bootstrap', 'toastr', 'layer', 'lang', 'moment'], f
Backend.api.open(Backend.api.fixurl($(this).attr('href')), $(this).attr('title'));
e.preventDefault();
});
//点击包含.btn-addtabs的元素时事件
$(document).on('click', '.btn-addtabs,.addtabsit', function (e) {
Backend.api.addtabs($(this).attr("href"), $(this).attr("title"));
e.preventDefault();
});
//点击加入到Shortcut
$(document).on('click', '#ribbon ol li:last a[data-url]', function (e) {
e.preventDefault();
var fastjump = top.window.$(".fastmenujump");
if (fastjump) {
var url = $(this).data("url");
var text = $(this).text();
if (fastjump.find("option[value='" + url + "']").size() == 0) {
fastjump.append("<option value='" + url + "'>" + $(this).text() + "</option>");
var shortcut = localStorage.getItem("shortcut");
shortcut = shortcut ? JSON.parse(shortcut) : {};
shortcut[url] = text;
localStorage.setItem("shortcut", JSON.stringify(shortcut));
Toastr.success(__('Operation completed'));
}
} else {
Toastr.error(__('Operation failed'));
}
});
}
};
//将Layer暴露到全局中去
@ -7234,7 +7249,7 @@ return d.keepInvalid=a,l},l.datepickerInput=function(a){if(0===arguments.length)
var vModal = sprintf("<div id=\"commonSearchContent_%s\" class=\"common-search-table %s\">", that.options.idTable, that.options.searchFormVisible ? "" : "hidden");
vModal += vFormCommon.join('');
vModal += "</div>";
$("#myTabContent").before($(vModal));
that.$container.prepend($(vModal));
var form = $("#commonSearchForm" + "_" + that.options.idTable);
@ -7292,16 +7307,26 @@ return d.keepInvalid=a,l},l.datepickerInput=function(a){if(0===arguments.length)
ColumnsForSearch.push(vObjCol);
htmlForm.push('<div class="form-group" style="margin:5px">');
htmlForm.push(sprintf('<label for="%s" class="control-label" style="padding:0 10px">%s</label>', vObjCol.field, vObjCol.title));
//htmlForm.push('<div class="col-sm-2">');
//htmlForm.push(sprintf('<select class="form-control" name="field-%s" data-name="%s">%s</select>', vObjCol.field, vObjCol.field, selectHtml));
vObjCol.operate = (typeof vObjCol.operate === 'undefined' || $.inArray(vObjCol.operate, opList) === -1) ? '=' : vObjCol.operate;
htmlForm.push(sprintf('<input type="hidden" class="form-control operate" name="field-%s" data-name="%s" value="%s" readonly>', vObjCol.field, vObjCol.field, vObjCol.operate));
//htmlForm.push('</div>');
//htmlForm.push('<div class="col-sm-8">');
var style = typeof vObjCol.style === 'undefined' ? '' : sprintf('style="%s"', vObjCol.style);
if (vObjCol.searchList) {
if (typeof vObjCol.searchList == 'function') {
if (typeof vObjCol.searchList === 'object' && typeof vObjCol.searchList.then === 'function') {
htmlForm.push(sprintf('<select class="form-control" name="%s" %s>%s</select>', vObjCol.field, style, sprintf('<option value="">%s</option>', that.options.formatCommonChoose())));
(function (vObjCol, options) {
$.when(vObjCol.searchList).done(function (ret) {
if (ret.data && ret.data.searchlist && $.isArray(ret.data.searchlist)) {
var optionList = [];
$.each(ret.data.searchlist, function (key, value) {
var isSelect = value.id === vObjCol.defaultValue ? 'selected' : '';
optionList.push(sprintf("<option value='" + value.id + "' %s>" + value.name + "</option>", isSelect));
});
$("#commonSearchForm_" + options.idTable + " select[name='" + vObjCol.field + "']").append(optionList.join(''));
}
});
})(vObjCol, that.options);
} else if (typeof vObjCol.searchList == 'function') {
htmlForm.push(vObjCol.searchList.call(this, vObjCol));
} else {
var isArray = vObjCol.searchList.constructor === Array;
@ -7328,7 +7353,6 @@ return d.keepInvalid=a,l},l.datepickerInput=function(a){if(0===arguments.length)
}
}
//htmlForm.push('</div>');
htmlForm.push('</div>');
}
}
@ -7397,7 +7421,7 @@ return d.keepInvalid=a,l},l.datepickerInput=function(a){if(0===arguments.length)
var value = $("[name='" + name + "']:checked").val();
}
} else {
var value = (typeof vObjCol.process === 'function') ? vObjCol.process(obj.val()) : obj.val();
var value = (typeof vObjCol.process === 'function') ? vObjCol.process(obj.val()) : (sym == 'LIKE %...%' ? obj.val().replace(/\*/g, '%') : obj.val());
}
if (value == '' && sym.indexOf("NULL") == -1) {
return true;
@ -7489,17 +7513,13 @@ return d.keepInvalid=a,l},l.datepickerInput=function(a){if(0===arguments.length)
}
});
var searchquery = getSearchQuery(this);
this.options.queryParams = function (params) {
return {
search: params.search,
sort: params.sort,
order: params.order,
filter: JSON.stringify(searchquery.filter),
op: JSON.stringify(searchquery.op),
offset: params.offset,
limit: params.limit,
};
var searchQuery = getSearchQuery(this);
var queryParams = this.options.queryParams;
this.options.queryParams = function () {
var params = queryParams.apply(this, arguments);
params.filter = JSON.stringify($.extend(params.filter || {}, searchQuery.filter));
params.op = JSON.stringify($.extend(params.op || {}, searchQuery.op));
return params;
};
};
@ -8757,7 +8777,6 @@ define('upload',['jquery', 'bootstrap', 'backend', 'plupload', 'dragsort', 'temp
that.each(function() {
var instance = $(this).data(NS);
if (instance) {
if ( isString(options) ) {
if ( options.charAt(0) === '_' ) return;
@ -10938,7 +10957,7 @@ define('form',['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'
return false;
},
bindevent: function (form, onBeforeSubmit, onAfterSubmit) {
form.validator({
form.validator($.extend({
validClass: 'has-success',
invalidClass: 'has-error',
bindClassTo: '.form-group',
@ -10972,12 +10991,48 @@ define('form',['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'
});
return false;
}
});
}, form.data("validator-options") || {}));
//绑定select元素事件
if ($(".selectpicker", form).size() > 0) {
require(['bootstrap-select'], function () {
$('.selectpicker', form).selectpicker();
require(['bootstrap-select', 'bootstrap-select-ajax'], function () {
var selectlist = $('.selectpicker', form).selectpicker();
$.each(selectlist, function () {
var that = this;
if ($(this).data("live-search")) {
$(this).ajaxSelectPicker({
ajax: {
url: 'ajax/selectpicker',
beforeSend: function (xhr, setting) {
setting.url = Backend.api.fixurl(setting.url);
},
data: function () {
var params = {
search: '{{{q}}}',
field: $(that).attr("name")
};
return params;
},
dataType: 'json'
},
locale: {
emptyTitle: 'Search...'
},
preprocessData: function (ret) {
var list = [];
if (ret.hasOwnProperty('data') && ret.data) {
var len = ret.data.length;
for (var i = 0; i < len; i++) {
var curr = ret.data[i];
list.push(curr);
}
}
return list;
},
preserveSelected: true
});
}
});
});
}
@ -10994,11 +11049,12 @@ define('form',['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'
if ($(".typeahead").size() > 0 || $(".tagsinput").size() > 0) {
require(['bloodhound'], function () {
var remotesource = function (input) {
var url = $(input).data("url") ? $(input).data("url") : "ajax/typeahead";
return new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: 'ajax/typeahead?search=%QUERY&field=' + $(input).attr("name"),
url: url + '?search=%QUERY&field=' + $(input).attr("name"),
wildcard: '%QUERY',
transform: function (ret) {
return ret.data.searchlist;
@ -11037,11 +11093,12 @@ define('form',['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'
$('.tagsinput', form).each(function () {
$(this).tagsinput({
freeInput: false,
itemValue: 'id',
itemText: 'name',
typeaheadjs: {
name: 'tagsinput',
limit: 20,
displayKey: 'name',
valueKey: 'id',
source: remotesource(this),
templates: {
empty: '<li class="notfound">' + __('No matches found') + '</li>',
@ -11052,7 +11109,6 @@ define('form',['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'
}
});
});
$('.bootstrap-tagsinput .twitter-typeahead').css('display', 'inline');
});
}
});
@ -11088,6 +11144,16 @@ define('form',['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'
$(".summernote", form).summernote({
height: 250,
lang: 'zh-CN',
fontNames: [
'Arial', 'Arial Black', 'Serif', 'Sans', 'Courier',
'Courier New', 'Comic Sans MS', 'Helvetica', 'Impact', 'Lucida Grande',
"Open Sans", "Hiragino Sans GB", "Microsoft YaHei",
'微软雅黑', '宋体', '黑体', '仿宋', '楷体', '幼圆',
],
fontNamesIgnoreCheck: [
"Open Sans", "Microsoft YaHei",
'微软雅黑', '宋体', '黑体', '仿宋', '楷体', '幼圆'
],
dialogsInBody: true,
callbacks: {
onChange: function (contents) {

View File

@ -67,7 +67,7 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func
return false;
},
bindevent: function (form, onBeforeSubmit, onAfterSubmit) {
form.validator({
form.validator($.extend({
validClass: 'has-success',
invalidClass: 'has-error',
bindClassTo: '.form-group',
@ -101,12 +101,48 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func
});
return false;
}
});
}, form.data("validator-options") || {}));
//绑定select元素事件
if ($(".selectpicker", form).size() > 0) {
require(['bootstrap-select'], function () {
$('.selectpicker', form).selectpicker();
require(['bootstrap-select', 'bootstrap-select-ajax'], function () {
var selectlist = $('.selectpicker', form).selectpicker();
$.each(selectlist, function () {
var that = this;
if ($(this).data("live-search")) {
$(this).ajaxSelectPicker({
ajax: {
url: 'ajax/selectpicker',
beforeSend: function (xhr, setting) {
setting.url = Backend.api.fixurl(setting.url);
},
data: function () {
var params = {
search: '{{{q}}}',
field: $(that).attr("name")
};
return params;
},
dataType: 'json'
},
locale: {
emptyTitle: 'Search...'
},
preprocessData: function (ret) {
var list = [];
if (ret.hasOwnProperty('data') && ret.data) {
var len = ret.data.length;
for (var i = 0; i < len; i++) {
var curr = ret.data[i];
list.push(curr);
}
}
return list;
},
preserveSelected: true
});
}
});
});
}
@ -123,11 +159,12 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func
if ($(".typeahead").size() > 0 || $(".tagsinput").size() > 0) {
require(['bloodhound'], function () {
var remotesource = function (input) {
var url = $(input).data("url") ? $(input).data("url") : "ajax/typeahead";
return new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: 'ajax/typeahead?search=%QUERY&field=' + $(input).attr("name"),
url: url + '?search=%QUERY&field=' + $(input).attr("name"),
wildcard: '%QUERY',
transform: function (ret) {
return ret.data.searchlist;
@ -166,11 +203,12 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func
$('.tagsinput', form).each(function () {
$(this).tagsinput({
freeInput: false,
itemValue: 'id',
itemText: 'name',
typeaheadjs: {
name: 'tagsinput',
limit: 20,
displayKey: 'name',
valueKey: 'id',
source: remotesource(this),
templates: {
empty: '<li class="notfound">' + __('No matches found') + '</li>',
@ -181,7 +219,6 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func
}
});
});
$('.bootstrap-tagsinput .twitter-typeahead').css('display', 'inline');
});
}
});
@ -217,6 +254,16 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func
$(".summernote", form).summernote({
height: 250,
lang: 'zh-CN',
fontNames: [
'Arial', 'Arial Black', 'Serif', 'Sans', 'Courier',
'Courier New', 'Comic Sans MS', 'Helvetica', 'Impact', 'Lucida Grande',
"Open Sans", "Hiragino Sans GB", "Microsoft YaHei",
'微软雅黑', '宋体', '黑体', '仿宋', '楷体', '幼圆',
],
fontNamesIgnoreCheck: [
"Open Sans", "Microsoft YaHei",
'微软雅黑', '宋体', '黑体', '仿宋', '楷体', '幼圆'
],
dialogsInBody: true,
callbacks: {
onChange: function (contents) {

View File

@ -67,6 +67,13 @@ body {
max-width:885px;
}
.form-group .bootstrap-tagsinput {
display: inherit;
span.twitter-typeahead {
width:auto;
}
}
#header {
background: #fff;
box-shadow: 0 2px 2px rgba(0,0,0,.05),0 1px 0 rgba(0,0,0,.05);
@ -102,6 +109,17 @@ body {
right:12px;
}
.bootstrap-select .status {
background: #f0f0f0;
clear: both;
color: #999;
font-size: 12px;
font-weight: 500;
line-height: 1;
margin-bottom: -5px;
padding: 10px 20px;
}
/*
* RIBBON
*/
@ -326,6 +344,12 @@ body {
margin-top:0;
}
}
.sidebar-collapse {
.user-panel > .image img{
width:25px;
height:25px;
}
}
#treeview {
.jstree-container-ul .jstree-node{
display:block;clear:both;