作者 Karson

新增导入Excel功能

新增回收站功能
新增插件伪静态配置
新增前端上传组件的回调事件
新增表格column字段中的width参数功能
新增上传和选择限时最多可上传、选择数
添加CRUD中admin_id保留字段
修复非summernote富文本插件不渲染的BUG
移除Backend.php中添加和修改时对请求的数据自动处理
优化分类列表的效率
修复后管理权限管理组不显示的BUG
优化权限级和管理员列表,使用树状显示
修复cdnurl使用site.cdnurl的错误
修复Date::unixtime中获取月天数错误的BUG
优化后台样式
正在显示 47 个修改的文件 包含 1533 行增加787 行删除
... ... @@ -85,7 +85,7 @@ class Crud extends Command
/**
* 保留字段
*/
protected $reservedField = ['createtime', 'updatetime'];
protected $reservedField = ['admin_id', 'createtime', 'updatetime'];
/**
* 排序字段
... ... @@ -95,7 +95,7 @@ class Crud extends Command
/**
* 编辑器的Class
*/
protected $editorClass = 'summernote';
protected $editorClass = 'editor';
protected function configure()
{
... ... @@ -478,6 +478,10 @@ class Crud extends Command
$itemArr = $this->getLangArray($itemArr, FALSE);
//添加一个获取器
$this->getAttr($getAttrArr, $field, $v['DATA_TYPE'] == 'set' ? 'multiple' : 'select');
if ($v['DATA_TYPE'] == 'set')
{
$this->setAttr($setAttrArr, $field, $inputType);
}
$this->appendAttr($appendAttrList, $field);
$formAddElement = $this->getReplacedStub('html/select', ['field' => $field, 'fieldName' => $fieldName, 'fieldList' => $this->getFieldListName($field), 'attrStr' => Form::attributes($attrArr), 'selectedValue' => $defaultValue]);
$formEditElement = $this->getReplacedStub('html/select', ['field' => $field, 'fieldName' => $fieldName, 'fieldList' => $this->getFieldListName($field), 'attrStr' => Form::attributes($attrArr), 'selectedValue' => "\$row.{$field}"]);
... ... @@ -533,6 +537,10 @@ class Crud extends Command
$itemArr = $this->getLangArray($itemArr, FALSE);
//添加一个获取器
$this->getAttr($getAttrArr, $field, $inputType);
if ($inputType == 'checkbox')
{
$this->setAttr($setAttrArr, $field, $inputType);
}
$this->appendAttr($appendAttrList, $field);
$defaultValue = $inputType == 'radio' && !$defaultValue ? key($itemArr) : $defaultValue;
... ... @@ -838,7 +846,7 @@ EOD;
protected function setAttr(&$setAttr, $field, $inputType = '')
{
if ($inputType != 'datetime')
if (!in_array($inputType, ['datetime', 'checkbox', 'select']))
return;
$attrField = ucfirst($this->getCamelizeName($field));
if ($inputType == 'datetime')
... ... @@ -847,6 +855,12 @@ EOD;
return \$value && !is_numeric(\$value) ? strtotime(\$value) : \$value;
EOD;
}
else if (in_array($inputType, ['checkbox', 'select']))
{
$return = <<<EOD
return is_array(\$value) ? implode(',', \$value) : \$value;
EOD;
}
$setAttr[] = <<<EOD
protected function set{$attrField}Attr(\$value)
{
... ...
... ... @@ -2,6 +2,7 @@
protected static function init()
{
self::afterInsert(function ($row) {
$row->save(['{%order%}' => $row['id']]);
$pk = $row->getPk();
$row->getQuery()->where($pk, $row[$pk])->update(['{%order%}' => $row[$pk]]);
});
}
... ...
... ... @@ -68,11 +68,11 @@ CREATE TABLE `fa_attachment` (
`id` int(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`url` varchar(255) NOT NULL DEFAULT '' COMMENT '物理路径',
`imagewidth` varchar(30) NOT NULL DEFAULT '' COMMENT '宽度',
`imageheight` varchar(30) NOT NULL DEFAULT '' COMMENT '度',
`imageheight` varchar(30) NOT NULL DEFAULT '' COMMENT '度',
`imagetype` varchar(30) NOT NULL DEFAULT '' COMMENT '图片类型',
`imageframes` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '图片帧数',
`filesize` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '文件大小',
`mimetype` varchar(30) NOT NULL DEFAULT '' COMMENT 'mime类型',
`mimetype` varchar(50) NOT NULL DEFAULT '' COMMENT 'mime类型',
`extparam` varchar(255) NOT NULL DEFAULT '' COMMENT '透传数据',
`createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建日期',
`updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
... ... @@ -301,13 +301,13 @@ CREATE TABLE `fa_config` (
BEGIN;
INSERT INTO `fa_config` VALUES (1, 'name', 'basic', 'Site name', '请填写站点名称', 'string', 'FastAdmin', '', 'required', '');
INSERT INTO `fa_config` VALUES (2, 'beian', 'basic', 'Beian', '粤ICP备15054802号-4', 'string', '', '', '', '');
INSERT INTO `fa_config` VALUES (3, 'cdnurl', 'basic', 'Cdn url', '如果使用CDN云储存请配置该值', 'string', '', '', '', '');
INSERT INTO `fa_config` VALUES (3, 'cdnurl', 'basic', 'Cdn url', '如果静态资源使用第三方云储存请配置该值', 'string', '', '', '', '');
INSERT INTO `fa_config` VALUES (4, 'version', 'basic', 'Version', '如果静态资源有变动请重新配置该值', 'string', '1.0.1', '', 'required', '');
INSERT INTO `fa_config` VALUES (5, 'timezone', 'basic', 'Timezone', '', 'string', 'Asia/Shanghai', '', 'required', '');
INSERT INTO `fa_config` VALUES (6, 'forbiddenip', 'basic', 'Forbidden ip', '一行一条记录', 'text', '', '', '', '');
INSERT INTO `fa_config` VALUES (7, 'languages', 'basic', 'Languages', '', 'array', '{\"backend\":\"zh-cn\",\"frontend\":\"zh-cn\"}', '', 'required', '');
INSERT INTO `fa_config` VALUES (8, 'fixedpage', 'basic', 'Fixed page', '请尽量输入左侧菜单栏存在的链接', 'string', 'dashboard', '', 'required', '');
INSERT INTO `fa_config` VALUES (9, 'categorytype', 'dictionary', 'Cateogry type', '', 'array', '{\"default\":\"Default\",\"page\":\"Page\",\"article\":\"Article\",\"test\":\"Test\"}', '', '', '');
INSERT INTO `fa_config` VALUES (9, 'categorytype', 'dictionary', 'Category type', '', 'array', '{\"default\":\"Default\",\"page\":\"Page\",\"article\":\"Article\",\"test\":\"Test\"}', '', '', '');
INSERT INTO `fa_config` VALUES (10, 'configgroup', 'dictionary', 'Config group', '', 'array', '{\"basic\":\"Basic\",\"email\":\"Email\",\"dictionary\":\"Dictionary\",\"user\":\"User\",\"example\":\"Example\"}', '', '', '');
INSERT INTO `fa_config` VALUES (11, 'mail_type', 'email', 'Mail type', '选择邮件发送方式', 'select', '1', '[\"Please select\",\"SMTP\",\"Mail\"]', '', '');
INSERT INTO `fa_config` VALUES (12, 'mail_smtp_host', 'email', 'Mail smtp host', '错误的配置发送邮件会导致服务器超时', 'string', 'smtp.qq.com', '', '', '');
... ...
... ... @@ -90,7 +90,7 @@ function build_toolbar($btns = NULL, $attr = [])
{
$auth = \app\admin\library\Auth::instance();
$controller = str_replace('.', '/', strtolower(think\Request::instance()->controller()));
$btns = $btns ? $btns : ['refresh', 'add', 'edit', 'del'];
$btns = $btns ? $btns : ['refresh', 'add', 'edit', 'del', 'import'];
$btns = is_array($btns) ? $btns : explode(',', $btns);
$index = array_search('delete', $btns);
if ($index !== FALSE)
... ... @@ -98,10 +98,11 @@ function build_toolbar($btns = NULL, $attr = [])
$btns[$index] = 'del';
}
$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')],
'del' => ['javascript:;', 'btn btn-danger btn-del btn-disabled disabled', 'fa fa-trash', __('Delete')],
'refresh' => ['javascript:;', 'btn btn-primary btn-refresh', 'fa fa-refresh', '', __('Refresh')],
'add' => ['javascript:;', 'btn btn-success btn-add', 'fa fa-plus', __('Add'), __('Add')],
'edit' => ['javascript:;', 'btn btn-success btn-edit btn-disabled disabled', 'fa fa-pencil', __('Edit'), __('Edit')],
'del' => ['javascript:;', 'btn btn-danger btn-del btn-disabled disabled', 'fa fa-trash', __('Delete'), __('Delete')],
'import' => ['javascript:;', 'btn btn-danger btn-import', 'fa fa-upload', __('Import'), __('Import')],
];
$btnAttr = array_merge($btnAttr, $attr);
$html = [];
... ... @@ -112,8 +113,9 @@ function build_toolbar($btns = NULL, $attr = [])
{
continue;
}
list($href, $class, $icon, $text) = $btnAttr[$v];
$html[] = '<a href="' . $href . '" class="' . $class . '" ><i class="' . $icon . '"></i> ' . $text . '</a>';
list($href, $class, $icon, $text, $title) = $btnAttr[$v];
$extend = $v == 'import' ? 'id="btn-import-' . \fast\Random::alpha() . '" data-url="ajax/upload" data-mimetype="csv,xsl,xslx" data-multiple="false"' : '';
$html[] = '<a href="' . $href . '" class="' . $class . '" title="' . $title . '" ' . $extend . '><i class="' . $icon . '"></i> ' . $text . '</a>';
}
return implode(' ', $html);
}
... ...
... ... @@ -107,7 +107,8 @@ class Ajax extends Backend
'sha1' => $sha1,
);
$attachment = model("attachment");
$attachment->create(array_filter($params));
$attachment->data(array_filter($params));
$attachment->save();
\think\Hook::listen("upload_after", $attachment);
$this->success('上传成功', null, [
'url' => $uploadDir . $splInfo->getSaveName()
... ...
... ... @@ -26,7 +26,7 @@ class Category extends Backend
$this->model = model('Category');
$tree = Tree::instance();
$tree->init($this->model->order('weigh desc,id desc')->select(), 'pid');
$tree->init(collection($this->model->order('weigh desc,id desc')->select())->toArray(), 'pid');
$this->categorylist = $tree->getTreeList($tree->getTreeArray(0), 'name');
$categorydata = [0 => ['type' => 'all', 'name' => __('None')]];
foreach ($this->categorylist as $k => $v)
... ...
... ... @@ -28,10 +28,10 @@ class Index extends Backend
{
//
$menulist = $this->auth->getSidebar([
'dashboard' => 'hot',
'addon' => ['new', 'red', 'badge'],
'auth/rule' => 'side',
'general' => ['18', 'purple'],
'dashboard' => 'hot',
'addon' => ['new', 'red', 'badge'],
'auth/rule' => 'side',
'general' => ['18', 'purple'],
], $this->view->site['fixedpage']);
$this->view->assign('menulist', $menulist);
$this->view->assign('title', __('Home'));
... ... @@ -87,8 +87,6 @@ class Index extends Backend
{
$this->redirect($url);
}
$background = cdnurl("/assets/img/loginbg.jpg");
$this->view->assign('background', $background);
\think\Hook::listen("login_init", $this->request);
return $this->view->fetch();
}
... ...
... ... @@ -27,15 +27,28 @@ class Admin extends Backend
$this->model = model('Admin');
$this->childrenAdminIds = $this->auth->getChildrenAdminIds(true);
$this->childrenGroupIds = $this->auth->getChildrenGroupIds();
$groupName = AuthGroup::where('id', 'in', $this->childrenGroupIds)
->column('id,name');
foreach ($groupName as $k => &$v)
$this->childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin() ? true : false);
$groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->select())->toArray();
$groupIds = $this->auth->getGroupIds();
Tree::instance()->init($groupList);
$result = [];
if ($this->auth->isSuperAdmin())
{
$result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
}
else
{
foreach ($groupIds as $m => $n)
{
$result = array_merge($result, Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n)));
}
}
$groupName = [];
foreach ($result as $k => $v)
{
$v = __($v);
$groupName[$v['id']] = $v['name'];
}
unset($v);
$this->view->assign('groupdata', $groupName);
$this->assignconfig("admin", ['id' => $this->auth->id]);
... ...
... ... @@ -24,7 +24,7 @@ class Adminlog extends Backend
$this->model = model('AdminLog');
$this->childrenAdminIds = $this->auth->getChildrenAdminIds(true);
$this->childrenGroupIds = $this->auth->getChildrenGroupIds();
$this->childrenGroupIds = $this->auth->getChildrenGroupIds($this->auth->isSuperAdmin() ? true : false);
$groupName = AuthGroup::where('id', 'in', $this->childrenGroupIds)
->column('id,name');
... ...
... ... @@ -30,13 +30,26 @@ class Group extends Backend
$this->childrenGroupIds = $this->auth->getChildrenGroupIds(true);
$groupName = AuthGroup::where('id', 'in', $this->childrenGroupIds)
->column('id,name');
foreach ($groupName as $k => &$v)
$groupList = collection(AuthGroup::where('id', 'in', $this->childrenGroupIds)->select())->toArray();
$groupIds = $this->auth->getGroupIds();
Tree::instance()->init($groupList);
$result = [];
if ($this->auth->isSuperAdmin())
{
$v = __($v);
$result = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
}
else
{
foreach ($groupIds as $m => $n)
{
$result = array_merge($result, Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n)));
}
}
$groupName = [];
foreach ($result as $k => $v)
{
$groupName[$v['id']] = $v['name'];
}
unset($v);
$this->groupdata = $groupName;
$this->assignconfig("admin", ['id' => $this->auth->id, 'group_ids' => $this->auth->getGroupIds()]);
... ... @@ -51,12 +64,21 @@ class Group extends Backend
{
if ($this->request->isAjax())
{
$list = AuthGroup::all(array_keys($this->groupdata));
$list = collection($list)->toArray();
$groupList = [];
foreach ($list as $k => $v)
{
$groupList[$v['id']] = $v;
}
$list = [];
foreach ($this->groupdata as $k => $v)
{
$data = $this->model->get($k);
$data->name = $v;
$list[] = $data;
if (isset($groupList[$k]))
{
$groupList[$k]['name'] = $v;
$list[] = $groupList[$k];
}
}
$total = count($list);
$result = array("total" => $total, "rows" => $list);
... ...
... ... @@ -82,19 +82,9 @@ class Config extends Backend
}
try
{
if ($params['content'] && in_array($params['type'], ['select', 'selects', 'checkbox', 'radio']))
if (in_array($params['type'], ['select', 'selects', 'checkbox', 'radio', 'array']))
{
$content = explode("\r\n", $params['content']);
$arr = [];
foreach ($content as $k => &$v)
{
if (stripos($v, "|") !== false)
{
$item = explode('|', $v);
$arr[$item[0]] = $item[1];
}
}
$params['content'] = $arr ? json_encode($arr, JSON_UNESCAPED_UNICODE) : '';
$params['content'] = ConfigModel::decode($params['content']);
}
else
{
... ... @@ -132,40 +122,28 @@ class Config extends Backend
{
if ($this->request->isPost())
{
$params = $this->request->post("row/a");
if ($params)
$row = $this->request->post("row/a");
if ($row)
{
$configList = [];
foreach ($this->model->all() as $k => $v)
foreach ($this->model->all() as $v)
{
if (isset($params[$v['name']]))
if (isset($row[$v['name']]))
{
if ($v['type'] == 'array')
$value = $row[$v['name']];
if (is_array($value) && isset($value['field']))
{
$fieldarr = $valuearr = [];
$field = $params[$v['name']]['field'];
$value = $params[$v['name']]['value'];
foreach ($field as $m => $n)
{
if ($n != '')
{
$fieldarr[] = $field[$m];
$valuearr[] = $value[$m];
}
}
$params[$v['name']] = array_combine($fieldarr, $valuearr);
$value = json_encode($params[$v['name']], JSON_UNESCAPED_UNICODE);
$value = json_encode(\app\common\model\Config::getArrayData($value), JSON_UNESCAPED_UNICODE);
}
else
{
$value = is_array($params[$v['name']]) ? implode(',', $params[$v['name']]) : $params[$v['name']];
$value = is_array($value) ? implode(',', $value) : $value;
}
$configList[] = ['id' => $v['id'], 'value' => $value];
$v['value'] = $value;
$configList[] = $v;
}
}
$this->model->saveAll($configList);
$this->model->allowField(true)->saveAll($configList);
try
{
$this->refreshFile();
... ...
... ... @@ -16,6 +16,7 @@ return [
'Edit' => '编辑',
'Del' => '删除',
'Delete' => '删除',
'Import' => '导入',
'Detail' => '详情',
'Multi' => '批量更新',
'Setting' => '配置',
... ... @@ -116,6 +117,8 @@ return [
'Network error' => '网络错误!',
'Invalid parameters' => '未知参数',
'No results were found' => '记录未找到',
'No rows were deleted' => '未删除任何行',
'No rows were updated' => '未更新任何行',
'Parameter %s can not be empty' => '参数%s不能为空',
'Are you sure you want to delete the %s selected item?' => '确定删除选中的 %s 项?',
'Are you sure you want to delete this item?' => '确定删除此项?',
... ... @@ -124,6 +127,8 @@ return [
'Please enter your username' => '请输入你的用户名',
'Please enter your password' => '请输入你的密码',
'Please login first' => '请登录后操作',
'You can upload up to %d file%s' => '你最多还可以上传%d个文件',
'You can choose up to %d file%s' => '你最多还可以选择%d个文件',
'An unexpected error occurred' => '发生了一个意外错误,程序猿正在紧急处理中',
'This page will be re-directed in %s seconds' => '页面将在 %s 秒后自动跳转',
//菜单
... ... @@ -152,9 +157,9 @@ return [
'Config tips' => '可以在此增改系统的变量和分组,也可以自定义分组和变量,如果需要删除请从数据库中删除',
'Category tips' => '用于统一管理网站的所有分类,分类可进行无限级分类',
'Attachment tips' => '主要用于管理上传到服务器或第三方存储的数据',
'Addon tips' => '可在线安装、卸载、禁用、启用插件,同时支持Add本地插件。FastAdmin已上线插件商店 ,你可以发布你的免费或付费插件:<a href="http://www.fastadmin.net/store.html" target="_blank">http://www.fastadmin.net/store.html</a>',
'Addon tips' => '可在线安装、卸载、禁用、启用插件,同时支持添加本地插件。FastAdmin已上线插件商店 ,你可以发布你的免费或付费插件:<a href="http://www.fastadmin.net/store.html" target="_blank">http://www.fastadmin.net/store.html</a>',
'Admin tips' => '一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成',
'Admin log tips' => '管理员可以View自己所拥有的权限的管理员日志',
'Group tips' => '角色组可以有多个,角色有上下级层级关系,如果子角色有角色组和管理员的权限则可以派生属于自己组别下级的角色组或管理员',
'Rule tips' => '规则通常对应一个控制器的方法,同时左侧的菜单栏数据也从规则中体现,通常建议通过控制台进行生成规则节点',
'Admin log tips' => '管理员可以查看自己所拥有的权限的管理员日志',
'Group tips' => '角色组可以有多个,角色有上下级层级关系,如果子角色有角色组和管理员的权限则可以派生属于自己组别的下级角色组或管理员',
'Rule tips' => '规则通常对应一个控制器的方法,同时左侧的菜单栏数据也从规则中体现,通常建议通过命令行进行生成规则节点',
];
... ...
... ... @@ -16,6 +16,7 @@ return [
'Extend' => '扩展属性',
'String' => '字符',
'Text' => '文本',
'Editor' => '编辑器',
'Number' => '数字',
'Date' => '日期',
'Time' => '时间',
... ...
... ... @@ -39,6 +39,36 @@ trait Backend
}
/**
* 回收站
*/
public function recyclebin()
{
//设置过滤方法
$this->request->filter(['strip_tags']);
if ($this->request->isAjax())
{
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model
->onlyTrashed()
->where($where)
->order($sort, $order)
->count();
$list = $this->model
->onlyTrashed()
->where($where)
->order($sort, $order)
->limit($offset, $limit)
->select();
$result = array("total" => $total, "rows" => $list);
return json($result);
}
return $this->view->fetch();
}
/**
* 添加
*/
public function add()
... ... @@ -48,10 +78,13 @@ trait Backend
$params = $this->request->post("row/a");
if ($params)
{
foreach ($params as $k => &$v)
{
$v = is_array($v) ? implode(',', $v) : $v;
}
/*
* 已经弃用,如果为了兼容老版可取消注释
foreach ($params as $k => &$v)
{
$v = is_array($v) ? implode(',', $v) : $v;
}
*/
if ($this->dataLimit)
{
$params[$this->dataLimitField] = $this->auth->id;
... ... @@ -65,7 +98,7 @@ trait Backend
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : true) : $this->modelValidate;
$this->model->validate($validate);
}
$result = $this->model->save($params);
$result = $this->model->allowField(true)->save($params);
if ($result !== false)
{
$this->success();
... ... @@ -106,10 +139,13 @@ trait Backend
$params = $this->request->post("row/a");
if ($params)
{
foreach ($params as $k => &$v)
{
$v = is_array($v) ? implode(',', $v) : $v;
}
/*
* 已经弃用,如果为了兼容老版可取消注释
foreach ($params as $k => &$v)
{
$v = is_array($v) ? implode(',', $v) : $v;
}
*/
try
{
//是否采用模型验证
... ... @@ -119,7 +155,7 @@ trait Backend
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : true) : $this->modelValidate;
$row->validate($validate);
}
$result = $row->save($params);
$result = $row->allowField(true)->save($params);
if ($result !== false)
{
$this->success();
... ... @@ -129,7 +165,7 @@ trait Backend
$this->error($row->getError());
}
}
catch (think\exception\PDOException $e)
catch (\think\exception\PDOException $e)
{
$this->error($e->getMessage());
}
... ... @@ -147,24 +183,86 @@ trait Backend
{
if ($ids)
{
$pk = $this->model->getPk();
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds))
{
$count = $this->model->where($this->dataLimitField, 'in', $adminIds)->delete($ids);
$count = $this->model->where($this->dataLimitField, 'in', $adminIds);
}
else
$list = $this->model->where($pk, 'in', $ids)->select();
$count = 0;
foreach ($list as $k => $v)
{
$count = $this->model->destroy($ids);
$count += $v->delete();
}
if ($count)
{
$this->success();
}
else
{
$this->error(__('No rows were deleted'));
}
}
$this->error(__('Parameter %s can not be empty', 'ids'));
}
/**
* 真实删除
*/
public function destroy($ids = "")
{
$pk = $this->model->getPk();
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds))
{
$count = $this->model->where($this->dataLimitField, 'in', $adminIds);
}
if ($ids)
{
$this->model->where($pk, 'in', $ids);
}
$count = 0;
$list = $this->model->onlyTrashed()->select();
foreach ($list as $k => $v)
{
$count += $v->delete(true);
}
if ($count)
{
$this->success();
}
else
{
$this->error(__('No rows were deleted'));
}
$this->error(__('Parameter %s can not be empty', 'ids'));
}
/**
* 还原
*/
public function restore($ids = "")
{
$pk = $this->model->getPk();
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds))
{
$this->model->where($this->dataLimitField, 'in', $adminIds);
}
if ($ids)
{
$this->model->where($pk, 'in', $ids);
}
$count = $this->model->restore('1=1');
if ($count)
{
$this->success();
}
$this->error(__('No rows were updated'));
}
/**
* 批量更新
*/
public function multi($ids = "")
... ... @@ -188,6 +286,10 @@ trait Backend
{
$this->success();
}
else
{
$this->error(__('No rows were updated'));
}
}
else
{
... ... @@ -198,4 +300,95 @@ trait Backend
$this->error(__('Parameter %s can not be empty', 'ids'));
}
/**
* 导入
*/
protected function import()
{
$file = $this->request->request('file');
if (!$file)
{
$this->error(__('Parameter %s can not be empty', 'file'));
}
$filePath = ROOT_PATH . DS . 'public' . DS . $file;
if (!is_file($filePath))
{
$this->error(__('No results were found'));
}
$PHPReader = new \PHPExcel_Reader_Excel2007();
if (!$PHPReader->canRead($filePath))
{
$PHPReader = new \PHPExcel_Reader_Excel5();
if (!$PHPReader->canRead($filePath))
{
$PHPReader = new \PHPExcel_Reader_CSV();
if (!$PHPReader->canRead($filePath))
{
$this->error(__('Unknown data format'));
}
}
}
$table = $this->model->getQuery()->getTable();
$database = \think\Config::get('database.database');
$fieldArr = [];
$list = db()->query("SELECT COLUMN_NAME,COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?", [$table, $database]);
foreach ($list as $k => $v)
{
$fieldArr[$v['COLUMN_COMMENT']] = $v['COLUMN_NAME'];
}
$PHPExcel = $PHPReader->load($filePath); //加载文件
$currentSheet = $PHPExcel->getSheet(0); //读取文件中的第一个工作表
$allColumn = $currentSheet->getHighestColumn(); //取得最大的列号
$allRow = $currentSheet->getHighestRow(); //取得一共有多少行
for ($currentRow = 1; $currentRow <= 1; $currentRow++)
{
for ($currentColumn = 'A'; $currentColumn <= $allColumn; $currentColumn++)
{
$val = $currentSheet->getCellByColumnAndRow(ord($currentColumn) - 65, $currentRow)->getValue();
$fields[] = $val;
}
}
$insert = [];
for ($currentRow = 2; $currentRow <= $allRow; $currentRow++)
{
$values = [];
for ($currentColumn = 'A'; $currentColumn <= $allColumn; $currentColumn++)
{
$val = $currentSheet->getCellByColumnAndRow(ord($currentColumn) - 65, $currentRow)->getValue(); /* * ord()将字符转为十进制数 */
$values[] = is_null($val) ? '' : $val;
//echo iconv('utf-8','gb2312', $val)."\t";
}
$row = [];
$temp = array_combine($fields, $values);
foreach ($temp as $k => $v)
{
if (isset($fieldArr[$k]) && $k !== '')
{
$row[$fieldArr[$k]] = $v;
}
}
if ($row)
{
$insert[] = $row;
}
}
if (!$insert)
{
$this->error(__('No rows were updated'));
}
try
{
$this->model->saveAll($insert);
}
catch (\think\exception\PDOException $exception)
{
$this->error($exception->getMessage());
}
$this->success();
}
}
... ...
... ... @@ -13,4 +13,9 @@ class AuthGroup extends Model
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
public function getNameAttr($value, $data)
{
return __($value);
}
}
... ...
... ... @@ -13,4 +13,8 @@ class AuthRule extends Model
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
public function getTitleAttr($value, $data)
{
return __($value);
}
}
... ...
... ... @@ -10,7 +10,7 @@
<div class="form-group">
<label for="c-third" class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button id="plupload-third" class="btn btn-danger plupload" data-input-id="c-third" ><i class="fa fa-upload"></i> {:__("Upload to third")}</button>
<button id="plupload-third" class="btn btn-danger plupload" data-multiple="true" data-input-id="c-third" ><i class="fa fa-upload"></i> {:__("Upload to third")}</button>
</div>
</div>
{/if}
... ...
... ... @@ -41,7 +41,7 @@
<div class="box-body box-profile">
<div class="profile-avatar-container">
<img class="profile-user-img img-responsive img-circle plupload" src="__CDN__{$admin.avatar}" alt="">
<img class="profile-user-img img-responsive img-circle plupload" src="{$admin.avatar}" alt="">
<div class="profile-avatar-text img-circle">{:__('Click to edit')}</div>
<button id="plupload-avatar" class="plupload" data-input-id="c-avatar"><i class="fa fa-upload"></i> {:__('Upload')}</button>
</div>
... ...
... ... @@ -6,7 +6,7 @@
<style type="text/css">
body {
color:#999;
background:url('{$background}');
background:url('__CDN__/assets/img/loginbg.jpg');
background-size:cover;
}
a {
... ...
... ... @@ -83,14 +83,13 @@ if (!function_exists('cdnurl'))
{
/**
* 获取CDN的地址
* @param int $time 时间戳
* @param string $format 日期时间格式
* 获取上传资源的CDN的地址
* @param string $url 资源相对地址
* @return string
*/
function cdnurl($url)
{
return preg_match("/^https?:\/\/(.*)/i", $url) ? $url : think\Config::get('site.cdnurl') . $url;
return preg_match("/^https?:\/\/(.*)/i", $url) ? $url : think\Config::get('upload.cdnurl') . $url;
}
}
... ... @@ -207,4 +206,97 @@ if (!function_exists('mb_ucfirst'))
return mb_strtoupper(mb_substr($string, 0, 1)) . mb_strtolower(mb_substr($string, 1));
}
}
\ No newline at end of file
}
if (!function_exists('addtion'))
{
/**
* 附加关联字段数据
* @param array $items 数据列表
* @param mixed $fields 渲染的来源字段
* @return array
*/
function addtion($items, $fields)
{
if (!$items || !$fields)
return $items;
$fieldsArr = [];
if (!is_array($fields))
{
$arr = explode(',', $fields);
foreach ($arr as $k => $v)
{
$fieldsArr[$v] = ['field' => $v];
}
}
else
{
foreach ($fields as $k => $v)
{
if (is_array($v))
{
$v['field'] = isset($v['field']) ? $v['field'] : $k;
}
else
{
$v = ['field' => $v];
}
$fieldsArr[$v['field']] = $v;
}
}
foreach ($fieldsArr as $k => &$v)
{
$v = is_array($v) ? $v : ['field' => $v];
$v['display'] = isset($v['display']) ? $v['display'] : str_replace(['_ids', '_id'], ['_names', '_name'], $v['field']);
$v['primary'] = isset($v['primary']) ? $v['primary'] : '';
$v['column'] = isset($v['column']) ? $v['column'] : 'name';
$v['model'] = isset($v['model']) ? $v['model'] : '';
$v['table'] = isset($v['table']) ? $v['table'] : '';
$v['name'] = isset($v['name']) ? $v['name'] : str_replace(['_ids', '_id'], '', $v['field']);
}
unset($v);
$ids = [];
$fields = array_keys($fieldsArr);
foreach ($items as $k => $v)
{
foreach ($fields as $m => $n)
{
if (isset($v[$n]))
{
$ids[$n] = array_merge(isset($ids[$n]) && is_array($ids[$n]) ? $ids[$n] : [], explode(',', $v[$n]));
}
}
}
$result = [];
foreach ($fieldsArr as $k => $v)
{
if ($v['model'])
{
$model = new $v['model'];
}
else
{
$model = $v['name'] ? \think\Db::name($v['name']) : \think\Db::table($v['table']);
}
$primary = $v['primary'] ? $v['primary'] : $model->getPk();
$result[$v['field']] = $model->where($primary, 'in', $ids[$v['field']])->column("{$primary},{$v['column']}");
}
foreach ($items as $k => &$v)
{
foreach ($fields as $m => $n)
{
if (isset($v[$n]))
{
$curr = array_flip(explode(',', $v[$n]));
$v[$fieldsArr[$n]['display']] = implode(',', array_intersect_key($result[$n], $curr));
}
}
}
return $items;
}
}
... ...
... ... @@ -170,6 +170,9 @@ class Backend extends Controller
'fastadmin' => Config::get('fastadmin'),
'referer' => Session::get("referer")
];
Config::set('upload', array_merge(Config::get('upload'), $upload));
// 配置信息后
Hook::listen("config_init", $config);
//加载当前控制器语言包
... ...
... ... @@ -4,6 +4,7 @@ namespace app\common\controller;
use think\Config;
use think\Controller;
use think\Hook;
use think\Lang;
class Frontend extends Controller
... ... @@ -34,10 +35,15 @@ class Frontend extends Controller
$site = Config::get("site");
$upload = \app\common\model\Config::upload();
// 上传信息配置后
Hook::listen("upload_config_init", $upload);
// 配置信息
$config = [
'site' => array_intersect_key($site, array_flip(['name', 'cdnurl', 'version', 'timezone', 'languages'])),
'upload' => \app\common\model\Config::upload(),
'upload' => $upload,
'modulename' => $modulename,
'controllername' => $controllername,
'actionname' => $actionname,
... ... @@ -45,6 +51,11 @@ class Frontend extends Controller
'moduleurl' => rtrim(url("/{$modulename}", '', false), '/'),
'language' => $lang
];
Config::set('upload', array_merge(Config::get('upload'), $upload));
// 配置信息后
Hook::listen("config_init", $config);
$this->loadlang($controllername);
$this->assign('site', $site);
$this->assign('config', $config);
... ...
... ... @@ -27,7 +27,10 @@ class Config extends Model
$typeList = [
'string' => __('String'),
'text' => __('Text'),
'editor' => __('Editor'),
'number' => __('Number'),
'date' => __('Date'),
'time' => __('Time'),
'datetime' => __('Datetime'),
'select' => __('Select'),
'selects' => __('Selects'),
... ... @@ -38,10 +41,33 @@ class Config extends Model
'checkbox' => __('Checkbox'),
'radio' => __('Radio'),
'array' => __('Array'),
'custom' => __('Custom'),
];
return $typeList;
}
public static function getRegexList()
{
$regexList = [
'required' => '必选',
'digits' => '数字',
'letters' => '字母',
'date' => '日期',
'time' => '时间',
'email' => '邮箱',
'url' => '网址',
'qq' => 'QQ号',
'IDcard' => '身份证',
'tel' => '座机电话',
'mobile' => '手机号',
'zipcode' => '邮编',
'chinese' => '中文',
'username' => '用户名',
'password' => '密码'
];
return $regexList;
}
/**
* 读取分类分组列表
* @return array
... ... @@ -49,9 +75,69 @@ class Config extends Model
public static function getGroupList()
{
$groupList = config('site.configgroup');
foreach ($groupList as $k => &$v)
{
$v = __($v);
}
return $groupList;
}
public static function getArrayData($data)
{
$fieldarr = $valuearr = [];
$field = isset($data['field']) ? $data['field'] : [];
$value = isset($data['value']) ? $data['value'] : [];
foreach ($field as $m => $n)
{
if ($n != '')
{
$fieldarr[] = $field[$m];
$valuearr[] = $value[$m];
}
}
return $fieldarr ? array_combine($fieldarr, $valuearr) : [];
}
/**
* 将字符串解析成键值数组
* @param string $text
* @return array
*/
public static function decode($text, $split = "\r\n")
{
$content = explode($split, $text);
$arr = [];
foreach ($content as $k => $v)
{
if (stripos($v, "|") !== false)
{
$item = explode('|', $v);
$arr[$item[0]] = $item[1];
}
}
return $arr;
}
/**
* 将键值数组转换为字符串
* @param array $array
* @return string
*/
public static function encode($array, $split = "\r\n")
{
$content = '';
if ($array && is_array($array))
{
$arr = [];
foreach ($array as $k => $v)
{
$arr[] = "{$k}|{$v}";
}
$content = implode($split, $arr);
}
return $content;
}
/**
* 本地上传配置信息
* @return array
... ...
... ... @@ -130,6 +130,7 @@ return [
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
'tpl_cache' => true,
],
// 视图输出字符串内容替换
'view_replace_str' => [
... ... @@ -242,7 +243,7 @@ return [
],
//FastAdmin配置
'fastadmin' => [
'version' => '1.0.0.20170915_beta',
'api_url' => 'http://api.fastadmin.net',
'version' => '1.0.0.20171026_beta',
'api_url' => 'http://api.fastadmin.net',
],
];
... ...
... ... @@ -5,4 +5,7 @@ return array (
'hooks' =>
array (
),
'route' =>
array (
),
);
\ No newline at end of file
... ...
... ... @@ -214,5 +214,4 @@
</body>
</html>
</html>
\ No newline at end of file
... ...
... ... @@ -11,20 +11,16 @@
// +----------------------------------------------------------------------
//如果有定义绑定后台模块则禁用路由规则
if (\think\Route::getBind('module') == 'admin')
if (\think\Route::getBind('module') == 'admin'){
return [];
}
return [
//别名配置,别名只能是映射到控制器且访问时必须加上请求的方法
// '__alias__' => [
// 'demo' => 'admin/Test',
// ],
'__pattern__' => [
'name' => '\w+',
'__alias__' => [
],
'[hello]' => [
':id' => ['index/hello', ['method' => 'get'], ['id' => '\d+']],
':name' => ['index/hello', ['method' => 'post']],
//变量规则
'__pattern__' => [
],
// 域名绑定到模块
// '__domain__' => [
... ...
... ... @@ -23,7 +23,8 @@
"mtdowling/cron-expression": "^1.2",
"phpmailer/phpmailer": "^5.2",
"karsonzhang/fastadmin-addons": "dev-master",
"overtrue/pinyin": "~3.0"
"overtrue/pinyin": "~3.0",
"phpoffice/phpexcel": "^1.8"
},
"config": {
"preferred-install": "dist"
... ...
... ... @@ -195,12 +195,12 @@ class Date
mktime(23, 59, 59, $month, $day - date("w", mktime(0, 0, 0, $month, $day, $year)) + 7 - 7 * (-$offset), $year);
break;
case 'month':
$time = $position ? mktime(0, 0, 0, $month + $offset, 1, $year) : mktime(23, 59, 59, $month + $offset, get_month_days($month + $offset, $year), $year);
$time = $position ? mktime(0, 0, 0, $month + $offset, 1, $year) : mktime(23, 59, 59, $month + $offset, cal_days_in_month(CAL_GREGORIAN, $month + $offset, $year), $year);
break;
case 'quarter':
$time = $position ?
mktime(0, 0, 0, 1 + ((ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) - 1) * 3, 1, $year) :
mktime(23, 59, 59, (ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) * 3, get_month_days((ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) * 3, $year), $year);
mktime(23, 59, 59, (ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) * 3, cal_days_in_month(CAL_GREGORIAN, (ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) * 3, $year), $year);
break;
case 'year':
$time = $position ? mktime(0, 0, 0, 1, 1, $year + $offset) : mktime(23, 59, 59, 12, 31, $year + $offset);
... ...
... ... @@ -176,7 +176,7 @@ table.table-template {
.is-dialog #main {
background: #fff;
}
.is-dialog form label {
form.form-horizontal .control-label {
font-weight: normal;
}
.user-panel > .image img {
... ... @@ -442,14 +442,6 @@ table.table-template {
#treeview .jstree-children:after {
clear: both;
}
#treeview .jstree-children:before,
#treeview .jstree-children:after {
content: " ";
display: table;
}
#treeview .jstree-children:after {
clear: both;
}
#treeview .jstree-themeicon {
display: none;
}
... ... @@ -499,6 +491,19 @@ table.table-template {
.bootstrap-table .fixed-table-toolbar .dropdown-menu {
overflow: auto;
}
.toolbar {
margin-top: 10px;
margin-bottom: 10px;
}
.fixed-table-toolbar .bs-bars,
.fixed-table-toolbar .columns,
.fixed-table-toolbar .search {
line-height: inherit;
}
.fixed-table-toolbar .toolbar {
margin-top: 0;
margin-bottom: 0;
}
.bootstrap-table table tbody tr:first-child td .bs-checkbox {
vertical-align: middle;
}
... ... @@ -687,11 +692,6 @@ table.table-template {
.layui-layer-fast .layui-layer-setwin .layui-layer-close2:hover:after {
display: none;
}
@media (min-width: 768px) {
.form-inline .form-control {
padding-right: 20px;
}
}
.n-bootstrap .input-group > .n-right {
position: absolute;
}
... ...
... ... @@ -923,7 +923,7 @@ a:focus {
border-color: #eee;
}
.dropdown-menu > li > a {
color: #777;
/*color: #777;*/
}
.dropdown-menu > li > a > .glyphicon,
.dropdown-menu > li > a > .fa,
... ... @@ -1242,6 +1242,43 @@ a:focus {
background: #fff;
}
}
.dropdown-submenu {
position: relative;
}
.dropdown-submenu > .dropdown-menu {
top: 0;
left: 100%;
margin-top: -6px;
margin-left: -1px;
border-radius: 3px 0 3px 3px;
}
.dropdown-submenu:hover > .dropdown-menu {
display: block;
}
.dropdown-submenu:hover > a:after {
border-left-color: #fff;
}
.dropdown-submenu > a:after {
display: block;
content: " ";
float: right;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 5px 0 5px 5px;
border-left-color: #ccc;
margin-top: 5px;
margin-right: -10px;
}
.dropdown-submenu.pull-left {
float: none;
}
.dropdown-submenu.pull-left > .dropdown-menu {
left: -100%;
margin-left: 10px;
border-radius: 3px 0 3px 3px;
}
/*
* Component: Form
* ---------------
... ... @@ -2658,14 +2695,6 @@ table.text-center th {
text-align: right;
}
/*
* Component: Label
* ----------------
*/
.label-default {
background-color: #d2d6de;
color: #444;
}
/*
* Component: Direct Chat
* ----------------------
*/
... ... @@ -4936,56 +4965,6 @@ fieldset[disabled] .btn-yahoo.active {
.select2-container .select2-selection--single .select2-selection__rendered {
padding-right: 10px;
}
span.twitter-typeahead {
width: 100%;
}
span.twitter-typeahead .tt-menu,
span.twitter-typeahead .tt-dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
list-style: none;
font-size: 14px;
background-color: #ffffff;
border: 1px solid #cccccc;
border: 1px solid rgba(0, 0, 0, 0.15);
background-clip: padding-box;
cursor: pointer;
font-size: 12px;
border-radius: 0;
}
span.twitter-typeahead .tt-menu .tt-suggestion,
span.twitter-typeahead .tt-dropdown-menu .tt-suggestion {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: 1.428571429;
color: #333333;
white-space: nowrap;
}
span.twitter-typeahead .tt-menu .tt-suggestion:hover,
span.twitter-typeahead .tt-dropdown-menu .tt-suggestion:hover,
span.twitter-typeahead .tt-menu .tt-suggestion:focus,
span.twitter-typeahead .tt-dropdown-menu .tt-suggestion:focus {
color: #ffffff;
text-decoration: none;
outline: 0;
background-color: #428bca;
}
span.twitter-typeahead .tt-menu li.notfound,
span.twitter-typeahead .tt-dropdown-menu li.notfound {
text-indent: 10px;
}
.bootstrap-tagsinput {
border-radius: 0!important;
}
/*
* General: Miscellaneous
* ----------------------
... ... @@ -5064,11 +5043,6 @@ span.twitter-typeahead .tt-dropdown-menu li.notfound {
.alert-error,
.alert-warning,
.alert-info,
.label-danger,
.label-info,
.label-warning,
.label-primary,
.label-success,
.modal-primary .modal-body,
.modal-primary .modal-header,
.modal-primary .modal-footer,
... ... @@ -5100,21 +5074,18 @@ span.twitter-typeahead .tt-dropdown-menu li.notfound {
.callout.callout-danger,
.alert-danger,
.alert-error,
.label-danger,
.modal-danger .modal-body {
background-color: #e74c3c !important;
}
.bg-yellow,
.callout.callout-warning,
.alert-warning,
.label-warning,
.modal-warning .modal-body {
background-color: #f39c12 !important;
}
.bg-aqua,
.callout.callout-info,
.alert-info,
.label-info,
.modal-info .modal-body {
background-color: #3498db !important;
}
... ... @@ -5122,14 +5093,12 @@ span.twitter-typeahead .tt-dropdown-menu li.notfound {
background-color: #0073b7 !important;
}
.bg-light-blue,
.label-primary,
.modal-primary .modal-body {
background-color: #3c8dbc !important;
}
.bg-green,
.callout.callout-success,
.alert-success,
.label-success,
.modal-success .modal-body {
background-color: #18bc9c !important;
}
... ...
... ... @@ -111,28 +111,28 @@ define(['fast', 'moment'], function (Fast, Moment) {
Toastr.options.positionClass = Config.controllername === 'index' ? "toast-top-right-index" : "toast-top-right";
//点击包含.btn-dialog的元素时弹出dialog
$(document).on('click', '.btn-dialog,.dialogit', function (e) {
e.preventDefault();
var options = $(this).data() || {};
Backend.api.open(Backend.api.replaceids(this, $(this).attr('href')), $(this).attr('title'), options);
return false;
});
//点击包含.btn-addtabs的元素时新增选项卡
$(document).on('click', '.btn-addtabs,.addtabsit', function (e) {
e.preventDefault();
Backend.api.addtabs(Backend.api.replaceids(this, $(this).attr('href')), $(this).attr("title"));
return false;
});
//点击包含.btn-ajax的元素时发送Ajax请求
$(document).on('click', '.btn-ajax,.ajaxit', function (e) {
e.preventDefault();
var options = $(this).data();
if (typeof options.url === 'undefined' && $(this).attr("href")) {
options.url = $(this).attr("href");
}
options.url = Backend.api.replaceids(this, options.url);
Backend.api.ajax(options);
return false;
});
//修复含有fixed-footer类的body边距
if ($(".fixed-footer").size() > 0) {
$(document.body).css("padding-bottom", $(".fixed-footer").height());
$(document.body).css("padding-bottom", $(".fixed-footer").outerHeight());
}
//修复不在iframe时layer-footer隐藏的问题
if ($(".layer-footer").size() > 0 && self === top) {
... ...
... ... @@ -50,28 +50,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
location.reload();
});
$(document).on("click", ".fieldlist .append", function () {
var rel = parseInt($(this).closest("dl").attr("rel")) + 1;
var name = $(this).closest("dl").data("name");
$(this).closest("dl").attr("rel", rel);
$('<dd class="form-inline"><input type="text" name="' + name + '[field][' + rel + ']" class="form-control" value="" size="10" /> <input type="text" name="' + name + '[value][' + rel + ']" class="form-control" value="" size="40" /> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></dd>').insertBefore($(this).parent());
});
$(document).on("click", ".fieldlist dd .btn-remove", function () {
$(this).parent().remove();
});
//拖拽排序
require(['dragsort'], function () {
//绑定拖动排序
$("dl.fieldlist").dragsort({
itemSelector: 'dd',
dragSelector: ".btn-dragsort",
dragEnd: function () {
},
placeHolderTemplate: "<dd></dd>"
});
});
//切换显示隐藏变量字典列表
$(document).on("change", "form#add-form select[name='row[type]']", function (e) {
$("#add-content-container").toggleClass("hide", ['select', 'selects', 'checkbox', 'radio'].indexOf($(this).val()) > -1 ? false : true);
... ...
... ... @@ -245,7 +245,7 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
$("body").addClass(cls);
store('skin', cls);
var cssfile = Backend.api.cdnurl("/assets/css/skins/" + cls + ".css");
var cssfile = Config.site.cdnurl + "/assets/css/skins/" + cls + ".css";
$('head').append('<link rel="stylesheet" href="' + cssfile + '" type="text/css" />');
}
return false;
... ...
... ... @@ -321,10 +321,20 @@
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initHeader = BootstrapTable.prototype.initHeader,
_initToolbar = BootstrapTable.prototype.initToolbar,
_load = BootstrapTable.prototype.load,
_initSearch = BootstrapTable.prototype.initSearch;
BootstrapTable.prototype.initHeader = function () {
_initHeader.apply(this, Array.prototype.slice.apply(arguments));
this.$header.find('th[data-field]').each(function (i) {
var column = $(this).data();
if (typeof column['width'] !== 'undefined') {
$(this).css("min-width", column['width']);
}
});
};
BootstrapTable.prototype.initToolbar = function () {
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
... ...
... ... @@ -6823,28 +6823,28 @@ define('backend',['fast', 'moment'], function (Fast, Moment) {
Toastr.options.positionClass = Config.controllername === 'index' ? "toast-top-right-index" : "toast-top-right";
//点击包含.btn-dialog的元素时弹出dialog
$(document).on('click', '.btn-dialog,.dialogit', function (e) {
e.preventDefault();
var options = $(this).data() || {};
Backend.api.open(Backend.api.replaceids(this, $(this).attr('href')), $(this).attr('title'), options);
return false;
});
//点击包含.btn-addtabs的元素时新增选项卡
$(document).on('click', '.btn-addtabs,.addtabsit', function (e) {
e.preventDefault();
Backend.api.addtabs(Backend.api.replaceids(this, $(this).attr('href')), $(this).attr("title"));
return false;
});
//点击包含.btn-ajax的元素时发送Ajax请求
$(document).on('click', '.btn-ajax,.ajaxit', function (e) {
e.preventDefault();
var options = $(this).data();
if (typeof options.url === 'undefined' && $(this).attr("href")) {
options.url = $(this).attr("href");
}
options.url = Backend.api.replaceids(this, options.url);
Backend.api.ajax(options);
return false;
});
//修复含有fixed-footer类的body边距
if ($(".fixed-footer").size() > 0) {
$(document.body).css("padding-bottom", $(".fixed-footer").height());
$(document.body).css("padding-bottom", $(".fixed-footer").outerHeight());
}
//修复不在iframe时layer-footer隐藏的问题
if ($(".layer-footer").size() > 0 && self === top) {
... ... @@ -9154,7 +9154,7 @@ return d.keepInvalid=a,l},l.datepickerInput=function(a){if(0===arguments.length)
value = $("[name='" + name + "']:checked", that.$commonsearch).val();
}
} else {
value = (typeof vObjCol.process === 'function') ? vObjCol.process(obj.val()) : (sym == 'LIKE %...%' ? obj.val().replace(/\*/g, '%') : obj.val());
value = (vObjCol && typeof vObjCol.process === 'function') ? vObjCol.process(obj.val()) : (sym == 'LIKE %...%' ? obj.val().replace(/\*/g, '%') : obj.val());
}
if (removeempty && value == '' && sym.indexOf("NULL") == -1) {
return true;
... ... @@ -9229,10 +9229,20 @@ return d.keepInvalid=a,l},l.datepickerInput=function(a){if(0===arguments.length)
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
var BootstrapTable = $.fn.bootstrapTable.Constructor,
_initHeader = BootstrapTable.prototype.initHeader,
_initToolbar = BootstrapTable.prototype.initToolbar,
_load = BootstrapTable.prototype.load,
_initSearch = BootstrapTable.prototype.initSearch;
BootstrapTable.prototype.initHeader = function () {
_initHeader.apply(this, Array.prototype.slice.apply(arguments));
this.$header.find('th[data-field]').each(function (i) {
var column = $(this).data();
if (typeof column['width'] !== 'undefined') {
$(this).css("min-width", column['width']);
}
});
};
BootstrapTable.prototype.initToolbar = function () {
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
... ... @@ -9419,12 +9429,12 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
defaults: {
url: '',
sidePagination: 'server',
method: 'get',
toolbar: "#toolbar",
search: true,
method: 'get', //请求方法
toolbar: ".toolbar", //工具栏
search: true, //是否启用快速搜索
cache: false,
commonSearch: true,
searchFormVisible: false,
commonSearch: true, //是否启用通用搜索
searchFormVisible: false, //是否始终显示搜索表单
titleForm: '', //为空则不显示标题,不定义默认显示:普通搜索
idTable: 'commonTable',
showExport: true,
... ... @@ -9433,7 +9443,8 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
pageSize: 10,
pageList: [10, 25, 50, 'All'],
pagination: true,
clickToSelect: true,
clickToSelect: true, //是否启用点击选中
singleSelect: false, //是否启用单选
showRefresh: false,
locale: 'zh-CN',
showToggle: true,
... ... @@ -9445,15 +9456,16 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
paginationPreText: __("Previous"),
paginationNextText: __("Next"),
paginationLastText: __("Last"),
mobileResponsive: true,
cardView: true,
checkOnInit: true,
escape: true,
mobileResponsive: true, //是否自适应移动端
cardView: false, //卡片视图
checkOnInit: true, //是否在初始化时判断
escape: true, //是否对内容进行转义
extend: {
index_url: '',
add_url: '',
edit_url: '',
del_url: '',
import_url: '',
multi_url: '',
dragsort_url: 'ajax/weigh',
}
... ... @@ -9470,6 +9482,7 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
addbtn: '.btn-add',
editbtn: '.btn-edit',
delbtn: '.btn-del',
importbtn: '.btn-import',
multibtn: '.btn-multi',
disabledbtn: '.btn-disabled',
editonebtn: '.btn-editone',
... ... @@ -9569,6 +9582,20 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
var ids = Table.api.selectedids(table);
Fast.api.open(options.extend.add_url + (ids.length > 0 ? (options.extend.add_url.match(/(\?|&)+/) ? "&ids=" : "/ids/") + ids.join(",") : ''), __('Add'), $(this).data() || {});
});
// 导入按钮事件
if ($(Table.config.importbtn, toolbar).size() > 0) {
require(['upload'], function (Upload) {
console.log($(Table.config.importbtn, toolbar));
Upload.api.plupload($(Table.config.importbtn, toolbar), function (data, ret) {
Fast.api.ajax({
url: options.extend.import_url,
data: {file: data.url},
}, function () {
table.bootstrapTable('refresh');
});
});
});
}
// 批量编辑按钮事件
$(toolbar).on('click', Table.config.editbtn, function () {
var ids = Table.api.selectedids(table);
... ... @@ -9675,11 +9702,13 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
operate: {
'click .btn-editone': function (e, value, row, index) {
e.stopPropagation();
e.preventDefault();
var options = $(this).closest('table').bootstrapTable('getOptions');
Fast.api.open(options.extend.edit_url + (options.extend.edit_url.match(/(\?|&)+/) ? "&ids=" : "/ids/") + row[options.pk], __('Edit'), $(this).data() || {});
},
'click .btn-delone': function (e, value, row, index) {
e.stopPropagation();
e.preventDefault();
var that = this;
var top = $(that).offset().top - $(window).scrollTop();
var left = $(that).offset().left - $(window).scrollLeft() - 260;
... ... @@ -9712,17 +9741,17 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
return '<i class="' + value + '"></i> ' + value;
},
image: function (value, row, index) {
value=value?value:'/assets/img/blank.gif';
value = value ? value : '/assets/img/blank.gif';
var classname = typeof this.classname !== 'undefined' ? this.classname : 'img-sm img-center';
return '<img class="' + classname + '" src="' + Fast.api.cdnurl(value) + '" />';
},
images: function (value, row, index) {
value = value.toString();
var classname = typeof this.classname !== 'undefined' ? this.classname : 'img-sm img-center';
var arr = value.split(',');
var arr = value.toString().split(',');
var html = [];
$.each(arr, function (i, value) {
value=value?value:'/assets/img/blank.gif';
value = value ? value : '/assets/img/blank.gif';
html.push('<img class="' + classname + '" src="' + Fast.api.cdnurl(value) + '" />');
});
return html.join(' ');
... ... @@ -9763,9 +9792,12 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
if (typeof this.custom !== 'undefined') {
colorArr = $.extend(colorArr, this.custom);
}
if (typeof this.customField !== 'undefined' && typeof row[this.customField] !== 'undefined') {
value = row[this.customField];
}
//渲染Flag
var html = [];
var arr = value.split(',');
var arr = value.toString().split(',');
$.each(arr, function (i, value) {
value = value.toString();
if (value == '')
... ... @@ -9789,7 +9821,7 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
// 默认按钮组
var buttons = $.extend([], this.buttons || []);
buttons.push({name: 'dragsort', icon: 'fa fa-arrows', classname: 'btn btn-xs btn-primary btn-dragsort'});
buttons.push({name: 'edit', icon: 'fa fa-pencil', classname: 'btn btn-xs btn-success btn-editone'});
buttons.push({name: 'edit', icon: 'fa fa-pencil', classname: 'btn btn-xs btn-success btn-editone', url: options.extend.edit_url});
buttons.push({name: 'del', icon: 'fa fa-trash', classname: 'btn btn-xs btn-danger btn-delone'});
var html = [];
var url, classname, icon, text, title, extend;
... ... @@ -9920,6 +9952,40 @@ define('upload',['jquery', 'bootstrap', 'plupload', 'template'], function ($, un
previewtpl: '<li class="col-xs-3"><a href="<%=fullurl%>" data-url="<%=url%>" target="_blank" class="thumbnail"><img src="<%=fullurl%>" class="img-responsive"></a><a href="javascript:;" class="btn btn-danger btn-xs btn-trash"><i class="fa fa-trash"></i></a></li>',
},
events: {
//初始化完成
onPostInit: function (up) {
},
//文件添加成功后
onFileAdded: function (up, files) {
var button = up.settings.button;
$(button).data("bakup-html", $(button).html());
var maxcount = $(button).data("maxcount");
var input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
maxcount = typeof maxcount !== "undefined" ? maxcount : 0;
if (maxcount > 0 && input_id) {
var inputObj = $("#" + input_id);
if (inputObj.size() > 0) {
var value = $.trim(inputObj.val());
var nums = value === '' ? 0 : value.split(/\,/).length;
var remains = maxcount - nums;
if (files.length > remains) {
for (var i = 0; i < files.length; i++) {
up.removeFile(files[i]);
}
Toastr.error(__('You can upload up to %d file%s', remains));
return false;
}
}
}
//添加后立即上传
setTimeout(function () {
up.start();
}, 1);
},
onBeforeUpload: function (up, file) {
console.log("before", up.settings);
},
//上传成功的回调
onUploadSuccess: function (ret, onUploadSuccess, button) {
var data = typeof ret.data !== 'undefined' ? ret.data : null;
... ... @@ -9999,6 +10065,9 @@ define('upload',['jquery', 'bootstrap', 'plupload', 'template'], function ($, un
plupload: function (element, onUploadSuccess, onUploadError) {
element = typeof element === 'undefined' ? Upload.config.classname : element;
$(element, Upload.config.container).each(function () {
if ($(this).attr("initialized")) {
return true;
}
$(this).attr("initialized", true);
var that = this;
var id = $(this).prop("id");
... ... @@ -10016,7 +10085,7 @@ define('upload',['jquery', 'bootstrap', 'plupload', 'template'], function ($, un
//上传URL
url = url ? url : Config.upload.uploadurl;
url = Fast.api.fixurl(url);
//最大可上传
//最大可上传文件大小
maxsize = typeof maxsize !== "undefined" ? maxsize : Config.upload.maxsize;
//文件类型
mimetype = typeof mimetype !== "undefined" ? mimetype : Config.upload.mimetype;
... ... @@ -10024,6 +10093,17 @@ define('upload',['jquery', 'bootstrap', 'plupload', 'template'], function ($, un
multipart = typeof multipart !== "undefined" ? multipart : Config.upload.multipart;
//是否支持批量上传
multiple = typeof multiple !== "undefined" ? multiple : Config.upload.multiple;
var mimetypeArr = new Array();
//支持后缀和Mimetype格式,以,分隔
if (mimetype && mimetype !== "*" && mimetype.indexOf("/") === -1)
{
var tempArr = mimetype.split(',');
for (var i = 0; i < tempArr.length; i++)
{
mimetypeArr.push({title: __('Files'), extensions: tempArr[i]});
}
mimetype = mimetypeArr;
}
//生成Plupload实例
Upload.list[id] = new Plupload.Uploader({
runtimes: 'html5,flash,silverlight,html4',
... ... @@ -10034,22 +10114,14 @@ define('upload',['jquery', 'bootstrap', 'plupload', 'template'], function ($, un
silverlight_xap_url: '/assets/libs/plupload/js/Moxie.xap',
filters: {
max_file_size: maxsize,
mime_types: mimetype
mime_types: mimetype,
},
url: url,
multipart_params: multipart,
multipart_params: $.isArray(multipart) ? {} : multipart,
init: {
PostInit: function () {
},
FilesAdded: function (up, files) {
var button = up.settings.button;
$(button).data("bakup-html", $(button).html());
//添加后立即上传
setTimeout(function () {
up.start();
}, 1);
},
PostInit: Upload.events.onPostInit,
FilesAdded: Upload.events.onFileAdded,
BeforeUpload: Upload.events.onBeforeUpload,
UploadProgress: function (up, file) {
var button = up.settings.button;
//这里可以改成其它的表现形式
... ... @@ -10060,18 +10132,18 @@ define('upload',['jquery', 'bootstrap', 'plupload', 'template'], function ($, un
var button = up.settings.button;
//还原按钮文字及状态
$(button).prop("disabled", false).html($(button).data("bakup-html"));
var ret = Upload.events.onUploadResponse(info.response);
var ret = Upload.events.onUploadResponse(info.response, info, up, file);
if (ret.code === 1) {
Upload.events.onUploadSuccess(ret, onUploadSuccess, button);
Upload.events.onUploadSuccess(ret, onUploadSuccess, button, up, file);
} else {
Upload.events.onUploadError(ret, onUploadError, button);
Upload.events.onUploadError(ret, onUploadError, button, up, file);
}
},
Error: function (up, err) {
var button = up.settings.button;
$(button).prop("disabled", false).html($(button).data("bakup-html"));
var ret = {code: err.code, msg: err.message, data: null};
Upload.events.onUploadError(ret, onUploadError, button);
Upload.events.onUploadError(ret, onUploadError, button, up, null);
}
},
onUploadSuccess: onUploadSuccess,
... ... @@ -10106,7 +10178,7 @@ define('upload',['jquery', 'bootstrap', 'plupload', 'template'], function ($, un
$("#" + preview_id).append(html);
});
});
$("#" + input_id).trigger("keyup");
$("#" + input_id).trigger("change");
}
if (preview_id) {
// 监听事件
... ... @@ -12455,6 +12527,8 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
},
events: {
validator: function (form, success, error, submit) {
if (!form.is("form"))
return;
//绑定表单事件
form.validator($.extend({
validClass: 'has-success',
... ... @@ -12475,8 +12549,13 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
return $msgbox;
},
valid: function (ret) {
var that = this, submitBtn = $(".layer-footer [type=submit]", form);
that.holdSubmit();
$(".layer-footer [type=submit]", form).addClass("disabled");
//验证通过提交表单
Form.api.submit($(ret), function (data, ret) {
that.holdSubmit(false);
submitBtn.removeClass("disabled");
if (typeof success === 'function') {
if (!success.call($(this), data, ret)) {
return false;
... ... @@ -12488,13 +12567,21 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
parent.$(".btn-refresh").trigger("click");
var index = parent.Layer.getFrameIndex(window.name);
parent.Layer.close(index);
}, error, submit);
}, function (data, ret) {
that.holdSubmit(false);
submitBtn.removeClass("disabled");
if (typeof error === 'function') {
if (!error.call($(this), data, ret)) {
return false;
}
}
}, submit);
return false;
}
}, form.data("validator-options") || {}));
//移除提交按钮的disabled类
$(".layer-footer .btn.disabled", form).removeClass("disabled");
$(".layer-footer [type=submit],.fixed-footer [type=submit],.normal-footer [type=submit]", form).removeClass("disabled");
},
selectpicker: function (form) {
//绑定select元素事件
... ... @@ -12563,27 +12650,41 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
plupload: function (form) {
//绑定plupload上传元素事件
if ($(".plupload", form).size() > 0) {
Upload.api.plupload();
Upload.api.plupload($(".plupload", form));
}
},
faselect: function (form) {
//绑定fachoose选择附件事件
if ($(".fachoose", form).size() > 0) {
$(document).on('click', ".fachoose", function () {
$(".fachoose", form).on('click', function () {
var that = this;
var multiple = $(this).data("multiple") ? $(this).data("multiple") : false;
var mimetype = $(this).data("mimetype") ? $(this).data("mimetype") : '';
parent.Fast.api.open("general/attachment/select?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype, __('Choose'), {
callback: function (data) {
var input_id = $("#" + $(that).attr("id")).data("input-id");
if (data.multiple) {
var button = $("#" + $(that).attr("id"));
var maxcount = $(button).data("maxcount");
var input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
maxcount = typeof maxcount !== "undefined" ? maxcount : 0;
if (input_id && data.multiple) {
var urlArr = [];
var inputObj = $("#" + input_id);
if (inputObj.val() !== "") {
var value = $.trim(inputObj.val());
if (value !== "") {
urlArr.push(inputObj.val());
}
urlArr.push(data.url);
inputObj.val(urlArr.join(",")).trigger("change");
urlArr.push(data.url)
var result = urlArr.join(",");
if (maxcount > 0) {
var nums = value === '' ? 0 : value.split(/\,/).length;
var files = data.url !== "" ? data.url.split(/\,/) : [];
var remains = maxcount - nums;
if (files.length > remains) {
Toastr.error(__('You can choose up to %d file%s', remains));
return false;
}
}
inputObj.val(result).trigger("change");
} else {
$("#" + input_id).val(data.url).trigger("change");
}
... ... @@ -12593,6 +12694,31 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
});
}
},
fieldlist: function (form) {
if ($(".fieldlist", form).size() > 0) {
$(".fieldlist", form).on("click", ".append", function () {
var rel = parseInt($(this).closest("dl").attr("rel")) + 1;
var name = $(this).closest("dl").data("name");
$(this).closest("dl").attr("rel", rel);
$('<dd class="form-inline"><input type="text" name="' + name + '[field][' + rel + ']" class="form-control" value="" size="10" /> <input type="text" name="' + name + '[value][' + rel + ']" class="form-control" value="" size="40" /> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></dd>').insertBefore($(this).parent());
});
$(".fieldlist", form).on("click", "dd .btn-remove", function () {
$(this).parent().remove();
});
//拖拽排序
require(['dragsort'], function () {
//绑定拖动排序
$("dl.fieldlist", form).dragsort({
itemSelector: 'dd',
dragSelector: ".btn-dragsort",
dragEnd: function () {
},
placeHolderTemplate: "<dd></dd>"
});
});
}
},
bindevent: function (form) {
}
... ... @@ -12687,6 +12813,8 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
events.plupload(form);
events.faselect(form);
events.fieldlist(form);
},
custom: {}
},
... ... @@ -13292,7 +13420,7 @@ define("addtabs", function(){});
* @summary SelectPage
* @desc 基于jQuery及使用Bootstrap环境开发的,下拉列表带输入快速查找及结果分页展示的多功能选择器
* @file selectpage.js
* @version 2.6
* @version 2.7
* @author TerryZeng
* @contact https://terryz.github.io/
* @license MIT License
... ... @@ -13413,6 +13541,16 @@ define("addtabs", function(){});
* 修复单选模式下初始化项目的显示文本没有使用formatItem回调格式化的问题
* 修复单选模式存在初始化项目时,再打开下拉列表时,仅显示匹配的项目一条数据的问题
* 修复多选模式下,动态修改选中值selectPageRefresh功能无效
* 2017.09.12(v2.7)
* 增加eClear回调,单选模式下,清除按钮的功能回调
* 单选,多选模式下,输入框禁用或只读状态,不显示清除按钮
* 2017.09.23(v2.8)
* 调整部分样式
* 修复可视区域高度较小时,列表始终会向上展开的问题
* 分离键盘事件处理,对键盘输入精准控制
* 优化区域外点击处理
* 优化数据展示渲染效率
* 优化列表位置定位的准确性
*/
;
(function (factory) {
... ... @@ -13590,7 +13728,12 @@ define("addtabs", function(){});
* @type function
* @param removeCount 被移除的个数
*/
eTagRemove: undefined
eTagRemove: undefined,
/**
* 单选模式下,选中项目后的清除按钮功能回调
* @type function
*/
eClear: undefined
};
... ... @@ -13626,7 +13769,7 @@ define("addtabs", function(){});
/**
* 插件版本号
*/
SelectPage.version = '2.6';
SelectPage.version = '2.7';
/**
* 插件缓存内部对象的KEY
*/
... ... @@ -13908,6 +14051,8 @@ define("addtabs", function(){});
selected: 'sp_selected',
input_off: 'sp_input_off',
message_box: 'sp_message_box',
// 多选模式的禁用状态样式
disabled: 'sp_disabled',
button: 'sp_button',
btn_on: 'sp_btn_on',
... ... @@ -13965,8 +14110,14 @@ define("addtabs", function(){});
if (option.selectOnly)
$(elem.combo_input).prop('readonly', true);
elem.container = $(elem.combo_input).parent().addClass(this.css_class.container);
if ($(elem.combo_input).prop('disabled')) {
if (option.multiple)
$(elem.container).addClass(this.css_class.disabled);
else
$(elem.combo_input).addClass(this.css_class.input_off);
}
$(elem.container).width(orgWidth);
//$(elem.container).width(orgWidth);
elem.button = $('<div>').addClass(this.css_class.button);
//bootstrap风格的向下三角箭头
... ... @@ -14202,6 +14353,8 @@ define("addtabs", function(){});
};
$(self.elem.combo_input).keyup(function (e) {
self.processKey(self, e);
}).keydown(function (e) {
self.processControl(self, e);
}).focus(function (e) {
//增加输入框获得焦点后,显示数据列表
if ($(self.elem.result_area).is(':hidden')) {
... ... @@ -14214,6 +14367,8 @@ define("addtabs", function(){});
e.stopPropagation();
self.clearAll(self);
$(self.elem.clear_btn).remove();
if (self.option.eClear && $.isFunction(self.option.eClear))
self.option.eClear();
});
if (self.option.multiple) {
if (self.option.multipleControlbar) {
... ... @@ -14249,82 +14404,140 @@ define("addtabs", function(){});
};
/**
* @desc 插件整体的事件处理
* 插件之外区域的事件处理
*/
SelectPage.prototype.eWhole = function () {
var self = this;
//如果是点击了控件本身则不响应外部鼠标点击事件
$(self.elem.container).mousedown(function () {
var thisindex = $('div.sp_container').index(this);
var lastindex = $(document.body).data(SelectPage.objStatusIndex);
if (lastindex != undefined && thisindex != lastindex)
$(document.body).data(SelectPage.objStatusKey, false);
else
$(document.body).data(SelectPage.objStatusKey, true);
$(document.body).data(SelectPage.objStatusIndex, thisindex);
});
/*
//如果是点击了控件本身则不响应外部鼠标点击事件
$(self.elem.container).mousedown(function() {
var thisindex = $('div.sp_container').index(this);
var lastindex = $(document.body).data(SelectPage.objStatusIndex);
if(lastindex != undefined && thisindex != lastindex)
$(document.body).data(SelectPage.objStatusKey,false);
else
$(document.body).data(SelectPage.objStatusKey,true);
$(document.body).data(SelectPage.objStatusIndex,thisindex);
});
*/
//控件外部的鼠标点击事件处理
$(document).off('mousedown.selectPage').on('mousedown.selectPage', function (e) {
if ($(document.body).data(SelectPage.objStatusKey))
$(document.body).data(SelectPage.objStatusKey, false);
else {
//清除内容
var cleanContent = function (obj) {
$(obj.elem.combo_input).val('');
if (!obj.option.multiple)
$(obj.elem.hidden).val('');
obj.prop.selected_text = '';
};
//列表是打开的状态
$('div.' + self.css_class.container + '.' + self.css_class.container_open).each(function () {
var d = $('input.' + self.css_class.input, this).data(SelectPage.dataKey);
var ele = e.target || e.srcElement;
var sm = $(ele).closest('div.' + self.css_class.container);
//清除内容
var cleanContent = function (obj) {
$(obj.elem.combo_input).val('');
if (!obj.option.multiple)
$(obj.elem.hidden).val('');
obj.prop.selected_text = '';
};
//若控件已有选中的的项目,而文本输入框中清空了关键字,则清空控件已选中的项目
if (!$(d.elem.combo_input).val() && $(d.elem.hidden).val() && !d.option.multiple) {
d.prop.current_page = 1;//重置当前页为1
cleanContent(d);
d.hideResults(d);
return true;
}
//匹配项且高亮时,下拉分页控件失去焦点后,自动选择该项目
if ($('li', $(d.elem.results)).size() > 0) {
if (d.option.autoFillResult) {//打开自动内容填充功能
//若已有选中项目,则直接隐藏列表
if ($('li.sp_selected', $(d.elem.results)).size() > 0) {
//列表是打开的状态
$('div.' + self.css_class.container + '.' + self.css_class.container_open).each(function () {
if (this == sm[0])
return;
var d = $('input.' + self.css_class.input, this).data(SelectPage.dataKey);
//若控件已有选中的的项目,而文本输入框中清空了关键字,则清空控件已选中的项目
if (!$(d.elem.combo_input).val() && $(d.elem.hidden).val() && !d.option.multiple) {
d.prop.current_page = 1;//重置当前页为1
cleanContent(d);
d.hideResults(d);
return true;
}
//匹配项且高亮时,下拉分页控件失去焦点后,自动选择该项目
if ($('li', $(d.elem.results)).size() > 0) {
if (d.option.autoFillResult) {//打开自动内容填充功能
//若已有选中项目,则直接隐藏列表
if ($('li.sp_selected', $(d.elem.results)).size() > 0) {
d.hideResults(d);
} else if ($('li.sp_over', $(d.elem.results)).size() > 0) {
//若控件已有选中的值,则忽略高亮的项目
if ($(d.elem.hidden).val())
d.hideResults(d);
} else if ($('li.sp_over', $(d.elem.results)).size() > 0) {
//若控件已有选中的值,则忽略高亮的项目
if ($(d.elem.hidden).val())
d.hideResults(d);
//若没有已选中的项目,且列表中有高亮项目时,选中当前高亮的行
else
d.selectCurrentLine(d, true);
} else if (d.option.autoSelectFirst) {
//若控件已有选中的值,则忽略自动选择第一项的功能
if ($(d.elem.hidden).val())
d.hideResults(d);
else {
//对于没有选中,没有高亮的情况,若插件设置了自动选中第一项时,则选中第一项
d.nextLine(d);
//self.nextLine(self);
d.selectCurrentLine(d, true);
}
} else
//若没有已选中的项目,且列表中有高亮项目时,选中当前高亮的行
else
d.selectCurrentLine(d, true);
} else if (d.option.autoSelectFirst) {
//若控件已有选中的值,则忽略自动选择第一项的功能
if ($(d.elem.hidden).val())
d.hideResults(d);
else {
//对于没有选中,没有高亮的情况,若插件设置了自动选中第一项时,则选中第一项
d.nextLine(d);
//self.nextLine(self);
d.selectCurrentLine(d, true);
}
} else
d.hideResults(d);
} else {
//无匹配项目时,自动清空用户输入的关键词
if (d.option.noResultClean)
cleanContent(d);
else {
if (!d.option.multiple)
$(d.elem.hidden).val('');
}
} else
d.hideResults(d);
} else {
//无匹配项目时,自动清空用户输入的关键词
if (d.option.noResultClean)
cleanContent(d);
else {
if (!d.option.multiple)
$(d.elem.hidden).val('');
}
});
}
d.hideResults(d);
}
});
/*
if ($(document.body).data(SelectPage.objStatusKey)) $(document.body).data(SelectPage.objStatusKey,false);
else {
//清除内容
var cleanContent = function(obj){
$(obj.elem.combo_input).val('');
if(!obj.option.multiple) $(obj.elem.hidden).val('');
obj.prop.selected_text = '';
};
//列表是打开的状态
$('div.' + self.css_class.container + '.' + self.css_class.container_open).each(function(){
var d = $('input.'+self.css_class.input,this).data(SelectPage.dataKey);
//若控件已有选中的的项目,而文本输入框中清空了关键字,则清空控件已选中的项目
if(!$(d.elem.combo_input).val() && $(d.elem.hidden).val() && !d.option.multiple){
d.prop.current_page = 1;//重置当前页为1
cleanContent(d);
d.hideResults(d);
return true;
}
//匹配项且高亮时,下拉分页控件失去焦点后,自动选择该项目
if ($('li', $(d.elem.results)).size() > 0) {
if(d.option.autoFillResult) {//打开自动内容填充功能
//若已有选中项目,则直接隐藏列表
if ($('li.sp_selected', $(d.elem.results)).size() > 0) {
d.hideResults(d);
}else if($('li.sp_over', $(d.elem.results)).size() > 0){
//若控件已有选中的值,则忽略高亮的项目
if($(d.elem.hidden).val()) d.hideResults(d);
//若没有已选中的项目,且列表中有高亮项目时,选中当前高亮的行
else d.selectCurrentLine(d, true);
}else if(d.option.autoSelectFirst){
//若控件已有选中的值,则忽略自动选择第一项的功能
if($(d.elem.hidden).val()) d.hideResults(d);
else{
//对于没有选中,没有高亮的情况,若插件设置了自动选中第一项时,则选中第一项
d.nextLine(d);
//self.nextLine(self);
d.selectCurrentLine(d, true);
}
}else d.hideResults(d);
}else d.hideResults(d);
} else {
//无匹配项目时,自动清空用户输入的关键词
if (d.option.noResultClean) cleanContent(d);
else{
if(!d.option.multiple) $(d.elem.hidden).val('');
}
d.hideResults(d);
}
});
}
*/
});
};
... ... @@ -14489,11 +14702,33 @@ define("addtabs", function(){});
};
/**
* @desc 文本输入框键盘事件处理
* @desc 文本输入框键盘事件处理(普通字符输入处理)
* @param {Object} self - 插件内部对象
* @param {Object} e - 事件event对象
*/
SelectPage.prototype.processKey = function (self, e) {
if ($.inArray(e.keyCode, [37, 38, 39, 40, 27, 9, 13]) === -1) {
if (e.keyCode != 16)
self.setCssFocusedInput(self); // except Shift(16)
self.inputResize(self);
if ($.type(self.option.data) === 'string') {
self.prop.last_input_time = e.timeStamp;
setTimeout(function () {
if ((e.timeStamp - self.prop.last_input_time) === 0)
self.checkValue(self);
}, self.option.inputDelay * 1000);
} else {
self.checkValue(self);
}
}
}
/**
* @desc 文本输入框键盘事件处理(控制键处理)
* @param {Object} self - 插件内部对象
* @param {Object} e - 事件event对象
*/
SelectPage.prototype.processControl = function (self, e) {
if (($.inArray(e.keyCode, [37, 38, 39, 40, 27, 9]) > -1 && $(self.elem.result_area).is(':visible')) ||
($.inArray(e.keyCode, [13, 9]) > -1 && self.getCurrentLine(self))) {
e.preventDefault();
... ... @@ -14550,19 +14785,6 @@ define("addtabs", function(){});
self.hideResults(self);
break;
}
} else {
if (e.keyCode != 16)
self.setCssFocusedInput(self); // except Shift(16)
self.inputResize(self);
if ($.type(self.option.data) === 'string') {
self.prop.last_input_time = e.timeStamp;
setTimeout(function () {
if ((e.timeStamp - self.prop.last_input_time) === 0)
self.checkValue(self);
}, self.option.inputDelay * 1000);
} else {
self.checkValue(self);
}
}
};
... ... @@ -14625,7 +14847,7 @@ define("addtabs", function(){});
* @param {number} which_page_num - 目标页
*/
SelectPage.prototype.searchForDb = function (self, q_word, which_page_num) {
if (!self.option.eAjaxSuccess && $.isFunction(self.option.eAjaxSuccess))
if (!self.option.eAjaxSuccess || !$.isFunction(self.option.eAjaxSuccess))
self.hideResults(self);
/**
* 增加自定义查询参数
... ... @@ -15104,7 +15326,7 @@ define("addtabs", function(){});
* @param {Object} self - 插件内部对象
*/
SelectPage.prototype.calcResultsSize = function (self) {
$(self.elem.result_area).show(1, function () {
var rePosition = function () {
if ($(self.elem.container).css('position') === 'static') {
// position: static
var offset = $(self.elem.combo_input).offset();
... ... @@ -15136,14 +15358,16 @@ define("addtabs", function(){});
//输入框高度
var inputHeight = $(self.elem.container).outerHeight();
var left = (offset.left + listWidth) > docWidth ? -(listWidth - $(self.elem.container).outerWidth()) : defaultLeft;
//控件在当前可视区域中的高度
//控件在全文档范围中的实际TOP(非当前可视区域中的相对TOP)
var screenTop = offset.top;//$(self.elem.container).scrollTop();//offset.top - screenScrollTop;
var top = 0, dist = 5;//设置偏移量,让列表与输入框有5px的间距
//列表展开后的坐标高度
var listBottom = screenTop + inputHeight + listHeight + dist;
var hasOverflow = docHeight > viewHeight;
if ((hasOverflow && listBottom > (viewHeight + screenScrollTop)) || (!hasOverflow && listBottom > viewHeight)) {
if ((screenTop - screenScrollTop - dist > listHeight) &&
(hasOverflow && listBottom > (viewHeight + screenScrollTop)) ||
(!hasOverflow && listBottom > viewHeight)) {
//控件当前位置+控件高度+列表高度超过实际body高度
//列表则需要向上展示
top = -(listHeight + 1) - dist;
... ... @@ -15154,12 +15378,25 @@ define("addtabs", function(){});
$(self.elem.result_area).removeClass('shadowUp shadowDown').addClass('shadowDown');
top += dist;
}
$(self.elem.result_area).css({
/*
$(self.elem.result_area).css({
top : top + 'px',
left: left + 'px'
});
*/
return {
top: top + 'px',
left: left + 'px'
});
};
}
});
};
if ($(self.elem.result_area).is(':visible')) {
$(self.elem.result_area).css(rePosition());
} else {
$(self.elem.result_area).show(1, function () {
$(this).css(rePosition());
});
}
};
/**
... ... @@ -15309,7 +15546,7 @@ define("addtabs", function(){});
* 单选模式下选中项目后,显示清空按钮
*/
SelectPage.prototype.putClearButton = function () {
if (!this.option.multiple)
if (!this.option.multiple && !$(this.elem.combo_input).prop('disabled'))
$(this.elem.container).append(this.elem.clear_btn);
};
/**
... ... @@ -15410,10 +15647,13 @@ define("addtabs", function(){});
SelectPage.prototype.addNewTag = function (self, item) {
if (!self.option.multiple || !item)
return;
var tmp = self.template.tag.content;
var tmp = self.template.tag.content, tag;
tmp = tmp.replace(self.template.tag.textKey, item.text);
tmp = tmp.replace(self.template.tag.valueKey, item.value);
$(self.elem.combo_input).closest('li').before($(tmp));
tag = $(tmp);
if ($(self.elem.combo_input).prop('disabled'))
$('span.tag_close', tag).hide();
$(self.elem.combo_input).closest('li').before(tag);
};
/**
* @desc 多选模式下移除一个标签
... ... @@ -15649,3 +15889,4 @@ define("addtabs", function(){});
return this;
};
}));
... ...
... ... @@ -4,6 +4,8 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
},
events: {
validator: function (form, success, error, submit) {
if (!form.is("form"))
return;
//绑定表单事件
form.validator($.extend({
validClass: 'has-success',
... ... @@ -24,8 +26,13 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
return $msgbox;
},
valid: function (ret) {
var that = this, submitBtn = $(".layer-footer [type=submit]", form);
that.holdSubmit();
$(".layer-footer [type=submit]", form).addClass("disabled");
//验证通过提交表单
Form.api.submit($(ret), function (data, ret) {
that.holdSubmit(false);
submitBtn.removeClass("disabled");
if (typeof success === 'function') {
if (!success.call($(this), data, ret)) {
return false;
... ... @@ -37,13 +44,21 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
parent.$(".btn-refresh").trigger("click");
var index = parent.Layer.getFrameIndex(window.name);
parent.Layer.close(index);
}, error, submit);
}, function (data, ret) {
that.holdSubmit(false);
submitBtn.removeClass("disabled");
if (typeof error === 'function') {
if (!error.call($(this), data, ret)) {
return false;
}
}
}, submit);
return false;
}
}, form.data("validator-options") || {}));
//移除提交按钮的disabled类
$(".layer-footer .btn.disabled", form).removeClass("disabled");
$(".layer-footer [type=submit],.fixed-footer [type=submit],.normal-footer [type=submit]", form).removeClass("disabled");
},
selectpicker: function (form) {
//绑定select元素事件
... ... @@ -112,27 +127,41 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
plupload: function (form) {
//绑定plupload上传元素事件
if ($(".plupload", form).size() > 0) {
Upload.api.plupload();
Upload.api.plupload($(".plupload", form));
}
},
faselect: function (form) {
//绑定fachoose选择附件事件
if ($(".fachoose", form).size() > 0) {
$(document).on('click', ".fachoose", function () {
$(".fachoose", form).on('click', function () {
var that = this;
var multiple = $(this).data("multiple") ? $(this).data("multiple") : false;
var mimetype = $(this).data("mimetype") ? $(this).data("mimetype") : '';
parent.Fast.api.open("general/attachment/select?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype, __('Choose'), {
callback: function (data) {
var input_id = $("#" + $(that).attr("id")).data("input-id");
if (data.multiple) {
var button = $("#" + $(that).attr("id"));
var maxcount = $(button).data("maxcount");
var input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
maxcount = typeof maxcount !== "undefined" ? maxcount : 0;
if (input_id && data.multiple) {
var urlArr = [];
var inputObj = $("#" + input_id);
if (inputObj.val() !== "") {
var value = $.trim(inputObj.val());
if (value !== "") {
urlArr.push(inputObj.val());
}
urlArr.push(data.url);
inputObj.val(urlArr.join(",")).trigger("change");
urlArr.push(data.url)
var result = urlArr.join(",");
if (maxcount > 0) {
var nums = value === '' ? 0 : value.split(/\,/).length;
var files = data.url !== "" ? data.url.split(/\,/) : [];
var remains = maxcount - nums;
if (files.length > remains) {
Toastr.error(__('You can choose up to %d file%s', remains));
return false;
}
}
inputObj.val(result).trigger("change");
} else {
$("#" + input_id).val(data.url).trigger("change");
}
... ... @@ -142,6 +171,31 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
});
}
},
fieldlist: function (form) {
if ($(".fieldlist", form).size() > 0) {
$(".fieldlist", form).on("click", ".append", function () {
var rel = parseInt($(this).closest("dl").attr("rel")) + 1;
var name = $(this).closest("dl").data("name");
$(this).closest("dl").attr("rel", rel);
$('<dd class="form-inline"><input type="text" name="' + name + '[field][' + rel + ']" class="form-control" value="" size="10" /> <input type="text" name="' + name + '[value][' + rel + ']" class="form-control" value="" size="40" /> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></dd>').insertBefore($(this).parent());
});
$(".fieldlist", form).on("click", "dd .btn-remove", function () {
$(this).parent().remove();
});
//拖拽排序
require(['dragsort'], function () {
//绑定拖动排序
$("dl.fieldlist", form).dragsort({
itemSelector: 'dd',
dragSelector: ".btn-dragsort",
dragEnd: function () {
},
placeHolderTemplate: "<dd></dd>"
});
});
}
},
bindevent: function (form) {
}
... ... @@ -236,6 +290,8 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
events.plupload(form);
events.faselect(form);
events.fieldlist(form);
},
custom: {}
},
... ...
... ... @@ -4,7 +4,8 @@ require.config({
name: 'moment',
location: '../libs/moment',
main: 'moment'
}],
}
],
//在打包压缩时将会把include中的模块合并到主文件中
include: ['css', 'layer', 'toastr', 'fast', 'frontend'],
paths: {
... ... @@ -25,6 +26,7 @@ require.config({
'jquery': '../libs/jquery/dist/jquery.min',
'bootstrap': '../libs/bootstrap/dist/js/bootstrap.min',
'bootstrap-datetimepicker': '../libs/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min',
'bootstrap-daterangepicker': '../libs/bootstrap-daterangepicker/daterangepicker',
'bootstrap-select': '../libs/bootstrap-select/dist/js/bootstrap-select.min',
'bootstrap-select-lang': '../libs/bootstrap-select/dist/js/i18n/defaults-zh_CN',
'bootstrap-table': '../libs/bootstrap-table/dist/bootstrap-table.min',
... ... @@ -33,6 +35,7 @@ require.config({
'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN',
'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min',
'dragsort': '../libs/dragsort/jquery.dragsort',
'qrcode': '../libs/jquery-qrcode/jquery.qrcode.min',
'sortable': '../libs/Sortable/Sortable.min',
'addtabs': '../libs/jquery-addtabs/jquery.addtabs',
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
... ... @@ -47,9 +50,12 @@ require.config({
'cxselect': '../libs/jquery-cxselect/js/jquery.cxselect',
'template': '../libs/art-template/dist/template-native',
'selectpage': '../libs/selectpage/selectpage',
'citypicker': '../libs/city-picker/dist/js/city-picker.min',
'citypicker-data': '../libs/city-picker/dist/js/city-picker.data',
},
// shim依赖配置
shim: {
'addons': ['backend'],
'bootstrap': ['jquery'],
'bootstrap-table': {
deps: [
... ... @@ -111,6 +117,7 @@ require.config({
// 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'],
'validator-lang': ['validator-core'],
// 'selectpage': ['css!../libs/selectpage/selectpage.css'],
'citypicker': ['citypicker-data', 'css!../libs/city-picker/dist/css/city-picker.css']
},
baseUrl: requirejs.s.contexts._.config.config.site.cdnurl + '/assets/js/', //资源基础路径
map: {
... ... @@ -130,42 +137,24 @@ require(['jquery', 'bootstrap'], function ($, undefined) {
// 配置语言包的路径
var paths = {};
paths['lang'] = Config.moduleurl + '/ajax/lang?callback=define&controllername=' + Config.controllername;
// 避免目录冲突
paths['frontend/'] = 'frontend/';
paths['backend/'] = 'backend/';
require.config({paths: paths});
// 初始化
$(function () {
require(['frontend'], function (Module) {
// 对相对地址进行处理
$.ajaxSetup({
beforeSend: function (xhr, setting) {
setting.url = Module.api.fixurl(setting.url);
}
});
// 绑定ESC关闭窗口事件
$(window).keyup(function (e) {
if (e.keyCode == 27) {
if ($(".layui-layer").size() > 0) {
var index = 0;
$(".layui-layer").each(function () {
index = Math.max(index, parseInt($(this).attr("times")));
});
if (index) {
Module.api.layer.close(index);
}
}
require(['fast'], function (Fast) {
require(['frontend', 'addons'], function (Frontend, Addons) {
//加载相应模块
if (Config.jsname) {
require([Config.jsname], function (Controller) {
Controller[Config.actionname] != undefined && Controller[Config.actionname]();
}, function (e) {
console.error(e);
// 这里可捕获模块加载的错误
});
}
});
//加载相应模块
if (Config.jsname) {
require([Config.jsname], function (Controller) {
Controller[Config.actionname] != undefined && Controller[Config.actionname]();
}, function (e) {
// 这里可捕获模块加载的错误
});
}
});
});
});
... ...
... ... @@ -18,7 +18,8 @@ require.config({
name: 'moment',
location: '../libs/moment',
main: 'moment'
}],
}
],
//在打包压缩时将会把include中的模块合并到主文件中
include: ['css', 'layer', 'toastr', 'fast', 'frontend'],
paths: {
... ... @@ -39,6 +40,7 @@ require.config({
'jquery': '../libs/jquery/dist/jquery.min',
'bootstrap': '../libs/bootstrap/dist/js/bootstrap.min',
'bootstrap-datetimepicker': '../libs/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min',
'bootstrap-daterangepicker': '../libs/bootstrap-daterangepicker/daterangepicker',
'bootstrap-select': '../libs/bootstrap-select/dist/js/bootstrap-select.min',
'bootstrap-select-lang': '../libs/bootstrap-select/dist/js/i18n/defaults-zh_CN',
'bootstrap-table': '../libs/bootstrap-table/dist/bootstrap-table.min',
... ... @@ -47,6 +49,7 @@ require.config({
'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN',
'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min',
'dragsort': '../libs/dragsort/jquery.dragsort',
'qrcode': '../libs/jquery-qrcode/jquery.qrcode.min',
'sortable': '../libs/Sortable/Sortable.min',
'addtabs': '../libs/jquery-addtabs/jquery.addtabs',
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
... ... @@ -61,9 +64,12 @@ require.config({
'cxselect': '../libs/jquery-cxselect/js/jquery.cxselect',
'template': '../libs/art-template/dist/template-native',
'selectpage': '../libs/selectpage/selectpage',
'citypicker': '../libs/city-picker/dist/js/city-picker.min',
'citypicker-data': '../libs/city-picker/dist/js/city-picker.data',
},
// shim依赖配置
shim: {
'addons': ['backend'],
'bootstrap': ['jquery'],
'bootstrap-table': {
deps: [
... ... @@ -125,6 +131,7 @@ require.config({
// 'validator-core': ['css!../libs/nice-validator/dist/jquery.validator.css'],
'validator-lang': ['validator-core'],
// 'selectpage': ['css!../libs/selectpage/selectpage.css'],
'citypicker': ['citypicker-data', 'css!../libs/city-picker/dist/css/city-picker.css']
},
baseUrl: requirejs.s.contexts._.config.config.site.cdnurl + '/assets/js/', //资源基础路径
map: {
... ... @@ -144,42 +151,24 @@ require(['jquery', 'bootstrap'], function ($, undefined) {
// 配置语言包的路径
var paths = {};
paths['lang'] = Config.moduleurl + '/ajax/lang?callback=define&controllername=' + Config.controllername;
// 避免目录冲突
paths['frontend/'] = 'frontend/';
paths['backend/'] = 'backend/';
require.config({paths: paths});
// 初始化
$(function () {
require(['frontend'], function (Module) {
// 对相对地址进行处理
$.ajaxSetup({
beforeSend: function (xhr, setting) {
setting.url = Module.api.fixurl(setting.url);
}
});
// 绑定ESC关闭窗口事件
$(window).keyup(function (e) {
if (e.keyCode == 27) {
if ($(".layui-layer").size() > 0) {
var index = 0;
$(".layui-layer").each(function () {
index = Math.max(index, parseInt($(this).attr("times")));
});
if (index) {
Module.api.layer.close(index);
}
}
require(['fast'], function (Fast) {
require(['frontend', 'addons'], function (Frontend, Addons) {
//加载相应模块
if (Config.jsname) {
require([Config.jsname], function (Controller) {
Controller[Config.actionname] != undefined && Controller[Config.actionname]();
}, function (e) {
console.error(e);
// 这里可捕获模块加载的错误
});
}
});
//加载相应模块
if (Config.jsname) {
require([Config.jsname], function (Controller) {
Controller[Config.actionname] != undefined && Controller[Config.actionname]();
}, function (e) {
// 这里可捕获模块加载的错误
});
}
});
});
});
... ...
... ... @@ -5,12 +5,12 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
defaults: {
url: '',
sidePagination: 'server',
method: 'get',
toolbar: "#toolbar",
search: true,
method: 'get', //请求方法
toolbar: ".toolbar", //工具栏
search: true, //是否启用快速搜索
cache: false,
commonSearch: true,
searchFormVisible: false,
commonSearch: true, //是否启用通用搜索
searchFormVisible: false, //是否始终显示搜索表单
titleForm: '', //为空则不显示标题,不定义默认显示:普通搜索
idTable: 'commonTable',
showExport: true,
... ... @@ -19,7 +19,8 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
pageSize: 10,
pageList: [10, 25, 50, 'All'],
pagination: true,
clickToSelect: true,
clickToSelect: true, //是否启用点击选中
singleSelect: false, //是否启用单选
showRefresh: false,
locale: 'zh-CN',
showToggle: true,
... ... @@ -31,15 +32,16 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
paginationPreText: __("Previous"),
paginationNextText: __("Next"),
paginationLastText: __("Last"),
mobileResponsive: true,
cardView: true,
checkOnInit: true,
escape: true,
mobileResponsive: true, //是否自适应移动端
cardView: false, //卡片视图
checkOnInit: true, //是否在初始化时判断
escape: true, //是否对内容进行转义
extend: {
index_url: '',
add_url: '',
edit_url: '',
del_url: '',
import_url: '',
multi_url: '',
dragsort_url: 'ajax/weigh',
}
... ... @@ -56,6 +58,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
addbtn: '.btn-add',
editbtn: '.btn-edit',
delbtn: '.btn-del',
importbtn: '.btn-import',
multibtn: '.btn-multi',
disabledbtn: '.btn-disabled',
editonebtn: '.btn-editone',
... ... @@ -155,6 +158,20 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
var ids = Table.api.selectedids(table);
Fast.api.open(options.extend.add_url + (ids.length > 0 ? (options.extend.add_url.match(/(\?|&)+/) ? "&ids=" : "/ids/") + ids.join(",") : ''), __('Add'), $(this).data() || {});
});
// 导入按钮事件
if ($(Table.config.importbtn, toolbar).size() > 0) {
require(['upload'], function (Upload) {
console.log($(Table.config.importbtn, toolbar));
Upload.api.plupload($(Table.config.importbtn, toolbar), function (data, ret) {
Fast.api.ajax({
url: options.extend.import_url,
data: {file: data.url},
}, function () {
table.bootstrapTable('refresh');
});
});
});
}
// 批量编辑按钮事件
$(toolbar).on('click', Table.config.editbtn, function () {
var ids = Table.api.selectedids(table);
... ... @@ -261,11 +278,13 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
operate: {
'click .btn-editone': function (e, value, row, index) {
e.stopPropagation();
e.preventDefault();
var options = $(this).closest('table').bootstrapTable('getOptions');
Fast.api.open(options.extend.edit_url + (options.extend.edit_url.match(/(\?|&)+/) ? "&ids=" : "/ids/") + row[options.pk], __('Edit'), $(this).data() || {});
},
'click .btn-delone': function (e, value, row, index) {
e.stopPropagation();
e.preventDefault();
var that = this;
var top = $(that).offset().top - $(window).scrollTop();
var left = $(that).offset().left - $(window).scrollLeft() - 260;
... ... @@ -298,17 +317,17 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
return '<i class="' + value + '"></i> ' + value;
},
image: function (value, row, index) {
value=value?value:'/assets/img/blank.gif';
value = value ? value : '/assets/img/blank.gif';
var classname = typeof this.classname !== 'undefined' ? this.classname : 'img-sm img-center';
return '<img class="' + classname + '" src="' + Fast.api.cdnurl(value) + '" />';
},
images: function (value, row, index) {
value = value.toString();
var classname = typeof this.classname !== 'undefined' ? this.classname : 'img-sm img-center';
var arr = value.split(',');
var arr = value.toString().split(',');
var html = [];
$.each(arr, function (i, value) {
value=value?value:'/assets/img/blank.gif';
value = value ? value : '/assets/img/blank.gif';
html.push('<img class="' + classname + '" src="' + Fast.api.cdnurl(value) + '" />');
});
return html.join(' ');
... ... @@ -349,9 +368,12 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
if (typeof this.custom !== 'undefined') {
colorArr = $.extend(colorArr, this.custom);
}
if (typeof this.customField !== 'undefined' && typeof row[this.customField] !== 'undefined') {
value = row[this.customField];
}
//渲染Flag
var html = [];
var arr = value.split(',');
var arr = value.toString().split(',');
$.each(arr, function (i, value) {
value = value.toString();
if (value == '')
... ... @@ -375,7 +397,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
// 默认按钮组
var buttons = $.extend([], this.buttons || []);
buttons.push({name: 'dragsort', icon: 'fa fa-arrows', classname: 'btn btn-xs btn-primary btn-dragsort'});
buttons.push({name: 'edit', icon: 'fa fa-pencil', classname: 'btn btn-xs btn-success btn-editone'});
buttons.push({name: 'edit', icon: 'fa fa-pencil', classname: 'btn btn-xs btn-success btn-editone', url: options.extend.edit_url});
buttons.push({name: 'del', icon: 'fa fa-trash', classname: 'btn btn-xs btn-danger btn-delone'});
var html = [];
var url, classname, icon, text, title, extend;
... ...
... ... @@ -7,6 +7,40 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
previewtpl: '<li class="col-xs-3"><a href="<%=fullurl%>" data-url="<%=url%>" target="_blank" class="thumbnail"><img src="<%=fullurl%>" class="img-responsive"></a><a href="javascript:;" class="btn btn-danger btn-xs btn-trash"><i class="fa fa-trash"></i></a></li>',
},
events: {
//初始化完成
onPostInit: function (up) {
},
//文件添加成功后
onFileAdded: function (up, files) {
var button = up.settings.button;
$(button).data("bakup-html", $(button).html());
var maxcount = $(button).data("maxcount");
var input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
maxcount = typeof maxcount !== "undefined" ? maxcount : 0;
if (maxcount > 0 && input_id) {
var inputObj = $("#" + input_id);
if (inputObj.size() > 0) {
var value = $.trim(inputObj.val());
var nums = value === '' ? 0 : value.split(/\,/).length;
var remains = maxcount - nums;
if (files.length > remains) {
for (var i = 0; i < files.length; i++) {
up.removeFile(files[i]);
}
Toastr.error(__('You can upload up to %d file%s', remains));
return false;
}
}
}
//添加后立即上传
setTimeout(function () {
up.start();
}, 1);
},
onBeforeUpload: function (up, file) {
console.log("before", up.settings);
},
//上传成功的回调
onUploadSuccess: function (ret, onUploadSuccess, button) {
var data = typeof ret.data !== 'undefined' ? ret.data : null;
... ... @@ -86,6 +120,9 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
plupload: function (element, onUploadSuccess, onUploadError) {
element = typeof element === 'undefined' ? Upload.config.classname : element;
$(element, Upload.config.container).each(function () {
if ($(this).attr("initialized")) {
return true;
}
$(this).attr("initialized", true);
var that = this;
var id = $(this).prop("id");
... ... @@ -103,7 +140,7 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
//上传URL
url = url ? url : Config.upload.uploadurl;
url = Fast.api.fixurl(url);
//最大可上传
//最大可上传文件大小
maxsize = typeof maxsize !== "undefined" ? maxsize : Config.upload.maxsize;
//文件类型
mimetype = typeof mimetype !== "undefined" ? mimetype : Config.upload.mimetype;
... ... @@ -111,6 +148,17 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
multipart = typeof multipart !== "undefined" ? multipart : Config.upload.multipart;
//是否支持批量上传
multiple = typeof multiple !== "undefined" ? multiple : Config.upload.multiple;
var mimetypeArr = new Array();
//支持后缀和Mimetype格式,以,分隔
if (mimetype && mimetype !== "*" && mimetype.indexOf("/") === -1)
{
var tempArr = mimetype.split(',');
for (var i = 0; i < tempArr.length; i++)
{
mimetypeArr.push({title: __('Files'), extensions: tempArr[i]});
}
mimetype = mimetypeArr;
}
//生成Plupload实例
Upload.list[id] = new Plupload.Uploader({
runtimes: 'html5,flash,silverlight,html4',
... ... @@ -121,22 +169,14 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
silverlight_xap_url: '/assets/libs/plupload/js/Moxie.xap',
filters: {
max_file_size: maxsize,
mime_types: mimetype
mime_types: mimetype,
},
url: url,
multipart_params: multipart,
multipart_params: $.isArray(multipart) ? {} : multipart,
init: {
PostInit: function () {
},
FilesAdded: function (up, files) {
var button = up.settings.button;
$(button).data("bakup-html", $(button).html());
//添加后立即上传
setTimeout(function () {
up.start();
}, 1);
},
PostInit: Upload.events.onPostInit,
FilesAdded: Upload.events.onFileAdded,
BeforeUpload: Upload.events.onBeforeUpload,
UploadProgress: function (up, file) {
var button = up.settings.button;
//这里可以改成其它的表现形式
... ... @@ -147,18 +187,18 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
var button = up.settings.button;
//还原按钮文字及状态
$(button).prop("disabled", false).html($(button).data("bakup-html"));
var ret = Upload.events.onUploadResponse(info.response);
var ret = Upload.events.onUploadResponse(info.response, info, up, file);
if (ret.code === 1) {
Upload.events.onUploadSuccess(ret, onUploadSuccess, button);
Upload.events.onUploadSuccess(ret, onUploadSuccess, button, up, file);
} else {
Upload.events.onUploadError(ret, onUploadError, button);
Upload.events.onUploadError(ret, onUploadError, button, up, file);
}
},
Error: function (up, err) {
var button = up.settings.button;
$(button).prop("disabled", false).html($(button).data("bakup-html"));
var ret = {code: err.code, msg: err.message, data: null};
Upload.events.onUploadError(ret, onUploadError, button);
Upload.events.onUploadError(ret, onUploadError, button, up, null);
}
},
onUploadSuccess: onUploadSuccess,
... ... @@ -193,7 +233,7 @@ define(['jquery', 'bootstrap', 'plupload', 'template'], function ($, undefined,
$("#" + preview_id).append(html);
});
});
$("#" + input_id).trigger("keyup");
$("#" + input_id).trigger("change");
}
if (preview_id) {
// 监听事件
... ...
... ... @@ -17,17 +17,6 @@
@import url("../libs/nice-validator/dist/jquery.validator.css");
@import url("../libs/selectpage/selectpage.css");
.clearfix() {
&:before,
&:after {
content: " "; // 1
display: table; // 2
}
&:after {
clear: both;
}
}
@main-bg: #f1f4f6;
@panel-intro-bg: darken(@main-bg,3%);
@panel-nav-bg: #fff;
... ... @@ -210,10 +199,9 @@ table.table-template{
#main {
background:#fff;
}
form label {
font-weight: normal;
}
}
form.form-horizontal .control-label {
font-weight: normal;
}
.user-panel > .image img{
... ... @@ -533,6 +521,17 @@ table.table-template{
.bootstrap-table .fixed-table-toolbar .dropdown-menu{
overflow:auto;
}
.toolbar{
margin-top:10px;
margin-bottom:10px;
}
.fixed-table-toolbar .bs-bars, .fixed-table-toolbar .columns, .fixed-table-toolbar .search{
line-height:inherit;
}
.fixed-table-toolbar .toolbar{
margin-top:0;
margin-bottom:0;
}
.bootstrap-table table tbody tr:first-child td .bs-checkbox {
vertical-align: middle;
... ... @@ -721,12 +720,6 @@ table.table-template{
}
}
@media (min-width: 768px){
.form-inline .form-control {
padding-right:20px;
}
}
.n-bootstrap {
.input-group > .n-right {
position:absolute;
... ...
... ... @@ -35,7 +35,7 @@
@import "fastadmin/navs.less";
@import "fastadmin/products.less";
@import "fastadmin/table.less";
@import "fastadmin/labels.less";
//@import "fastadmin/labels.less";
@import "fastadmin/direct-chat.less";
@import "fastadmin/users-list.less";
@import "fastadmin/carousel.less";
... ... @@ -57,4 +57,4 @@
//Miscellaneous
//-------------
@import "fastadmin/miscellaneous.less";
@import "fastadmin/print.less";
@import "fastadmin/print.less";
\ No newline at end of file
... ...
... ... @@ -5,346 +5,387 @@
/*Dropdowns in general*/
.dropdown-menu {
box-shadow: none;
border-color: #eee;
> li > a {
color: #777;
}
> li > a > .glyphicon,
> li > a > .fa,
> li > a > .ion {
margin-right: 10px;
}
> li > a:hover {
background-color: lighten(@gray, 5%);
color: #333;
}
> .divider {
background-color: #eee;
}
box-shadow: none;
border-color: #eee;
> li > a {
/*color: #777;*/
}
> li > a > .glyphicon,
> li > a > .fa,
> li > a > .ion {
margin-right: 10px;
}
> li > a:hover {
background-color: lighten(@gray, 5%);
color: #333;
}
> .divider {
background-color: #eee;
}
}
//Navbar custom dropdown menu
.navbar-nav > .notifications-menu,
.navbar-nav > .messages-menu,
.navbar-nav > .tasks-menu {
//fix width and padding
> .dropdown-menu {
> li {
position: relative;
//fix width and padding
> .dropdown-menu {
> li {
position: relative;
}
width: 280px;
//Remove padding and margins
padding: 0 0 0 0;
margin: 0;
top: 100%;
}
width: 280px;
//Remove padding and margins
padding: 0 0 0 0;
margin: 0;
top: 100%;
}
//Define header class
> .dropdown-menu > li.header {
.border-radius(4px; 4px; 0; 0);
background-color: #ffffff;
padding: 7px 10px;
border-bottom: 1px solid #f4f4f4;
color: #444444;
font-size: 14px;
}
//Define footer class
> .dropdown-menu > li.footer > a {
.border-radius(0; 0; 4px; 4px);
font-size: 12px;
background-color: #fff;
padding: 7px 10px;
border-bottom: 1px solid #eeeeee;
color: #444 !important;
@media (max-width: @screen-sm-max) {
background: #fff !important;
color: #444 !important;
//Define header class
> .dropdown-menu > li.header {
.border-radius(4px; 4px; 0; 0);
background-color: #ffffff;
padding: 7px 10px;
border-bottom: 1px solid #f4f4f4;
color: #444444;
font-size: 14px;
}
text-align: center;
//Hover state
&:hover {
text-decoration: none;
font-weight: normal;
//Define footer class
> .dropdown-menu > li.footer > a {
.border-radius(0; 0; 4px; 4px);
font-size: 12px;
background-color: #fff;
padding: 7px 10px;
border-bottom: 1px solid #eeeeee;
color: #444 !important;
@media (max-width: @screen-sm-max) {
background: #fff !important;
color: #444 !important;
}
text-align: center;
//Hover state
&:hover {
text-decoration: none;
font-weight: normal;
}
}
}
//Clear inner menu padding and margins
> .dropdown-menu > li .menu {
max-height: 200px;
margin: 0;
padding: 0;
list-style: none;
overflow-x: hidden;
> li > a {
display: block;
white-space: nowrap; /* Prevent text from breaking */
border-bottom: 1px solid #f4f4f4;
// Hove state
&:hover {
background: #f4f4f4;
text-decoration: none;
}
//Clear inner menu padding and margins
> .dropdown-menu > li .menu {
max-height: 200px;
margin: 0;
padding: 0;
list-style: none;
overflow-x: hidden;
> li > a {
display: block;
white-space: nowrap; /* Prevent text from breaking */
border-bottom: 1px solid #f4f4f4;
// Hove state
&:hover {
background: #f4f4f4;
text-decoration: none;
}
}
}
}
}
//Notifications menu
.navbar-nav > .notifications-menu {
> .dropdown-menu > li .menu {
// Links inside the menu
> li > a {
color: #444444;
overflow: hidden;
text-overflow: ellipsis;
padding: 10px;
// Icons inside the menu
> .glyphicon,
> .fa,
> .ion {
width: 20px;
}
}
> .dropdown-menu > li .menu {
// Links inside the menu
> li > a {
color: #444444;
overflow: hidden;
text-overflow: ellipsis;
padding: 10px;
// Icons inside the menu
> .glyphicon,
> .fa,
> .ion {
width: 20px;
}
}
}
}
}
//Messages menu
.navbar-nav > .messages-menu {
//Inner menu
> .dropdown-menu > li .menu {
// Messages menu item
> li > a {
margin: 0;
//line-height: 20px;
padding: 10px 10px;
// User image
> div > img {
margin: auto 10px auto auto;
width: 40px;
height: 40px;
}
// Message heading
> h4 {
padding: 0;
margin: 0 0 0 45px;
color: #444444;
font-size: 15px;
position: relative;
// Small for message time display
> small {
color: #999999;
font-size: 10px;
position: absolute;
top: 0;
right: 0;
}
}
//Inner menu
> .dropdown-menu > li .menu {
// Messages menu item
> li > a {
margin: 0;
//line-height: 20px;
padding: 10px 10px;
// User image
> div > img {
margin: auto 10px auto auto;
width: 40px;
height: 40px;
}
// Message heading
> h4 {
padding: 0;
margin: 0 0 0 45px;
color: #444444;
font-size: 15px;
position: relative;
// Small for message time display
> small {
color: #999999;
font-size: 10px;
position: absolute;
top: 0;
right: 0;
}
}
> p {
margin: 0 0 0 45px;
font-size: 12px;
color: #888888;
}
.clearfix();
> p {
margin: 0 0 0 45px;
font-size: 12px;
color: #888888;
}
.clearfix();
}
}
}
}
//Tasks menu
.navbar-nav > .tasks-menu {
> .dropdown-menu > li .menu {
> li > a {
padding: 10px;
> h3 {
font-size: 14px;
padding: 0;
margin: 0 0 10px 0;
color: #666666;
}
> .progress {
padding: 0;
margin: 0;
}
> .dropdown-menu > li .menu {
> li > a {
padding: 10px;
> h3 {
font-size: 14px;
padding: 0;
margin: 0 0 10px 0;
color: #666666;
}
> .progress {
padding: 0;
margin: 0;
}
}
}
}
}
//User menu
.navbar-nav > .user-menu {
> .dropdown-menu {
.border-top-radius(0);
padding: 1px 0 0 0;
border-top-width: 0;
width: 280px;
&,
> .user-body {
.border-bottom-radius(4px);
}
// Header menu
> li.user-header {
height: 175px;
padding: 10px;
text-align: center;
// User image
> img {
z-index: 5;
height: 90px;
width: 90px;
border: 3px solid;
border-color: transparent;
border-color: rgba(255, 255, 255, 0.2);
}
> p {
z-index: 5;
color: #fff;
color: rgba(255, 255, 255, 0.8);
font-size: 17px;
//text-shadow: 2px 2px 3px #333333;
margin-top: 10px;
> small {
display: block;
font-size: 12px;
> .dropdown-menu {
.border-top-radius(0);
padding: 1px 0 0 0;
border-top-width: 0;
width: 280px;
&,
> .user-body {
.border-bottom-radius(4px);
}
// Header menu
> li.user-header {
height: 175px;
padding: 10px;
text-align: center;
// User image
> img {
z-index: 5;
height: 90px;
width: 90px;
border: 3px solid;
border-color: transparent;
border-color: rgba(255, 255, 255, 0.2);
}
> p {
z-index: 5;
color: #fff;
color: rgba(255, 255, 255, 0.8);
font-size: 17px;
//text-shadow: 2px 2px 3px #333333;
margin-top: 10px;
> small {
display: block;
font-size: 12px;
}
}
}
}
}
// Menu Body
> .user-body {
padding: 15px;
border-bottom: 1px solid #f4f4f4;
border-top: 1px solid #dddddd;
.clearfix();
a {
color: #444 !important;
@media (max-width: @screen-sm-max) {
background: #fff !important;
color: #444 !important;
// Menu Body
> .user-body {
padding: 15px;
border-bottom: 1px solid #f4f4f4;
border-top: 1px solid #dddddd;
.clearfix();
a {
color: #444 !important;
@media (max-width: @screen-sm-max) {
background: #fff !important;
color: #444 !important;
}
}
}
}
}
// Menu Footer
> .user-footer {
background-color: #f9f9f9;
padding: 10px;
.clearfix();
.btn-default {
color: #666666;
&:hover {
@media (max-width: @screen-sm-max) {
// Menu Footer
> .user-footer {
background-color: #f9f9f9;
}
padding: 10px;
.clearfix();
.btn-default {
color: #666666;
&:hover {
@media (max-width: @screen-sm-max) {
background-color: #f9f9f9;
}
}
}
}
}
}
}
.user-image {
float: left;
width: 25px;
height: 25px;
border-radius: 50%;
margin-right: 10px;
margin-top: -2px;
@media (max-width: @screen-xs-max) {
float: none;
margin-right: 0;
margin-top: -8px;
line-height: 10px;
.user-image {
float: left;
width: 25px;
height: 25px;
border-radius: 50%;
margin-right: 10px;
margin-top: -2px;
@media (max-width: @screen-xs-max) {
float: none;
margin-right: 0;
margin-top: -8px;
line-height: 10px;
}
}
}
}
/* Add fade animation to dropdown menus by appending
the class .animated-dropdown-menu to the .dropdown-menu ul (or ol)*/
.open:not(.dropup) > .animated-dropdown-menu {
backface-visibility: visible !important;
.animation(flipInX .7s both);
backface-visibility: visible !important;
.animation(flipInX .7s both);
}
@keyframes flipInX {
0% {
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
transition-timing-function: ease-in;
opacity: 0;
}
40% {
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
transition-timing-function: ease-in;
}
60% {
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
opacity: 1;
}
80% {
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
}
100% {
transform: perspective(400px);
}
0% {
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
transition-timing-function: ease-in;
opacity: 0;
}
40% {
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
transition-timing-function: ease-in;
}
60% {
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
opacity: 1;
}
80% {
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
}
100% {
transform: perspective(400px);
}
}
@-webkit-keyframes flipInX {
0% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
-webkit-transition-timing-function: ease-in;
opacity: 0;
}
40% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
-webkit-transition-timing-function: ease-in;
}
60% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
opacity: 1;
}
80% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
}
100% {
-webkit-transform: perspective(400px);
}
0% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
-webkit-transition-timing-function: ease-in;
opacity: 0;
}
40% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
-webkit-transition-timing-function: ease-in;
}
60% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
opacity: 1;
}
80% {
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
}
100% {
-webkit-transform: perspective(400px);
}
}
/* Fix dropdown menu in navbars */
.navbar-custom-menu > .navbar-nav {
> li {
position: relative;
> .dropdown-menu {
position: absolute;
right: 0;
left: auto;
> li {
position: relative;
> .dropdown-menu {
position: absolute;
right: 0;
left: auto;
}
}
}
}
@media (max-width: @screen-sm-max) {
.navbar-custom-menu > .navbar-nav {
float: right;
> li {
position: static;
> .dropdown-menu {
position: absolute;
right: 5%;
left: auto;
border: 1px solid #ddd;
background: #fff;
}
.navbar-custom-menu > .navbar-nav {
float: right;
> li {
position: static;
> .dropdown-menu {
position: absolute;
right: 5%;
left: auto;
border: 1px solid #ddd;
background: #fff;
}
}
}
}
.dropdown-submenu {
position: relative;
>.dropdown-menu {
top: 0;
left: 100%;
margin-top: -6px;
margin-left: -1px;
.border-radius(3px 0 3px 3px);
}
&:hover{
>.dropdown-menu {
display: block;
}
>a:after {
border-left-color: #fff;
}
}
}
>a:after {
display: block;
content: " ";
float: right;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 5px 0 5px 5px;
border-left-color: #ccc;
margin-top: 5px;
margin-right: -10px;
}
&.pull-left {
float: none;
>.dropdown-menu {
left: -100%;
margin-left: 10px;
.border-radius(3px 0 3px 3px);
}
}
}
... ...
... ... @@ -10,14 +10,3 @@
@import url("../libs/toastr/toastr.min.css");
@import url("../libs/layer/build/skin/default/layer.css");
.clearfix() {
&:before,
&:after {
content: " ";
display: table;
}
&:after {
clear: both;
}
}
... ...