mirror of https://gitee.com/karson/fastadmin.git
Merge branch '1.x' into develop
# Conflicts: # README.md # application/admin/command/Install/fastadmin.sql # application/admin/controller/Index.php # application/admin/controller/auth/Adminlog.php # application/common.php # application/common/controller/Backend.php # application/common/library/Email.php # application/config.php # application/index/controller/User.php # bower.json # composer.json # extend/fast/Http.php # public/assets/css/backend.min.css # public/assets/css/frontend.min.css # public/assets/js/backend/addon.js # public/assets/js/bootstrap-table-commonsearch.js # public/assets/js/fast.js # public/assets/js/frontend/user.js # public/assets/js/jquery.drag.min.js # public/assets/js/require-backend.js # public/assets/js/require-backend.min.js # public/assets/js/require-form.js # public/assets/js/require-frontend.min.js # public/assets/js/require-table.jspull/463/MERGE
commit
8caeeb8a78
|
|
@ -4,7 +4,7 @@ namespace app\admin\behavior;
|
|||
|
||||
class AdminLog
|
||||
{
|
||||
public function run(&$params)
|
||||
public function run(&$response)
|
||||
{
|
||||
//只记录POST请求的日志
|
||||
if (request()->isPost() && config('fastadmin.auto_record_log')) {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use think\exception\PDOException;
|
|||
|
||||
class Addon extends Command
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
|
|
@ -33,6 +32,7 @@ class Addon extends Command
|
|||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
\think\Config::load(dirname(dirname(__FILE__)) . DS . 'config.php');
|
||||
$name = $input->getOption('name') ?: '';
|
||||
$action = $input->getOption('action') ?: '';
|
||||
if (stripos($name, 'addons' . DS) !== false) {
|
||||
|
|
@ -82,7 +82,6 @@ class Addon extends Command
|
|||
$createTableSql = $result[0]['Create Table'];
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
|
||||
}
|
||||
|
||||
$data = [
|
||||
|
|
@ -177,12 +176,12 @@ class Addon extends Command
|
|||
if (!$info) {
|
||||
throw new Exception(__('Addon info file data incorrect'));
|
||||
}
|
||||
$infoname = isset($info['name']) ? $info['name'] : '';
|
||||
$infoname = $info['name'] ?? '';
|
||||
if (!$infoname || !preg_match("/^[a-z]+$/i", $infoname) || $infoname != $name) {
|
||||
throw new Exception(__('Addon info name incorrect'));
|
||||
}
|
||||
|
||||
$infoversion = isset($info['version']) ? $info['version'] : '';
|
||||
$infoversion = $info['version'] ?? '';
|
||||
if (!$infoversion || !preg_match("/^\d+\.\d+\.\d+$/i", $infoversion)) {
|
||||
throw new Exception(__('Addon info version incorrect'));
|
||||
}
|
||||
|
|
@ -340,5 +339,4 @@ class Addon extends Command
|
|||
{
|
||||
return __DIR__ . '/Addon/stubs/' . $name . '.stub';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ class Crud extends Command
|
|||
/**
|
||||
* JSON后缀
|
||||
*/
|
||||
protected $jsonSuffix = ['json'];
|
||||
protected $jsonSuffix = ['json', 'array'];
|
||||
|
||||
/**
|
||||
* 标签后缀
|
||||
|
|
@ -466,7 +466,7 @@ class Crud extends Command
|
|||
}
|
||||
}
|
||||
$relationTableInfo = $relationTableInfo[0];
|
||||
$relationModel = isset($relationModels[$index]) ? $relationModels[$index] : '';
|
||||
$relationModel = $relationModels[$index] ?? '';
|
||||
|
||||
list($relationNamespace, $relationName, $relationFile) = $this->getModelData($modelModuleName, $relationModel, $relationName);
|
||||
|
||||
|
|
@ -666,8 +666,8 @@ class Crud extends Command
|
|||
//如果是关联模型
|
||||
foreach ($relations as $index => &$relation) {
|
||||
if ($relation['relationMode'] == 'hasone') {
|
||||
$relationForeignKey = $relation['relationForeignKey'] ? $relation['relationForeignKey'] : $table . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ? $relation['relationPrimaryKey'] : $priKey;
|
||||
$relationForeignKey = $relation['relationForeignKey'] ?: $table . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ?: $priKey;
|
||||
|
||||
if (!in_array($relationForeignKey, $relation['relationFieldList'])) {
|
||||
throw new Exception('relation table [' . $relation['relationTableName'] . '] must be contain field [' . $relationForeignKey . ']');
|
||||
|
|
@ -676,8 +676,8 @@ class Crud extends Command
|
|||
throw new Exception('table [' . $modelTableName . '] must be contain field [' . $relationPrimaryKey . ']');
|
||||
}
|
||||
} elseif ($relation['relationMode'] == 'belongsto') {
|
||||
$relationForeignKey = $relation['relationForeignKey'] ? $relation['relationForeignKey'] : Loader::parseName($relation['relationName']) . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ? $relation['relationPrimaryKey'] : $relation['relationPriKey'];
|
||||
$relationForeignKey = $relation['relationForeignKey'] ?: Loader::parseName($relation['relationName']) . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ?: $relation['relationPriKey'];
|
||||
if (!in_array($relationForeignKey, $fieldArr)) {
|
||||
throw new Exception('table [' . $modelTableName . '] must be contain field [' . $relationForeignKey . ']');
|
||||
}
|
||||
|
|
@ -685,8 +685,8 @@ class Crud extends Command
|
|||
throw new Exception('relation table [' . $relation['relationTableName'] . '] must be contain field [' . $relationPrimaryKey . ']');
|
||||
}
|
||||
} elseif ($relation['relationMode'] == 'hasmany') {
|
||||
$relationForeignKey = $relation['relationForeignKey'] ? $relation['relationForeignKey'] : $table . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ? $relation['relationPrimaryKey'] : $priKey;
|
||||
$relationForeignKey = $relation['relationForeignKey'] ?: $table . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ?: $priKey;
|
||||
if (!in_array($relationForeignKey, $relation['relationFieldList'])) {
|
||||
throw new Exception('relation table [' . $relation['relationTableName'] . '] must be contain field [' . $relationForeignKey . ']');
|
||||
}
|
||||
|
|
@ -879,7 +879,7 @@ class Crud extends Command
|
|||
$formEditElement = Form::input('text', $fieldName, $editValue, $attrArr);
|
||||
} elseif ($inputType == 'fieldlist') {
|
||||
$itemArr = $this->getItemArray($itemArr, $field, $v['COLUMN_COMMENT']);
|
||||
$templateName = !isset($itemArr['key']) && !isset($itemArr['value']) && count($itemArr) > 0 ? 'fieldlist-template' : 'fieldlist';
|
||||
$templateName = !isset($itemArr['key']) && count($itemArr) > 0 ? (isset($itemArr['value']) && count($itemArr) === 1 ? 'fieldlist-array' : 'fieldlist-template') : 'fieldlist';
|
||||
$itemKey = isset($itemArr['key']) ? ucfirst($itemArr['key']) : 'Key';
|
||||
$itemValue = isset($itemArr['value']) ? ucfirst($itemArr['value']) : 'Value';
|
||||
$theadListArr = $tbodyListArr = [];
|
||||
|
|
@ -901,6 +901,12 @@ class Crud extends Command
|
|||
$cssClassArr[] = 'selectpage';
|
||||
$selectpageTable = substr($field, 0, strripos($field, '_'));
|
||||
$selectpageField = '';
|
||||
foreach ($relations as $index => $relation) {
|
||||
if ($relation['relationForeignKey'] === $field) {
|
||||
$selectpageTable = substr($relation['relationTableName'], strlen($prefix));
|
||||
break;
|
||||
}
|
||||
}
|
||||
$selectpageController = str_replace('_', '/', $selectpageTable);
|
||||
$attrArr['data-source'] = $selectpageController . "/index";
|
||||
//如果是类型表需要特殊处理下
|
||||
|
|
@ -931,7 +937,6 @@ class Crud extends Command
|
|||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
if (!$selectpageField) {
|
||||
foreach ($this->fieldSelectpageMap as $m => $n) {
|
||||
|
|
@ -993,7 +998,7 @@ class Crud extends Command
|
|||
}
|
||||
if (!$fields || in_array($field, explode(',', $fields))) {
|
||||
//构造JS列信息
|
||||
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : '', $itemArr);
|
||||
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : '', $itemArr, $v);
|
||||
}
|
||||
if ($this->headingFilterField && $this->headingFilterField == $field && $itemArr) {
|
||||
$headingHtml = $this->getReplacedStub('html/heading-html', ['field' => $field, 'fieldName' => Loader::parseName($field, 1, false)]);
|
||||
|
|
@ -1048,7 +1053,7 @@ class Crud extends Command
|
|||
//过滤text类型字段
|
||||
if ($v['DATA_TYPE'] != 'text') {
|
||||
//构造JS列信息
|
||||
$javascriptList[] = $this->getJsColumn($relationField, $v['DATA_TYPE']);
|
||||
$javascriptList[] = $this->getJsColumn($relationField, $v['DATA_TYPE'], '', [], $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1537,7 +1542,7 @@ EOD;
|
|||
{
|
||||
$itemArr = [];
|
||||
$comment = str_replace(',', ',', $comment);
|
||||
if (stripos($comment, ':') !== false && stripos($comment, ',') && stripos($comment, '=') !== false) {
|
||||
if (stripos($comment, ':') !== false && stripos($comment, '=') !== false) {
|
||||
list($fieldLang, $item) = explode(':', $comment);
|
||||
$itemArr = [];
|
||||
foreach (explode(',', $item) as $k => $v) {
|
||||
|
|
@ -1699,9 +1704,10 @@ EOD;
|
|||
* @param string $datatype
|
||||
* @param string $extend
|
||||
* @param array $itemArr
|
||||
* @param array $fieldConfig
|
||||
* @return string
|
||||
*/
|
||||
protected function getJsColumn($field, $datatype = '', $extend = '', $itemArr = [])
|
||||
protected function getJsColumn($field, $datatype = '', $extend = '', $itemArr = [], $fieldConfig = [])
|
||||
{
|
||||
$lang = mb_ucfirst($field);
|
||||
$formatter = '';
|
||||
|
|
@ -1739,7 +1745,7 @@ EOD;
|
|||
$noSearchFiles = ['file$', 'files$', 'image$', 'images$', '^weigh$'];
|
||||
if (preg_match("/" . implode('|', $noSearchFiles) . "/i", $field)) {
|
||||
$html .= ", operate: false";
|
||||
} else if (in_array($datatype, ['varchar'])) {
|
||||
} elseif (in_array($datatype, ['varchar'])) {
|
||||
$html .= ", operate: 'LIKE'";
|
||||
}
|
||||
|
||||
|
|
@ -1751,6 +1757,10 @@ EOD;
|
|||
if (in_array($datatype, ['set'])) {
|
||||
$html .= ", operate:'FIND_IN_SET'";
|
||||
}
|
||||
if (isset($fieldConfig['CHARACTER_MAXIMUM_LENGTH']) && $fieldConfig['CHARACTER_MAXIMUM_LENGTH'] >= 255 && in_array($datatype, ['varchar']) && !$formatter) {
|
||||
$formatter = 'content';
|
||||
$html .= ", table: table, class: 'autocontent'";
|
||||
}
|
||||
if (in_array($formatter, ['image', 'images'])) {
|
||||
$html .= ", events: Table.api.events.image";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
<dl class="list-unstyled fieldlist" data-name="{%fieldName%}" data-template="{%fieldName%}tpl">
|
||||
<dd>
|
||||
<ins>{:__('{%itemValue%}')}</ins>
|
||||
</dd>
|
||||
<dd>
|
||||
<ins><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></ins>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<textarea name="{%fieldName%}" class="form-control hide" cols="30" rows="5">{%fieldValue%}</textarea>
|
||||
<script id="{%fieldName%}tpl" type="text/html">
|
||||
<dd class="form-inline">
|
||||
<ins><input type="text" name="<%=name%>[<%=index%>][value]" class="form-control" size="15" value="<%=row%>"/></ins>
|
||||
<ins>
|
||||
<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>
|
||||
</ins>
|
||||
</dd>
|
||||
</script>
|
||||
|
||||
|
|
@ -336,16 +336,16 @@ INSERT INTO `fa_config` VALUES (4, 'version', 'basic', 'Version', '如果静态
|
|||
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 (8, 'fixedpage', 'basic', 'Fixed page', '请输入左侧菜单栏存在的链接', 'string', '', 'dashboard', '', 'required', '', '');
|
||||
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', '[\"请选择\",\"SMTP\"]', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (12, 'mail_smtp_host', 'email', 'Mail smtp host', '错误的配置发送邮件会导致服务器超时', 'string', '', 'smtp.qq.com', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (13, 'mail_smtp_port', 'email', 'Mail smtp port', '(不加密默认25,SSL默认465,TLS默认587)', 'string', '', '465', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (14, 'mail_smtp_user', 'email', 'Mail smtp user', '(填写完整用户名)', 'string', '', '10000', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (15, 'mail_smtp_pass', 'email', 'Mail smtp password', '(填写您的密码或授权码)', 'password', '', 'password', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (14, 'mail_smtp_user', 'email', 'Mail smtp user', '(填写完整用户名)', 'string', '', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (15, 'mail_smtp_pass', 'email', 'Mail smtp password', '(填写您的密码或授权码)', 'password', '', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (16, 'mail_verify_type', 'email', 'Mail vertify type', '(SMTP验证方式[推荐SSL])', 'select', '', '2', '[\"无\",\"TLS\",\"SSL\"]', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (17, 'mail_from', 'email', 'Mail from', '', 'string', '', '10000@qq.com', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (17, 'mail_from', 'email', 'Mail from', '', 'string', '', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (18, 'attachmentcategory', 'dictionary', 'Attachment category', '', 'array', '', '{\"category1\":\"Category1\",\"category2\":\"Category2\",\"custom\":\"Custom\"}', '', '', '', '');
|
||||
COMMIT;
|
||||
|
||||
|
|
@ -399,7 +399,8 @@ CREATE TABLE `fa_test` (
|
|||
`keywords` varchar(255) DEFAULT '' COMMENT '关键字',
|
||||
`description` varchar(255) DEFAULT '' COMMENT '描述',
|
||||
`city` varchar(100) DEFAULT '' COMMENT '省市',
|
||||
`json` varchar(255) DEFAULT NULL COMMENT '配置:key=名称,value=值',
|
||||
`array` varchar(255) DEFAULT '' COMMENT '数组:value=值',
|
||||
`json` varchar(255) DEFAULT '' COMMENT '配置:key=名称,value=值',
|
||||
`multiplejson` varchar(1500) DEFAULT '' COMMENT '二维数组:title=标题,intro=介绍,author=作者,age=年龄',
|
||||
`price` decimal(10,2) unsigned DEFAULT '0.00' COMMENT '价格',
|
||||
`views` int(10) unsigned DEFAULT '0' COMMENT '点击',
|
||||
|
|
@ -423,7 +424,7 @@ CREATE TABLE `fa_test` (
|
|||
-- Records of fa_test
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `fa_test` VALUES (1, 1, 1, 12, '12,13', '互联网,计算机', 'monday', 'hot,index', 'male', 'music,reading', '我是一篇测试文章', '<p>我是测试内容</p>', '/assets/img/avatar.png', '/assets/img/avatar.png,/assets/img/qrcode.png', '/assets/img/avatar.png', '关键字', '我是一篇测试文章描述,内容过多时将自动隐藏', '广西壮族自治区/百色市/平果县', '{\"a\":\"1\",\"b\":\"2\"}', '[{\"title\":\"标题一\",\"intro\":\"介绍一\",\"author\":\"小明\",\"age\":\"21\"}]', 0.00, 0, '2020-10-01 00:00:00 - 2021-10-31 23:59:59', '2017-07-10', '2017-07-10 18:24:45', 2017, '18:24:45', 1491635035, 1491635035, 1491635035, NULL, 0, 1, 'normal', '1');
|
||||
INSERT INTO `fa_test` VALUES (1, 1, 1, 12, '12,13', '互联网,计算机', 'monday', 'hot,index', 'male', 'music,reading', '我是一篇测试文章', '<p>我是测试内容</p>', '/assets/img/avatar.png', '/assets/img/avatar.png,/assets/img/qrcode.png', '/assets/img/avatar.png', '关键字', '我是一篇测试文章描述,内容过多时将自动隐藏', '广西壮族自治区/百色市/平果县', '[\"a\",\"b\"]', '{\"a\":\"1\",\"b\":\"2\"}', '[{\"title\":\"标题一\",\"intro\":\"介绍一\",\"author\":\"小明\",\"age\":\"21\"}]', 0.00, 0, '2020-10-01 00:00:00 - 2021-10-31 23:59:59', '2017-07-10', '2017-07-10 18:24:45', 2017, '18:24:45', 1491635035, 1491635035, 1491635035, NULL, 0, 1, 'normal', '1');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
|
@ -468,7 +469,7 @@ CREATE TABLE `fa_user` (
|
|||
-- Records of fa_user
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `fa_user` VALUES (1, 1, 'admin', 'admin', '', '', 'admin@163.com', '13888888888', '', 0, 0, '2017-04-08', '', 0, 0, 1, 1, 1491635035, 1491635035, '127.0.0.1', 0, '127.0.0.1', 1491635035, 0, 1491635035, '', 'normal','');
|
||||
INSERT INTO `fa_user` VALUES (1, 1, 'admin', 'admin', '', '', 'admin@163.com', '13000000000', '', 0, 0, '2017-04-08', '', 0, 0, 1, 1, 1491635035, 1491635035, '127.0.0.1', 0, '127.0.0.1', 1491635035, 0, 1491635035, '', 'normal','');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
|
|
|
|||
|
|
@ -95,19 +95,24 @@ class Addon extends Backend
|
|||
}
|
||||
$tips = [];
|
||||
$groupList = [];
|
||||
$ungroupList = [];
|
||||
foreach ($config as $index => &$item) {
|
||||
//如果有设置分组
|
||||
if (isset($item['group']) && $item['group']) {
|
||||
if (!in_array($item['group'], $groupList)) {
|
||||
$groupList["custom" . (count($groupList) + 1)] = $item['group'];
|
||||
}
|
||||
} elseif ($item['name'] != '__tips__') {
|
||||
$ungroupList[] = $item['name'];
|
||||
}
|
||||
if ($item['name'] == '__tips__') {
|
||||
$tips = $item;
|
||||
unset($config[$index]);
|
||||
}
|
||||
}
|
||||
if ($ungroupList) {
|
||||
$groupList['other'] = '其它';
|
||||
}
|
||||
$this->view->assign("groupList", $groupList);
|
||||
$this->view->assign("addon", ['info' => $info, 'config' => $config, 'tips' => $tips]);
|
||||
$configFile = ADDON_PATH . $name . DS . 'config.html';
|
||||
|
|
@ -230,6 +235,7 @@ class Addon extends Backend
|
|||
$uid = $this->request->post("uid");
|
||||
$token = $this->request->post("token");
|
||||
$faversion = $this->request->post("faversion");
|
||||
$force = $this->request->post("force");
|
||||
if (!$uid || !$token) {
|
||||
throw new Exception(__('Please login and try to install'));
|
||||
}
|
||||
|
|
@ -238,7 +244,7 @@ class Addon extends Backend
|
|||
'token' => $token,
|
||||
'faversion' => $faversion
|
||||
];
|
||||
$info = Service::local($file, $extend);
|
||||
$info = Service::local($file, $extend, $force);
|
||||
} catch (AddonException $e) {
|
||||
$this->result($e->getData(), $e->getCode(), __($e->getMessage()));
|
||||
} catch (Exception $e) {
|
||||
|
|
@ -441,8 +447,11 @@ class Addon extends Backend
|
|||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
$rows = isset($json['rows']) ? $json['rows'] : [];
|
||||
$rows = $json['rows'] ?? [];
|
||||
foreach ($rows as $index => $row) {
|
||||
if (!isset($row['name'])) {
|
||||
continue;
|
||||
}
|
||||
$onlineaddons[$row['name']] = $row;
|
||||
}
|
||||
Cache::set("onlineaddons", $onlineaddons, 600);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ class Index extends Backend
|
|||
'dashboard' => 'hot',
|
||||
'addon' => ['new', 'red', 'badge'],
|
||||
'auth/rule' => __('Menu'),
|
||||
'general' => ['new', 'purple'],
|
||||
], $this->view->site['fixedpage']);
|
||||
$action = $this->request->request('action');
|
||||
if ($this->request->isPost()) {
|
||||
|
|
@ -66,7 +65,8 @@ class Index extends Backend
|
|||
*/
|
||||
public function login()
|
||||
{
|
||||
$url = $this->request->get('url', 'index/index', 'url_clean');
|
||||
$url = $this->request->get('url', '', 'url_clean');
|
||||
$url = $url ?: 'index/index';
|
||||
if ($this->auth->isLogin()) {
|
||||
$this->success(__("You've logged in, do not login again"), $url);
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@ class Index extends Backend
|
|||
$keeyloginhours = 24;
|
||||
if ($this->request->isPost()) {
|
||||
$username = $this->request->post('username');
|
||||
$password = $this->request->post('password');
|
||||
$password = $this->request->post('password', '', null);
|
||||
$keeplogin = $this->request->post('keeplogin');
|
||||
$token = $this->request->post('__token__');
|
||||
$rule = [
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ class Adminlog extends Backend
|
|||
$query->where('admin_id', 'in', $childrenAdminIds);
|
||||
}
|
||||
})
|
||||
->field('content,useragent', true)
|
||||
->order($sort, $order)
|
||||
->paginate($limit);
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ class Profile extends Backend
|
|||
$admin->save($params);
|
||||
//因为个人资料面板读取的Session显示,修改自己资料后同时更新Session
|
||||
Session::set("admin", $admin->toArray());
|
||||
Session::set("admin.safecode", $this->auth->getEncryptSafecode($admin));
|
||||
$this->success();
|
||||
}
|
||||
$this->error();
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class User extends Backend
|
|||
public function _initialize()
|
||||
{
|
||||
parent::_initialize();
|
||||
$this->model = model('User');
|
||||
$this->model = new \app\admin\model\User;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ return [
|
|||
'User id' => '会员ID',
|
||||
'Username' => '用户名',
|
||||
'Nickname' => '昵称',
|
||||
'Mobile' => '手机',
|
||||
'Email' => '邮箱',
|
||||
'Password' => '密码',
|
||||
'Mobile' => '手机号',
|
||||
'Sign up' => '注 册',
|
||||
|
|
|
|||
|
|
@ -14,11 +14,8 @@ return [
|
|||
'Refresh addon cache' => '刷新插件缓存',
|
||||
'Userinfo' => '会员信息',
|
||||
'Reload authorization' => '刷新授权',
|
||||
'Online store' => '在线商店',
|
||||
'Local addon' => '本地插件',
|
||||
'Conflict tips' => '此插件中发现和现有系统中部分文件发现冲突!以下文件将会被影响,请备份好相关文件后再继续操作',
|
||||
'Login tips' => '此处登录账号为<a href="https://www.fastadmin.net" target="_blank">FastAdmin官网账号</a>',
|
||||
'Logined tips' => '你好!%s<br />当前你已经登录,将同步保存你的购买记录',
|
||||
'Pay tips' => '扫码支付后如果仍然无法安装,请不要重复支付,请稍后再重试安装!',
|
||||
'Pay successful tips' => '购买成功!请点击继续安装按钮完成安装!',
|
||||
'Pay click tips' => '请点击这里在新窗口中进行支付!',
|
||||
|
|
@ -26,8 +23,7 @@ return [
|
|||
'Upgrade tips' => '确认升级<b>《%s》</b>?<p class="text-danger">1、请务必做好代码和数据库备份!备份!备份!<br>2、升级后如出现冗余数据,请根据需要移除即可!<br>3、不建议在生产环境升级,请在本地完成升级测试</p>如有重要数据请备份后再操作!',
|
||||
'Offline installed tips' => '安装成功!清除浏览器缓存和框架缓存后生效!',
|
||||
'Online installed tips' => '安装成功!清除浏览器缓存和框架缓存后生效!',
|
||||
'Not login tips' => '你当前未登录FastAdmin,请登录后操作!',
|
||||
'Please login and try to install' => '请登录FastAdmin后再进行离线安装!',
|
||||
'Please login and try to install' => '请登录FastAdmin后再进行本地安装!',
|
||||
'Not installed tips' => '请安装后再访问插件前台页面!',
|
||||
'Not enabled tips' => '插件已经禁用,请启用后再访问插件前台页面!',
|
||||
'New version tips' => '发现新版本:%s 点击查看更新日志',
|
||||
|
|
@ -37,6 +33,7 @@ return [
|
|||
'Store not available tips' => '插件市场暂不可用,是否切换到本地插件?',
|
||||
'Switch to the local' => '切换到本地插件',
|
||||
'try to reload' => '重新尝试加载',
|
||||
'Please disable addon first' => '请先禁用插件再进行操作',
|
||||
'Please disable the add before trying to upgrade' => '请先禁用插件再进行升级',
|
||||
'Please disable the add before trying to uninstall' => '请先禁用插件再进行卸载',
|
||||
'Login now' => '立即登录',
|
||||
|
|
@ -80,7 +77,6 @@ return [
|
|||
'Enable' => '启用',
|
||||
'Your username or email' => '你的手机号、用户名或邮箱',
|
||||
'Your password' => '你的密码',
|
||||
'Login FastAdmin' => '登录',
|
||||
'Login' => '登录',
|
||||
'Logout' => '退出登录',
|
||||
'Register' => '注册账号',
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ class Auth extends \fast\Auth
|
|||
}
|
||||
}
|
||||
// 取出所有分组
|
||||
$groupList = \app\admin\model\AuthGroup::where(['status' => 'normal'])->select();
|
||||
$groupList = \app\admin\model\AuthGroup::where($this->isSuperAdmin() ? '1=1' : ['status' => 'normal'])->select();
|
||||
$objList = [];
|
||||
foreach ($groups as $k => $v) {
|
||||
if ($v['rules'] === '*') {
|
||||
|
|
@ -371,8 +371,7 @@ class Auth extends \fast\Auth
|
|||
$childrenAdminIds = [];
|
||||
if (!$this->isSuperAdmin()) {
|
||||
$groupIds = $this->getChildrenGroupIds(false);
|
||||
$authGroupList = \app\admin\model\AuthGroupAccess::
|
||||
field('uid,group_id')
|
||||
$authGroupList = \app\admin\model\AuthGroupAccess::field('uid,group_id')
|
||||
->where('group_id', 'in', $groupIds)
|
||||
->select();
|
||||
foreach ($authGroupList as $k => $v) {
|
||||
|
|
@ -418,7 +417,6 @@ class Auth extends \fast\Auth
|
|||
$titleArr[$pathArr[$rule['name']]] = $rule['title'];
|
||||
$menuArr[$pathArr[$rule['name']]] = $rule;
|
||||
}
|
||||
|
||||
}
|
||||
ksort($menuArr);
|
||||
$this->breadcrumb = $menuArr;
|
||||
|
|
@ -444,9 +442,9 @@ class Auth extends \fast\Auth
|
|||
foreach ($params as $k => $v) {
|
||||
$url = $k;
|
||||
if (is_array($v)) {
|
||||
$nums = isset($v[0]) ? $v[0] : 0;
|
||||
$color = isset($v[1]) ? $v[1] : $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums];
|
||||
$class = isset($v[2]) ? $v[2] : 'label';
|
||||
$nums = $v[0] ?? 0;
|
||||
$color = $v[1] ?? $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums];
|
||||
$class = $v[2] ?? 'label';
|
||||
} else {
|
||||
$nums = $v;
|
||||
$color = $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums];
|
||||
|
|
@ -485,7 +483,7 @@ class Auth extends \fast\Auth
|
|||
}
|
||||
$v['icon'] = $v['icon'] . ' fa-fw';
|
||||
$v['url'] = isset($v['url']) && $v['url'] ? $v['url'] : '/' . $module . '/' . $v['name'];
|
||||
$v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : '';
|
||||
$v['badge'] = $badgeList[$v['name']] ?? '';
|
||||
$v['title'] = __($v['title']);
|
||||
$v['url'] = preg_match("/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i", $v['url']) ? $v['url'] : url($v['url']);
|
||||
$v['menuclass'] = in_array($v['menutype'], ['dialog', 'ajax']) ? 'btn-' . $v['menutype'] : '';
|
||||
|
|
|
|||
|
|
@ -460,7 +460,7 @@ trait Backend
|
|||
if ($has_admin_id) {
|
||||
$auth = Auth::instance();
|
||||
foreach ($insert as &$val) {
|
||||
if (!isset($val['admin_id']) || empty($val['admin_id'])) {
|
||||
if (empty($val['admin_id'])) {
|
||||
$val['admin_id'] = $auth->isLogin() ? $auth->id : 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ class AdminLog extends Model
|
|||
|
||||
/**
|
||||
* 记录日志
|
||||
* @param string $title
|
||||
* @param string $content
|
||||
* @param string $title 日志标题
|
||||
* @param string $content 日志内容
|
||||
*/
|
||||
public static function record($title = '', $content = '')
|
||||
{
|
||||
|
|
@ -50,6 +50,9 @@ class AdminLog extends Model
|
|||
$admin_id = $auth->isLogin() ? $auth->id : 0;
|
||||
$username = $auth->isLogin() ? $auth->username : __('Unknown');
|
||||
|
||||
// 设置过滤函数
|
||||
request()->filter('trim,strip_tags,htmlspecialchars');
|
||||
|
||||
$controllername = Loader::parseName(request()->controller());
|
||||
$actionname = strtolower(request()->action());
|
||||
$path = str_replace('.', '/', $controllername) . '/' . $actionname;
|
||||
|
|
@ -60,12 +63,12 @@ class AdminLog extends Model
|
|||
}
|
||||
}
|
||||
}
|
||||
$content = $content ? $content : self::$content;
|
||||
$content = $content ?: self::$content;
|
||||
if (!$content) {
|
||||
$content = request()->param('', null, 'trim,strip_tags,htmlspecialchars');
|
||||
$content = request()->param('') ?: file_get_contents("php://input");
|
||||
$content = self::getPureContent($content);
|
||||
}
|
||||
$title = $title ? $title : self::$title;
|
||||
$title = $title ?: self::$title;
|
||||
if (!$title) {
|
||||
$title = [];
|
||||
$breadcrumb = Auth::instance()->getBreadcrumb($path);
|
||||
|
|
@ -77,18 +80,18 @@ class AdminLog extends Model
|
|||
self::create([
|
||||
'title' => $title,
|
||||
'content' => !is_scalar($content) ? json_encode($content, JSON_UNESCAPED_UNICODE) : $content,
|
||||
'url' => substr(request()->url(), 0, 1500),
|
||||
'url' => substr(xss_clean(strip_tags(request()->url())), 0, 1500),
|
||||
'admin_id' => $admin_id,
|
||||
'username' => $username,
|
||||
'useragent' => substr(request()->server('HTTP_USER_AGENT'), 0, 255),
|
||||
'ip' => request()->ip()
|
||||
'ip' => xss_clean(strip_tags(request()->ip()))
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已屏蔽关键信息的数据
|
||||
* @param $content
|
||||
* @return false|string
|
||||
* @return array
|
||||
*/
|
||||
protected static function getPureContent($content)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -105,6 +105,12 @@
|
|||
<span class="msg-box n-right" for="c-{$item.name}"></span>
|
||||
</div>
|
||||
{/case}
|
||||
{case switch}
|
||||
<input id="c-{$item.name}" name="row[{$item.name}]" type="hidden" value="{:$item.value?1:0}">
|
||||
<a href="javascript:;" data-toggle="switcher" class="btn-switcher" data-input-id="c-{$item.name}" data-yes="1" data-no="0">
|
||||
<i class="fa fa-toggle-on text-success {if !$item.value}fa-flip-horizontal text-gray{/if} fa-2x"></i>
|
||||
</a>
|
||||
{/case}
|
||||
{case bool}
|
||||
<label for="row[{$item.name}]-yes"><input id="row[{$item.name}]-yes" name="row[{$item.name}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip}" /> {:__('Yes')}</label>
|
||||
<label for="row[{$item.name}]-no"><input id="row[{$item.name}]-no" name="row[{$item.name}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip}" /> {:__('No')}</label>
|
||||
|
|
|
|||
|
|
@ -167,6 +167,11 @@
|
|||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script id="upgradetpl" type="text/html">
|
||||
<div class="">
|
||||
<div class=""><%=#__("Upgrade tips", addon['title'])%></div>
|
||||
</div>
|
||||
</script>
|
||||
<script id="conflicttpl" type="text/html">
|
||||
<div class="alert alert-dismissable alert-danger">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
|
|
|
|||
|
|
@ -137,6 +137,8 @@ class Common extends Api
|
|||
$attachment = $upload->upload();
|
||||
} catch (UploadException $e) {
|
||||
$this->error($e->getMessage());
|
||||
} catch (\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
$this->success(__('Uploaded successful'), ['url' => $attachment->url, 'fullurl' => cdnurl($attachment->url, true)]);
|
||||
|
|
|
|||
|
|
@ -45,6 +45,12 @@ class Ems extends Api
|
|||
if ($last && time() - $last['createtime'] < 60) {
|
||||
$this->error(__('发送频繁'));
|
||||
}
|
||||
|
||||
$ipSendTotal = \app\common\model\Ems::where(['ip' => $this->request->ip()])->whereTime('createtime', '-1 hours')->count();
|
||||
if ($ipSendTotal >= 5) {
|
||||
$this->error(__('发送频繁'));
|
||||
}
|
||||
|
||||
if ($event) {
|
||||
$userinfo = User::getByEmail($email);
|
||||
if ($event == 'register' && $userinfo) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
// 公共助手函数
|
||||
|
||||
use Symfony\Component\VarExporter\VarExporter;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Response;
|
||||
|
||||
|
|
@ -88,8 +87,8 @@ if (!function_exists('cdnurl')) {
|
|||
function cdnurl($url, $domain = false)
|
||||
{
|
||||
$regex = "/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i";
|
||||
if (is_bool($domain)) {
|
||||
$cdnurl = \think\Config::get('upload.cdnurl');
|
||||
if (is_bool($domain) || stripos($cdnurl, '/') === 0) {
|
||||
$url = preg_match($regex, $url) || ($cdnurl && stripos($url, $cdnurl) === 0) ? $url : $cdnurl . $url;
|
||||
}
|
||||
if ($domain && !preg_match($regex, $url)) {
|
||||
|
|
@ -249,9 +248,10 @@ if (!function_exists('addtion')) {
|
|||
if ($v['model']) {
|
||||
$model = new $v['model'];
|
||||
} else {
|
||||
$model = $v['name'] ? \think\Db::name($v['name']) : \think\Db::table($v['table']);
|
||||
// 优先判断使用table的配置
|
||||
$model = $v['table'] ? \think\Db::table($v['table']) : \think\Db::name($v['name']);
|
||||
}
|
||||
$primary = $v['primary'] ? $v['primary'] : $model->getPk();
|
||||
$primary = $v['primary'] ?: $model->getPk();
|
||||
$result[$v['field']] = isset($ids[$v['field']]) ? $model->where($primary, 'in', $ids[$v['field']])->column($v['column'], $primary) : [];
|
||||
}
|
||||
|
||||
|
|
@ -280,60 +280,6 @@ if (!function_exists('var_export_short')) {
|
|||
function var_export_short($data, $return = true)
|
||||
{
|
||||
return var_export($data, $return);
|
||||
$replaced = [];
|
||||
$count = 0;
|
||||
|
||||
//判断是否是对象
|
||||
if (is_resource($data) || is_object($data)) {
|
||||
return var_export($data, $return);
|
||||
}
|
||||
|
||||
//判断是否有特殊的键名
|
||||
$specialKey = false;
|
||||
array_walk_recursive($data, function (&$value, &$key) use (&$specialKey) {
|
||||
if (is_string($key) && (stripos($key, "\n") !== false || stripos($key, "array (") !== false)) {
|
||||
$specialKey = true;
|
||||
}
|
||||
});
|
||||
if ($specialKey) {
|
||||
return var_export($data, $return);
|
||||
}
|
||||
array_walk_recursive($data, function (&$value, &$key) use (&$replaced, &$count, &$stringcheck) {
|
||||
if (is_object($value) || is_resource($value)) {
|
||||
$replaced[$count] = var_export($value, true);
|
||||
$value = "##<{$count}>##";
|
||||
} else {
|
||||
if (is_string($value) && (stripos($value, "\n") !== false || stripos($value, "array (") !== false)) {
|
||||
$index = array_search($value, $replaced);
|
||||
if ($index === false) {
|
||||
$replaced[$count] = var_export($value, true);
|
||||
$value = "##<{$count}>##";
|
||||
} else {
|
||||
$value = "##<{$index}>##";
|
||||
}
|
||||
}
|
||||
}
|
||||
$count++;
|
||||
});
|
||||
|
||||
$dump = var_export($data, true);
|
||||
|
||||
$dump = preg_replace('#(?:\A|\n)([ ]*)array \(#i', '[', $dump); // Starts
|
||||
$dump = preg_replace('#\n([ ]*)\),#', "\n$1],", $dump); // Ends
|
||||
$dump = preg_replace('#=> \[\n\s+\],\n#', "=> [],\n", $dump); // Empties
|
||||
$dump = preg_replace('#\)$#', "]", $dump); //End
|
||||
|
||||
if ($replaced) {
|
||||
$dump = preg_replace_callback("/'##<(\d+)>##'/", function ($matches) use ($replaced) {
|
||||
return $replaced[$matches[1]] ?? "''";
|
||||
}, $dump);
|
||||
}
|
||||
|
||||
if ($return === true) {
|
||||
return $dump;
|
||||
} else {
|
||||
echo $dump;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -429,7 +375,7 @@ if (!function_exists('check_cors_request')) {
|
|||
*/
|
||||
function check_cors_request()
|
||||
{
|
||||
if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN']) {
|
||||
if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN'] && config('fastadmin.cors_request_domain')) {
|
||||
$info = parse_url($_SERVER['HTTP_ORIGIN']);
|
||||
$domainArr = explode(',', config('fastadmin.cors_request_domain'));
|
||||
$domainArr[] = request()->host(true);
|
||||
|
|
@ -504,20 +450,24 @@ if (!function_exists('check_url_allowed')) {
|
|||
* @param string $url URL
|
||||
* @return bool
|
||||
*/
|
||||
function check_url_allowed($url = null)
|
||||
function check_url_allowed($url = '')
|
||||
{
|
||||
//允许的主机列表
|
||||
$allowedHostArr = [
|
||||
strtolower(request()->host())
|
||||
];
|
||||
|
||||
if (empty($url)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//如果是站内相对链接则允许
|
||||
if (preg_match("/^[\/a-z][a-z0-9][a-z0-9\.\/]+\$/i", $url) && substr($url, 0, 2) !== '//') {
|
||||
if (preg_match("/^[\/a-z][a-z0-9][a-z0-9\.\/]+((\?|#).*)?\$/i", $url) && substr($url, 0, 2) !== '//') {
|
||||
return true;
|
||||
}
|
||||
|
||||
//如果是站外链接则需要判断HOST是否允许
|
||||
if (preg_match("/((http[s]?:\/\/)+(?>[a-z\-0-9]{2,}\.){1,}[a-z]{2,8})(?:\s|\/)/i", $url)) {
|
||||
if (preg_match("/((http[s]?:\/\/)+((?>[a-z\-0-9]{2,}\.)+[a-z]{2,8}|((?>([0-9]{1,3}\.)){3}[0-9]{1,3}))(:[0-9]{1,5})?)(?:\s|\/)/i", $url)) {
|
||||
$chkHost = parse_url(strtolower($url), PHP_URL_HOST);
|
||||
if ($chkHost && in_array($chkHost, $allowedHostArr)) {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -204,8 +204,8 @@ class Api
|
|||
'time' => Request::instance()->server('REQUEST_TIME'),
|
||||
'data' => $data,
|
||||
];
|
||||
// 如果未设置类型则自动判断
|
||||
$type = $type ? $type : ($this->request->param(config('var_jsonp_handler')) ? 'jsonp' : $this->responseType);
|
||||
// 如果未设置类型则使用默认类型判断
|
||||
$type = $type ? : $this->responseType;
|
||||
|
||||
if (isset($header['statuscode'])) {
|
||||
$code = $header['statuscode'];
|
||||
|
|
|
|||
|
|
@ -123,10 +123,10 @@ class Backend extends Controller
|
|||
$path = str_replace('.', '/', $controllername) . '/' . $actionname;
|
||||
|
||||
// 定义是否Addtabs请求
|
||||
!defined('IS_ADDTABS') && define('IS_ADDTABS', input("addtabs") ? true : false);
|
||||
!defined('IS_ADDTABS') && define('IS_ADDTABS', (bool)input("addtabs"));
|
||||
|
||||
// 定义是否Dialog请求
|
||||
!defined('IS_DIALOG') && define('IS_DIALOG', input("dialog") ? true : false);
|
||||
!defined('IS_DIALOG') && define('IS_DIALOG', (bool)input("dialog"));
|
||||
|
||||
// 定义是否AJAX请求
|
||||
!defined('IS_AJAX') && define('IS_AJAX', $this->request->isAjax());
|
||||
|
|
@ -269,7 +269,8 @@ class Backend extends Controller
|
|||
$sort = $this->request->get("sort", !empty($this->model) && $this->model->getPk() ? $this->model->getPk() : 'id');
|
||||
$order = $this->request->get("order", "DESC");
|
||||
$offset = $this->request->get("offset/d", 0);
|
||||
$limit = $this->request->get("limit/d", 999999);
|
||||
$limit = $this->request->get("limit/d", 0);
|
||||
$limit = $limit ?: 999999;
|
||||
//新增自动计算页码
|
||||
$page = $limit ? intval($offset / $limit) + 1 : 1;
|
||||
if ($this->request->has("page")) {
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ class Auth
|
|||
'avatar' => '',
|
||||
];
|
||||
$params = array_merge($data, [
|
||||
'nickname' => preg_match("/^1[3-9]{1}\d{9}$/",$username) ? substr_replace($username,'****',3,4) : $username,
|
||||
'nickname' => preg_match("/^1[3-9]{1}\d{9}$/", $username) ? substr_replace($username, '****', 3, 4) : $username,
|
||||
'salt' => Random::alnum(),
|
||||
'jointime' => $time,
|
||||
'joinip' => $ip,
|
||||
|
|
@ -356,7 +356,7 @@ class Auth
|
|||
}
|
||||
$url = ($module ? $module : request()->module()) . '/' . (is_null($path) ? $this->getRequestUri() : $path);
|
||||
$url = strtolower(str_replace('.', '/', $url));
|
||||
return in_array($url, $rules) ? true : false;
|
||||
return in_array($url, $rules);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -394,7 +394,7 @@ class Auth
|
|||
|
||||
/**
|
||||
* 获取会员组别规则列表
|
||||
* @return array
|
||||
* @return array|bool|\PDOStatement|string|\think\Collection
|
||||
*/
|
||||
public function getRuleList()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -182,14 +182,14 @@ class Menu
|
|||
} else {
|
||||
$pid = $parent;
|
||||
}
|
||||
$allow = array_flip(['file', 'name', 'title', 'url', 'icon', 'condition', 'remark', 'ismenu', 'menutype', 'extend', 'weigh']);
|
||||
$allow = array_flip(['file', 'name', 'title', 'url', 'icon', 'condition', 'remark', 'ismenu', 'menutype', 'extend', 'weigh', 'status']);
|
||||
foreach ($newMenu as $k => $v) {
|
||||
$hasChild = isset($v['sublist']) && $v['sublist'];
|
||||
$data = array_intersect_key($v, $allow);
|
||||
$data['ismenu'] = $data['ismenu'] ?? ($hasChild ? 1 : 0);
|
||||
$data['icon'] = $data['icon'] ?? ($hasChild ? 'fa fa-list' : 'fa fa-circle-o');
|
||||
$data['pid'] = $pid;
|
||||
$data['status'] = 'normal';
|
||||
$data['status'] = $data['status'] ?? 'normal';
|
||||
if (!isset($oldMenu[$data['name']])) {
|
||||
$menu = AuthRule::create($data);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ use Exception;
|
|||
*/
|
||||
class Security
|
||||
{
|
||||
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
|
|
@ -420,7 +419,7 @@ class Security
|
|||
*/
|
||||
public function get_random_bytes($length)
|
||||
{
|
||||
if (empty($length) OR !ctype_digit((string)$length)) {
|
||||
if (empty($length) or !ctype_digit((string)$length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -485,8 +484,8 @@ class Security
|
|||
|
||||
static $_entities;
|
||||
|
||||
isset($charset) OR $charset = $this->charset;
|
||||
isset($_entities) OR $_entities = array_map('strtolower', get_html_translation_table(HTML_ENTITIES, ENT_COMPAT | ENT_HTML5, $charset));
|
||||
isset($charset) or $charset = $this->charset;
|
||||
isset($_entities) or $_entities = array_map('strtolower', get_html_translation_table(HTML_ENTITIES, ENT_COMPAT | ENT_HTML5, $charset));
|
||||
|
||||
do {
|
||||
$str_compare = $str;
|
||||
|
|
@ -698,7 +697,7 @@ class Security
|
|||
// Is it indeed an "evil" attribute?
|
||||
preg_match($is_evil_pattern, $attribute['name'][0])
|
||||
// Or does it have an equals sign, but no value and not quoted? Strip that too!
|
||||
OR (trim($attribute['value'][0]) === '')
|
||||
or (trim($attribute['value'][0]) === '')
|
||||
) {
|
||||
$attributes[] = 'xss=removed';
|
||||
} else {
|
||||
|
|
@ -870,5 +869,4 @@ class Security
|
|||
|
||||
return $str;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ class Config extends Model
|
|||
if (!preg_match("/^((?:[a-z]+:)?\/\/)(.*)/i", $uploadurl) && substr($uploadurl, 0, 1) !== '/') {
|
||||
$uploadurl = url($uploadurl, '', false);
|
||||
}
|
||||
$uploadcfg['fullmode'] = isset($uploadcfg['fullmode']) && $uploadcfg['fullmode'] ? true : false;
|
||||
$uploadcfg['fullmode'] = isset($uploadcfg['fullmode']) && $uploadcfg['fullmode'];
|
||||
$uploadcfg['thumbstyle'] = $uploadcfg['thumbstyle'] ?? '';
|
||||
|
||||
$upload = [
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ return [
|
|||
//允许跨域的域名,多个以,分隔
|
||||
'cors_request_domain' => 'localhost,127.0.0.1',
|
||||
//版本号
|
||||
'version' => '1.4.0.20230315',
|
||||
'version' => '2.0.0.20240401',
|
||||
//API接口地址
|
||||
'api_url' => 'https://api.fastadmin.net',
|
||||
],
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ return [
|
|||
'mail_type' => '1',
|
||||
'mail_smtp_host' => 'smtp.qq.com',
|
||||
'mail_smtp_port' => '465',
|
||||
'mail_smtp_user' => '10000',
|
||||
'mail_smtp_pass' => 'password',
|
||||
'mail_smtp_user' => '',
|
||||
'mail_smtp_pass' => '',
|
||||
'mail_verify_type' => '2',
|
||||
'mail_from' => '10000@qq.com',
|
||||
'mail_from' => '',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -66,13 +66,13 @@ class User extends Frontend
|
|||
*/
|
||||
public function register()
|
||||
{
|
||||
$url = $this->request->request('url', '', 'trim,xss_clean');
|
||||
$url = $this->request->request('url', '', 'url_clean');
|
||||
if ($this->auth->id) {
|
||||
$this->success(__('You\'ve logged in, do not login again'), $url ? $url : url('user/index'));
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$username = $this->request->post('username');
|
||||
$password = $this->request->post('password');
|
||||
$password = $this->request->post('password', '', null);
|
||||
$email = $this->request->post('email');
|
||||
$mobile = $this->request->post('mobile', '');
|
||||
$captcha = $this->request->post('captcha');
|
||||
|
|
@ -144,13 +144,13 @@ class User extends Frontend
|
|||
*/
|
||||
public function login()
|
||||
{
|
||||
$url = $this->request->request('url', '', 'trim,xss_clean');
|
||||
$url = $this->request->request('url', '', 'url_clean');
|
||||
if ($this->auth->id) {
|
||||
$this->success(__('You\'ve logged in, do not login again'), $url ?: url('user/index'));
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$account = $this->request->post('account');
|
||||
$password = $this->request->post('password');
|
||||
$password = $this->request->post('password', '', null);
|
||||
$keeplogin = (int)$this->request->post('keeplogin');
|
||||
$token = $this->request->post('__token__');
|
||||
$rule = [
|
||||
|
|
@ -270,9 +270,9 @@ class User extends Frontend
|
|||
public function changepwd()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$oldpassword = $this->request->post("oldpassword");
|
||||
$newpassword = $this->request->post("newpassword");
|
||||
$renewpassword = $this->request->post("renewpassword");
|
||||
$oldpassword = $this->request->post("oldpassword", '', null);
|
||||
$newpassword = $this->request->post("newpassword", '', null);
|
||||
$renewpassword = $this->request->post("renewpassword", '', null);
|
||||
$token = $this->request->post('__token__');
|
||||
$rule = [
|
||||
'oldpassword' => 'require|regex:\S{6,30}',
|
||||
|
|
@ -299,7 +299,6 @@ class User extends Frontend
|
|||
$result = $validate->check($data);
|
||||
if (!$result) {
|
||||
$this->error(__($validate->getError()), null, ['token' => $this->request->token()]);
|
||||
return false;
|
||||
}
|
||||
|
||||
$ret = $this->auth->changepwd($newpassword, $oldpassword);
|
||||
|
|
|
|||
|
|
@ -24,26 +24,21 @@
|
|||
<a href="{:url('user/profile')}" class="btn btn-primary pull-right"><i class="fa fa-pencil"></i> {:__('Profile')}</a>
|
||||
</h2>
|
||||
<div class="row user-baseinfo">
|
||||
<div class="col-md-3 col-sm-3 col-xs-2 text-center user-center">
|
||||
<div class="col-md-3 col-sm-3 col-xs-3 text-center user-center">
|
||||
<a href="{:url('user/profile')}" title="{:__('Click to edit')}">
|
||||
<span class="avatar-img"><img src="{$user.avatar|htmlentities|cdnurl}" alt=""></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-9 col-sm-9 col-xs-10">
|
||||
<!-- Content -->
|
||||
<div class="col-md-9 col-sm-9 col-xs-9">
|
||||
<div class="ui-content">
|
||||
<!-- Heading -->
|
||||
<h4><a href="{:url('user/profile')}">{$user.nickname|htmlentities}</a></h4>
|
||||
<!-- Paragraph -->
|
||||
<p class="text-muted">
|
||||
{$user.bio|default=__("This guy hasn't written anything yet")|htmlentities}
|
||||
</p>
|
||||
<!-- Success -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-9 col-sm-9 col-xs-12">
|
||||
<!-- Content -->
|
||||
<div class="ui-content">
|
||||
<div class="basicinfo">
|
||||
<div class="row">
|
||||
|
|
@ -56,12 +51,6 @@
|
|||
<a href="javascript:;" class="viewscore">{$user.score}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-md-2">{:__('Successions')}</div>
|
||||
<div class="col-xs-8 col-md-4">{$user.successions} {:__('Day')}</div>
|
||||
<div class="col-xs-4 col-md-2">{:__('Maxsuccessions')}</div>
|
||||
<div class="col-xs-8 col-md-4">{$user.maxsuccessions} {:__('Day')}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-md-2">{:__('Logintime')}</div>
|
||||
<div class="col-xs-8 col-md-4">{$user.logintime|date="Y-m-d H:i:s",###}</div>
|
||||
|
|
|
|||
|
|
@ -118,8 +118,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group form-footer">
|
||||
<label class="control-label col-xs-12 col-sm-3"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="col-xs-12 col-sm-8 col-sm-offset-3">
|
||||
<button type="submit" class="btn btn-md btn-primary">{:__('Ok')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -132,8 +132,7 @@
|
|||
</div>
|
||||
<div class="form-footer">
|
||||
<div class="form-group" style="margin-bottom:0;">
|
||||
<label class="control-label col-xs-12 col-sm-3"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="col-xs-12 col-sm-8 col-sm-offset-3">
|
||||
<button type="submit" class="btn btn-md btn-primary">{:__('Submit')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -166,8 +165,7 @@
|
|||
</div>
|
||||
<div class="form-footer">
|
||||
<div class="form-group" style="margin-bottom:0;">
|
||||
<label class="control-label col-xs-12 col-sm-3"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="col-xs-12 col-sm-8 col-sm-offset-3">
|
||||
<button type="submit" class="btn btn-md btn-primary">{:__('Submit')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
"topthink/think-installer": "^1.0.14",
|
||||
"topthink/think-queue": "1.1.6",
|
||||
"topthink/think-helper": "^1.0.7",
|
||||
"karsonzhang/fastadmin-addons": "~1.3.2",
|
||||
"karsonzhang/fastadmin-addons": "~1.4.0",
|
||||
"overtrue/pinyin": "^3.0",
|
||||
"phpoffice/phpspreadsheet": "1.19.0",
|
||||
"overtrue/wechat": "^4.6.0",
|
||||
|
|
@ -32,7 +32,11 @@
|
|||
"txthinking/mailer": "^2.0"
|
||||
},
|
||||
"config": {
|
||||
"preferred-install": "dist"
|
||||
"preferred-install": "dist",
|
||||
"allow-plugins": {
|
||||
"topthink/think-installer": true,
|
||||
"easywechat-composer/easywechat-composer": true
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,15 +60,15 @@ class Http
|
|||
} else {
|
||||
$defaults[CURLOPT_CUSTOMREQUEST] = $method;
|
||||
}
|
||||
$defaults[CURLOPT_POSTFIELDS] = $params;
|
||||
$defaults[CURLOPT_POSTFIELDS] = is_array($params) && count(array_filter($params, 'is_array')) > 0 ? $query_string : $params;
|
||||
}
|
||||
|
||||
$defaults[CURLOPT_HEADER] = false;
|
||||
$defaults[CURLOPT_USERAGENT] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.98 Safari/537.36";
|
||||
$defaults[CURLOPT_FOLLOWLOCATION] = true;
|
||||
$defaults[CURLOPT_RETURNTRANSFER] = true;
|
||||
$defaults[CURLOPT_CONNECTTIMEOUT] = 3;
|
||||
$defaults[CURLOPT_TIMEOUT] = 3;
|
||||
$defaults[CURLOPT_CONNECTTIMEOUT] = 10;
|
||||
$defaults[CURLOPT_TIMEOUT] = 10;
|
||||
|
||||
// disable 100-continue
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
|
||||
|
|
@ -133,12 +133,12 @@ class Http
|
|||
}
|
||||
$parts['query'] = isset($parts['query']) && $parts['query'] ? '?' . $parts['query'] : '';
|
||||
//发送socket请求,获得连接句柄
|
||||
$fp = fsockopen($parts['host'], $parts['port'] ?? 80, $errno, $errstr, 3);
|
||||
$fp = fsockopen($parts['host'], $parts['port'] ?? 80, $errno, $errstr, 10);
|
||||
if (!$fp) {
|
||||
return false;
|
||||
}
|
||||
//设置超时时间
|
||||
stream_set_timeout($fp, 3);
|
||||
stream_set_timeout($fp, 10);
|
||||
$out = "{$method} {$parts['path']}{$parts['query']} HTTP/1.1\r\n";
|
||||
$out .= "Host: {$parts['host']}\r\n";
|
||||
$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
|
||||
|
|
|
|||
|
|
@ -970,6 +970,9 @@ form.form-horizontal .control-label {
|
|||
.fixed-table-container .bs-checkbox {
|
||||
min-width: 36px;
|
||||
}
|
||||
.fixed-table-container tr[data-origpos] > td > .tooltip.in {
|
||||
display: none !important;
|
||||
}
|
||||
/*修复nice-validator新版下的一处BUG*/
|
||||
.nice-validator input,
|
||||
.nice-validator select,
|
||||
|
|
@ -1519,6 +1522,14 @@ table.table-nowrap thead > tr > th {
|
|||
border-bottom: 1px solid #eee;
|
||||
border-radius: 0;
|
||||
}
|
||||
.sidebar-menu li.active > a > .fa-angle-left,
|
||||
.sidebar-menu li.active > a > .pull-right-container > .fa-angle-left {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
.sidebar-menu li.treeview-open > a > .fa-angle-left,
|
||||
.sidebar-menu li.treeview-open > a > .pull-right-container > .fa-angle-left {
|
||||
-webkit-transform: rotate(-90deg);
|
||||
|
|
@ -1610,4 +1621,25 @@ table.table-nowrap thead > tr > th {
|
|||
display: block;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.autocontent {
|
||||
position: relative;
|
||||
}
|
||||
.autocontent .autocontent-caret {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
line-height: 1;
|
||||
background: #eee;
|
||||
color: #ddd;
|
||||
vertical-align: middle;
|
||||
padding: 0 5px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.autocontent .autocontent-caret:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
/*# sourceMappingURL=backend.css.map */
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -317,6 +317,10 @@ a:focus {
|
|||
height: 60px;
|
||||
line-height: 27px;
|
||||
}
|
||||
.navbar-white .navbar-brand {
|
||||
height: 60px;
|
||||
line-height: 27px;
|
||||
}
|
||||
.navbar-white .navbar-nav > li > a {
|
||||
height: 60px;
|
||||
line-height: 27px;
|
||||
|
|
@ -652,6 +656,20 @@ form.form-horizontal .control-label {
|
|||
padding: 15px;
|
||||
min-height: 300px;
|
||||
}
|
||||
.n-bootstrap .n-right {
|
||||
margin-top: 0;
|
||||
top: -20px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
.n-bootstrap .n-right .msg-wrap {
|
||||
position: relative;
|
||||
}
|
||||
.n-bootstrap .col-xs-12 > .n-right .msg-wrap {
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
.nav-pills > li {
|
||||
margin-right: 5px;
|
||||
|
|
@ -1094,4 +1112,25 @@ main.content {
|
|||
display: block;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.autocontent {
|
||||
position: relative;
|
||||
}
|
||||
.autocontent .autocontent-caret {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
line-height: 1;
|
||||
background: #eee;
|
||||
color: #ddd;
|
||||
vertical-align: middle;
|
||||
padding: 0 5px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.autocontent .autocontent-caret:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
/*# sourceMappingURL=frontend.css.map */
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -2481,6 +2481,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-blue .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-blue .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #555299;
|
||||
border-left-color: #555299;
|
||||
}
|
||||
.skin-black-blue .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
@ -2717,6 +2722,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-purple .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-purple .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #555299;
|
||||
border-left-color: #555299;
|
||||
}
|
||||
.skin-black-purple .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
@ -2953,6 +2963,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-green .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-green .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #555299;
|
||||
border-left-color: #555299;
|
||||
}
|
||||
.skin-black-green .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
@ -3189,6 +3204,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-red .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-red .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #555299;
|
||||
border-left-color: #555299;
|
||||
}
|
||||
.skin-black-red .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
@ -3425,6 +3445,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-yellow .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-yellow .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #555299;
|
||||
border-left-color: #555299;
|
||||
}
|
||||
.skin-black-yellow .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
@ -3661,6 +3686,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-pink .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-pink .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #555299;
|
||||
border-left-color: #555299;
|
||||
}
|
||||
.skin-black-pink .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-blue .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-blue .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #181f23;
|
||||
border-left-color: #181f23;
|
||||
}
|
||||
.skin-black-blue .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-green .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-green .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #181f23;
|
||||
border-left-color: #181f23;
|
||||
}
|
||||
.skin-black-green .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-pink .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-pink .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #181f23;
|
||||
border-left-color: #181f23;
|
||||
}
|
||||
.skin-black-pink .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-purple .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-purple .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #181f23;
|
||||
border-left-color: #181f23;
|
||||
}
|
||||
.skin-black-purple .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-red .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-red .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #181f23;
|
||||
border-left-color: #181f23;
|
||||
}
|
||||
.skin-black-red .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,11 @@
|
|||
background: transparent;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
.skin-black-yellow .sidebar-menu li.treeview.active > a,
|
||||
.skin-black-yellow .sidebar-menu li.treeview.treeview-open > a {
|
||||
background-color: #181f23;
|
||||
border-left-color: #181f23;
|
||||
}
|
||||
.skin-black-yellow .sidebar-menu .treeview-menu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -468,7 +468,7 @@ function _init() {
|
|||
//Fix the layout in case the sidebar stretches over the height of the window
|
||||
//_this.layout.fix();
|
||||
});
|
||||
checkElement.parent("li").removeClass("active");
|
||||
// checkElement.parent("li").removeClass("active");
|
||||
checkElement.parent("li").removeClass('treeview-open');
|
||||
}
|
||||
//If the menu is not visible
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ define(['fast', 'template', 'moment'], function (Fast, Template, Moment) {
|
|||
}
|
||||
//tooltip和popover
|
||||
if (!('ontouchstart' in document.documentElement)) {
|
||||
$('body').tooltip({selector: '[data-toggle="tooltip"]'});
|
||||
$('body').tooltip({selector: '[data-toggle="tooltip"]', trigger: 'hover'});
|
||||
}
|
||||
$('body').popover({selector: '[data-toggle="popover"]'});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,12 +73,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
Template.helper("Moment", Moment);
|
||||
Template.helper("addons", Config['addons']);
|
||||
|
||||
$("#faupload-addon").data("params", function () {
|
||||
$("#faupload-addon").data("params", function (files, xhr) {
|
||||
var userinfo = Controller.api.userinfo.get();
|
||||
return {
|
||||
uid: userinfo ? userinfo.id : '',
|
||||
token: userinfo ? userinfo.token : '',
|
||||
version: Config.faversion
|
||||
version: Config.faversion,
|
||||
force: (files[0].force || false) ? 1 : 0
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -92,7 +93,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
uid: userinfo ? userinfo.id : '',
|
||||
token: userinfo ? userinfo.token : '',
|
||||
domain: Config.domain,
|
||||
version: Config.faversion
|
||||
version: Config.faversion,
|
||||
sid: Controller.api.sid()
|
||||
});
|
||||
return params;
|
||||
},
|
||||
|
|
@ -113,7 +115,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
align: 'left',
|
||||
formatter: Controller.api.formatter.title
|
||||
},
|
||||
{field: 'intro', title: __('Intro'), operate: 'LIKE', align: 'left', class: 'visible-lg'},
|
||||
{
|
||||
field: 'intro',
|
||||
title: __('Intro'),
|
||||
operate: 'LIKE',
|
||||
align: 'left',
|
||||
class: 'visible-lg',
|
||||
formatter: Controller.api.formatter.intro
|
||||
},
|
||||
{
|
||||
field: 'author',
|
||||
title: __('Author'),
|
||||
|
|
@ -187,7 +196,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
|
||||
// 离线安装
|
||||
require(['upload'], function (Upload) {
|
||||
Upload.api.upload("#faupload-addon", function (data, ret) {
|
||||
Upload.api.upload("#faupload-addon", function (data, ret, up, file) {
|
||||
Config['addons'][data.addon.name] = data.addon;
|
||||
var addon = data.addon;
|
||||
var testdata = data.addon.testdata;
|
||||
|
|
@ -215,7 +224,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
});
|
||||
});
|
||||
return false;
|
||||
}, function (data, ret) {
|
||||
}, function (data, ret, up, file) {
|
||||
if (ret.msg && ret.msg.match(/(login|登录)/g)) {
|
||||
return Layer.alert(ret.msg, {
|
||||
title: __('Warning'),
|
||||
|
|
@ -224,6 +233,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
$(".btn-userinfo").trigger("click");
|
||||
}
|
||||
});
|
||||
} else if (ret.code === -1) {
|
||||
Layer.confirm(__('Upgrade tips', data.title), {title: __('Warmtips')}, function (index, layero) {
|
||||
up.removeFile(file);
|
||||
file.force = true;
|
||||
up.uploadFile(file);
|
||||
Layer.close(index);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -231,10 +248,16 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
$(document).on("mousedown", "#faupload-addon", function (e) {
|
||||
var userinfo = Controller.api.userinfo.get();
|
||||
var uid = userinfo ? userinfo.id : 0;
|
||||
var uploadBtn = Upload.list['faupload-addon'];
|
||||
|
||||
if (parseInt(uid) === 0) {
|
||||
uploadBtn.disable();
|
||||
$(".btn-userinfo").trigger("click");
|
||||
return false;
|
||||
} else {
|
||||
if (uploadBtn.disabled) {
|
||||
uploadBtn.enable();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -299,14 +322,64 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
Fast.api.ajax({
|
||||
url: Config.api_url + '/user/logintpl',
|
||||
type: 'post',
|
||||
loading: false,
|
||||
data: {
|
||||
version: Config.faversion
|
||||
version: Config.faversion,
|
||||
sid: Controller.api.sid()
|
||||
}
|
||||
}, function (tpldata, ret) {
|
||||
Layer.open({
|
||||
content: Template.render(tpldata, {}),
|
||||
zIndex: 99,
|
||||
area: area,
|
||||
title: __('Login'),
|
||||
resize: false,
|
||||
btn: [__('Login')],
|
||||
yes: function (index, layero) {
|
||||
var data = $("form", layero).serializeArray();
|
||||
data.push({name: "faversion", value: Config.faversion});
|
||||
data.push({name: "sid", value: Controller.api.sid()});
|
||||
Fast.api.ajax({
|
||||
url: Config.api_url + '/user/login',
|
||||
type: 'post',
|
||||
data: data
|
||||
}, function (data, ret) {
|
||||
Controller.api.userinfo.set(data);
|
||||
Layer.closeAll();
|
||||
Layer.alert(ret.msg, {title: __('Warning'), icon: 1});
|
||||
return false;
|
||||
}, function (data, ret) {
|
||||
});
|
||||
},
|
||||
success: function (layero, index) {
|
||||
this.checkEnterKey = function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
$(".layui-layer-btn0").trigger("click");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
$(document).on('keydown', this.checkEnterKey);
|
||||
},
|
||||
end: function () {
|
||||
$(document).off('keydown', this.checkEnterKey);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
Fast.api.ajax({
|
||||
url: Config.api_url + '/user/userinfotpl',
|
||||
type: 'post',
|
||||
data: {
|
||||
uid: userinfo.id,
|
||||
token: userinfo.token,
|
||||
version: Config.faversion,
|
||||
sid: Controller.api.sid()
|
||||
}
|
||||
}, function (tpldata, ret) {
|
||||
Layer.open({
|
||||
content: Template.render(tpldata, userinfo),
|
||||
area: area,
|
||||
title: __('Login FastAdmin'),
|
||||
resize: false,
|
||||
btn: [__('Login')],
|
||||
|
|
@ -314,9 +387,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
var data = $("form", layero).serializeArray();
|
||||
data.push({name: "faversion", value: Config.faversion});
|
||||
Fast.api.ajax({
|
||||
url: Config.api_url + '/user/login',
|
||||
type: 'post',
|
||||
data: data
|
||||
url: Config.api_url + '/user/logout',
|
||||
data: {
|
||||
uid: userinfo.id,
|
||||
token: userinfo.token,
|
||||
version: Config.faversion,
|
||||
sid: Controller.api.sid()
|
||||
}
|
||||
}, function (data, ret) {
|
||||
Controller.api.userinfo.set(data);
|
||||
Layer.closeAll();
|
||||
|
|
@ -610,16 +687,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
var uid = userinfo ? userinfo.id : 0;
|
||||
|
||||
if (parseInt(uid) === 0) {
|
||||
return Layer.alert(__('Not login tips'), {
|
||||
title: __('Warning'),
|
||||
btn: [__('Login now')],
|
||||
yes: function (index, layero) {
|
||||
$(".btn-userinfo").trigger("click", name, version);
|
||||
},
|
||||
btn2: function () {
|
||||
install(name, version, false);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
install(name, version, false);
|
||||
});
|
||||
|
|
@ -632,6 +701,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
return false;
|
||||
}
|
||||
Template.helper("__", __);
|
||||
tables = [];
|
||||
Layer.confirm(Template("uninstalltpl", {addon: Config['addons'][name]}), {focusBtn: false, title: __("Warning")}, function (index, layero) {
|
||||
uninstall(name, false, $("input[name='droptables']", layero).prop("checked"));
|
||||
});
|
||||
|
|
@ -659,7 +729,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
}
|
||||
var version = $(this).data("version");
|
||||
|
||||
Layer.confirm(__('Upgrade tips', Config['addons'][name].title), function (index, layero) {
|
||||
Layer.confirm(__('Upgrade tips', Config['addons'][name].title), {title: __('Warmtips')}, function (index, layero) {
|
||||
upgrade(name, version);
|
||||
});
|
||||
});
|
||||
|
|
@ -709,12 +779,15 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
if ($(".btn-switch.active").data("type") == "local") {
|
||||
// return value;
|
||||
}
|
||||
var title = '<a class="title" href="' + row.url + '" data-toggle="tooltip" title="' + __('View addon home page') + '" target="_blank">' + value + '</a>';
|
||||
var title = '<a class="title" href="' + row.url + '" data-toggle="tooltip" title="' + __('View addon home page') + '" target="_blank"><span class="' + Fast.api.escape(row.color) + '">' + value + '</span></a>';
|
||||
if (row.screenshots && row.screenshots.length > 0) {
|
||||
title += ' <a href="javascript:;" data-index="' + index + '" class="view-screenshots text-success" title="' + __('View addon screenshots') + '" data-toggle="tooltip"><i class="fa fa-image"></i></a>';
|
||||
}
|
||||
return title;
|
||||
},
|
||||
intro: function (value, row, index) {
|
||||
return row.intro + (row.extend ? "<a href='" + Fast.api.escape(row.extend[1]) + "' class='" + Fast.api.escape(row.extend[2]) + "'>" + Fast.api.escape(row.extend[0]) + "</a>" : "");
|
||||
},
|
||||
operate: function (value, row, index) {
|
||||
return Template("operatetpl", {item: row, index: index});
|
||||
},
|
||||
|
|
@ -777,6 +850,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
|
|||
}
|
||||
}
|
||||
},
|
||||
sid: function () {
|
||||
var sid = $.cookie('fastadmin_sid');
|
||||
if (!sid) {
|
||||
sid = Math.random().toString(20).substr(2, 12);
|
||||
$.cookie('fastadmin_sid', sid);
|
||||
}
|
||||
return sid;
|
||||
},
|
||||
refresh: function (table, name) {
|
||||
//刷新左侧边栏
|
||||
Fast.api.refreshmenu();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
|||
{field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '模糊搜索'},
|
||||
{field: 'url', title: __('Url'), formatter: Table.api.formatter.url},
|
||||
{field: 'ip', title: __('IP'), events: Table.api.events.ip, formatter: Table.api.formatter.search},
|
||||
{field: 'browser', title: __('Browser'), operate: false, formatter: Controller.api.formatter.browser},
|
||||
{field: 'createtime', title: __('Create time'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true},
|
||||
{
|
||||
field: 'operate', title: __('Operate'), table: table,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
|
|||
if (val != '') {
|
||||
$("ul.sidebar-menu li a[addtabs]:not([href^='javascript:;'])").each(function () {
|
||||
if ($("span:first", this).text().indexOf(val) > -1 || $(this).attr("py").indexOf(val) > -1 || $(this).attr("pinyin").indexOf(val) > -1) {
|
||||
html.push('<a data-url="' + $(this).attr("href") + '" href="javascript:;">' + $("span:first", this).text() + '</a>');
|
||||
html.push('<a data-url="' + ($(this).attr("url") || $(this).attr("href")) + '" href="javascript:;">' + $("span:first", this).text() + '</a>');
|
||||
if (html.length >= 100) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -67,6 +67,7 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
|
|||
var visible = nextul.is(":visible");
|
||||
if (nextul.length == 0) {
|
||||
$(this).parents("li").addClass("active");
|
||||
$(this).closest(".treeview").addClass("treeview-open");
|
||||
} else {
|
||||
}
|
||||
e.stopPropagation();
|
||||
|
|
@ -333,11 +334,13 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
|
|||
|
||||
// 切换菜单栏
|
||||
$(document).on("click", ".sidebar-toggle", function () {
|
||||
setTimeout(function(){
|
||||
var value = $("body").hasClass("sidebar-collapse") ? 1 : 0;
|
||||
setTimeout(function () {
|
||||
$(window).trigger("resize");
|
||||
}, 300);
|
||||
createCookie('sidebar_collapse', value);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
// 切换简洁模式菜单
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
setTimeout(function () {
|
||||
that.onCommonSearch();
|
||||
}, 10);
|
||||
}, 1);
|
||||
});
|
||||
|
||||
};
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
htmlForm.push('<div class="row">');
|
||||
for (var i in pColumns) {
|
||||
var vObjCol = pColumns[i];
|
||||
if (!vObjCol.checkbox && vObjCol.field !== 'operate' && vObjCol.searchable && vObjCol.operate !== false) {
|
||||
if (!vObjCol.checkbox && !vObjCol.radio && vObjCol.field && vObjCol.field !== 'operate' && vObjCol.searchable && vObjCol.operate !== false) {
|
||||
var query = Fast.api.query(vObjCol.field);
|
||||
var operate = Fast.api.query(vObjCol.field + "-operate");
|
||||
|
||||
|
|
|
|||
|
|
@ -103,8 +103,8 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefine
|
|||
//获取修复后可访问的cdn链接
|
||||
cdnurl: function (url, domain) {
|
||||
var rule = new RegExp("^((?:[a-z]+:)?\\/\\/|data:image\\/)", "i");
|
||||
if(typeof domain === 'undefined'){
|
||||
var cdnurl = Config.upload.cdnurl;
|
||||
if (typeof domain === 'undefined' || domain === true || cdnurl.indexOf("/") === 0) {
|
||||
url = rule.test(url) || (cdnurl && url.indexOf(cdnurl) === 0) ? url : cdnurl + url;
|
||||
}
|
||||
if (domain && !rule.test(url)) {
|
||||
|
|
@ -118,6 +118,8 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefine
|
|||
if (!url) {
|
||||
url = window.location.href;
|
||||
}
|
||||
if (!name)
|
||||
return '';
|
||||
name = name.replace(/[\[\]]/g, "\\$&");
|
||||
var regex = new RegExp("[?&/]" + name + "([=/]([^&#/?]*)|&|#|$)"),
|
||||
results = regex.exec(url);
|
||||
|
|
@ -276,6 +278,18 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefine
|
|||
time: 2000
|
||||
}, callback);
|
||||
},
|
||||
escape: function (text) {
|
||||
if (typeof text === 'string') {
|
||||
return text
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
.replace(/`/g, '`');
|
||||
}
|
||||
return text;
|
||||
},
|
||||
toastr: Toastr,
|
||||
layer: Layer
|
||||
},
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, und
|
|||
Layer.open({
|
||||
type: 1,
|
||||
title: __('Reset password'),
|
||||
area: [Math.min($(window).width(), 450) + "px", "355px"],
|
||||
area: [$(window).width() < 450 ? ($(window).width() - 10) + "px" : "450px", "355px"],
|
||||
content: content,
|
||||
success: function (layero) {
|
||||
var rule = $("#resetpwd-form input[name='captcha']").data("rule");
|
||||
|
|
@ -98,7 +98,7 @@ define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, und
|
|||
Layer.open({
|
||||
type: 1,
|
||||
title: "修改",
|
||||
area: [Math.min($(window).width(), 400) + "px", "250px"],
|
||||
area: [$(window).width() < 450 ? ($(window).width() - 10) + "px" : "450px", "355px"],
|
||||
content: content,
|
||||
success: function (layero) {
|
||||
var form = $("form", layero);
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -12,8 +12,6 @@ require.config({
|
|||
'form': 'require-form',
|
||||
'table': 'require-table',
|
||||
'upload': 'require-upload',
|
||||
'drag': 'jquery.drag.min',
|
||||
'drop': 'jquery.drop.min',
|
||||
'dropzone': 'dropzone.min',
|
||||
'echarts': 'echarts.min',
|
||||
'echarts-theme': 'echarts-theme',
|
||||
|
|
|
|||
|
|
@ -133,7 +133,11 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
|
|||
});
|
||||
$(form).on("reset", function () {
|
||||
setTimeout(function () {
|
||||
$('.selectpage', form).selectPageClear();
|
||||
$(".selectpage", form).each(function () {
|
||||
var selectpage = $(this).data("selectPageObject");
|
||||
selectpage.elem.hidden.val($(this).val());
|
||||
$(this).selectPageRefresh();
|
||||
});
|
||||
}, 1);
|
||||
});
|
||||
}
|
||||
|
|
@ -321,10 +325,15 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
|
|||
var result = template ? [] : {};
|
||||
$.each(data, function (i, j) {
|
||||
if (j) {
|
||||
if (!template) {
|
||||
if (j.key !== '') {
|
||||
var keys = Object.keys(j);
|
||||
if (keys.indexOf("value") > -1 && (keys.length === 1 || (keys.length === 2 && keys.indexOf("key") > -1))) {
|
||||
if (keys.length === 2) {
|
||||
if (j.key != '') {
|
||||
result['__PLACEHOLDKEY__' + j.key] = j.value;
|
||||
}
|
||||
} else {
|
||||
result.push(j.value);
|
||||
}
|
||||
} else {
|
||||
result.push(j);
|
||||
}
|
||||
|
|
@ -366,6 +375,12 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
|
|||
return obj;
|
||||
};
|
||||
var fieldlist = $(".fieldlist", form);
|
||||
//表单重置
|
||||
form.on("reset", function () {
|
||||
setTimeout(function () {
|
||||
fieldlist.trigger("fa.event.refreshfieldlist");
|
||||
});
|
||||
});
|
||||
//监听文本框改变事件
|
||||
$(document).on('change keyup changed', ".fieldlist input,.fieldlist textarea,.fieldlist select", function () {
|
||||
var container = $(this).closest(".fieldlist");
|
||||
|
|
@ -375,7 +390,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
|
|||
fieldlist.on("click", ".btn-append,.append", function (e, row) {
|
||||
var container = $(this).closest(".fieldlist");
|
||||
append(container, row);
|
||||
// refresh(container);
|
||||
refresh(container);
|
||||
});
|
||||
//移除控制(点击按钮)
|
||||
fieldlist.on("click", ".btn-remove", function () {
|
||||
|
|
@ -467,9 +482,9 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
|
|||
|
||||
},
|
||||
slider: function (form) {
|
||||
if ($(".slider", form).length > 0) {
|
||||
if ($("[data-role='slider'],input.slider", form).length > 0) {
|
||||
require(['bootstrap-slider'], function () {
|
||||
$('.slider').removeClass('hidden').css('width', function (index, value) {
|
||||
$("[data-role='slider'],input.slider").removeClass('hidden').css('width', function (index, value) {
|
||||
return $(this).parents('.form-control').width();
|
||||
}).slider().on('slide', function (ev) {
|
||||
var data = $(this).data();
|
||||
|
|
@ -484,6 +499,11 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
|
|||
if ($("[data-role='tagsinput']", form).length > 0) {
|
||||
require(['tagsinput', 'autocomplete'], function () {
|
||||
$("[data-role='tagsinput']").tagsinput();
|
||||
form.on("reset", function () {
|
||||
setTimeout(function () {
|
||||
$("[data-role='tagsinput']").tagsinput('reset');
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
@ -504,13 +524,27 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
|
|||
var baseregex = /^([a-z0-9\_]+)([>|<|=|\!]=?)(.*)$/i, strregex = /^('|")(.*)('|")$/, regregex = /^regex:(.*)$/;
|
||||
// @formatter:off
|
||||
var operator_result = {
|
||||
'>': function(a, b) { return a > b; },
|
||||
'>=': function(a, b) { return a >= b; },
|
||||
'<': function(a, b) { return a < b; },
|
||||
'<=': function(a, b) { return a <= b; },
|
||||
'==': function(a, b) { return a == b; },
|
||||
'!=': function(a, b) { return a != b; },
|
||||
'in': function(a, b) { return b.split(/\,/).indexOf(a) > -1; },
|
||||
'>': function (a, b) {
|
||||
return a > b;
|
||||
},
|
||||
'>=': function (a, b) {
|
||||
return a >= b;
|
||||
},
|
||||
'<': function (a, b) {
|
||||
return a < b;
|
||||
},
|
||||
'<=': function (a, b) {
|
||||
return a <= b;
|
||||
},
|
||||
'==': function (a, b) {
|
||||
return a == b;
|
||||
},
|
||||
'!=': function (a, b) {
|
||||
return a != b;
|
||||
},
|
||||
'in': function (a, b) {
|
||||
return b.split(/\,/).indexOf(a) > -1;
|
||||
},
|
||||
'regex': function (a, b) {
|
||||
var regParts = b.match(/^\/(.*?)\/([gim]*)$/);
|
||||
var regexp = regParts ? new RegExp(regParts[1], regParts[2]) : new RegExp(b);
|
||||
|
|
@ -558,10 +592,10 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
|
|||
});
|
||||
return success === conditionArr.length;
|
||||
};
|
||||
form.on("keyup change click configchange", "input,select", function () {
|
||||
form.on("keyup change click configchange", "input,textarea,select", function () {
|
||||
$("[data-favisible][data-favisible!='']", form).each(function () {
|
||||
var visible = $(this).data("favisible");
|
||||
var groupArr = visible.split(/\|\|/);
|
||||
var groupArr = visible ? visible.toString().split(/\|\|/) : [];
|
||||
var success = 0;
|
||||
$.each(groupArr, function (i, j) {
|
||||
if (checkCondition(j)) {
|
||||
|
|
@ -578,10 +612,13 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
|
|||
|
||||
//追加上忽略元素
|
||||
setTimeout(function () {
|
||||
form.data('validator').options.ignore += ((form.data('validator').options.ignore ? ',' : '') + '[data-favisible] :hidden,[data-favisible]:hidden');
|
||||
var validator = form.data('validator');
|
||||
if (validator) {
|
||||
validator.options.ignore += ((validator.options.ignore ? ',' : '') + '.hidden[data-favisible] :hidden,.hidden[data-favisible]:hidden');
|
||||
}
|
||||
}, 0);
|
||||
|
||||
$("input,select", form).trigger("configchange");
|
||||
$("input,textarea,select", form).trigger("configchange");
|
||||
}
|
||||
},
|
||||
api: {
|
||||
|
|
|
|||
|
|
@ -6,14 +6,12 @@ require.config({
|
|||
main: 'moment'
|
||||
}],
|
||||
//在打包压缩时将会把include中的模块合并到主文件中
|
||||
include: ['css', 'layer', 'toastr', 'fast', 'frontend', 'frontend-init', 'table', 'form', 'dragsort', 'drag', 'drop', 'selectpage'],
|
||||
include: ['css', 'layer', 'toastr', 'fast', 'frontend', 'frontend-init', 'table', 'form', 'dragsort', 'selectpage'],
|
||||
paths: {
|
||||
'lang': "empty:",
|
||||
'form': 'require-form',
|
||||
'table': 'require-table',
|
||||
'upload': 'require-upload',
|
||||
'drag': 'jquery.drag.min',
|
||||
'drop': 'jquery.drop.min',
|
||||
'dropzone': 'dropzone.min',
|
||||
'echarts': 'echarts.min',
|
||||
'echarts-theme': 'echarts-theme',
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ define(['jquery', 'bootstrap'], function ($, undefined) {
|
|||
titleForm: '', //为空则不显示标题,不定义默认显示:普通搜索
|
||||
idTable: 'commonTable',
|
||||
showExport: true,
|
||||
exportDataType: "auto",
|
||||
exportDataType: "auto", //支持auto,selected,all 当设定为auto时自动时有选中则导出选中,没有选中则导出全部
|
||||
exportTypes: ['json', 'xml', 'csv', 'txt', 'doc', 'excel'],
|
||||
exportOptions: {
|
||||
fileName: 'export_' + Moment().format("YYYY-MM-DD"),
|
||||
|
|
@ -51,6 +51,7 @@ define(['jquery', 'bootstrap'], function ($, undefined) {
|
|||
checkOnInit: true, //是否在初始化时判断
|
||||
escape: true, //是否对内容进行转义
|
||||
fixDropdownPosition: true, //是否修复下拉的定位
|
||||
dragCheckboxMultiselect: true, //拖拽时复选框是否多选模式
|
||||
selectedIds: [],
|
||||
selectedData: [],
|
||||
extend: {
|
||||
|
|
@ -90,14 +91,14 @@ define(['jquery', 'bootstrap'], function ($, undefined) {
|
|||
name: 'edit',
|
||||
icon: 'fa fa-pencil',
|
||||
title: __('Edit'),
|
||||
extend: 'data-toggle="tooltip"',
|
||||
extend: 'data-toggle="tooltip" data-container="body"',
|
||||
classname: 'btn btn-xs btn-success btn-editone'
|
||||
},
|
||||
del: {
|
||||
name: 'del',
|
||||
icon: 'fa fa-trash',
|
||||
title: __('Del'),
|
||||
extend: 'data-toggle="tooltip"',
|
||||
extend: 'data-toggle="tooltip" data-container="body"',
|
||||
classname: 'btn btn-xs btn-danger btn-delone'
|
||||
},
|
||||
dragsort: {
|
||||
|
|
@ -197,6 +198,8 @@ define(['jquery', 'bootstrap'], function ($, undefined) {
|
|||
//当刷新表格时
|
||||
table.on('refresh.bs.table', function (e, settings, data) {
|
||||
$(Table.config.refreshbtn, toolbar).find(".fa").addClass("fa-spin");
|
||||
//移除指定浮动弹窗
|
||||
$(".layui-layer-autocontent").remove();
|
||||
});
|
||||
//当执行搜索时
|
||||
table.on('search.bs.table common-search.bs.table', function (e, settings, data) {
|
||||
|
|
@ -220,39 +223,82 @@ define(['jquery', 'bootstrap'], function ($, undefined) {
|
|||
table.on('post-body.bs.table', function (e, data) {
|
||||
$(Table.config.refreshbtn, toolbar).find(".fa").removeClass("fa-spin");
|
||||
if ($(Table.config.checkboxtd + ":first", table).find("input[type='checkbox'][data-index]").length > 0) {
|
||||
// 拖拽选择,需要重新绑定事件
|
||||
require(['drag', 'drop'], function () {
|
||||
var checkboxtd = $(Table.config.checkboxtd, table);
|
||||
checkboxtd.drag("start", function (ev, dd) {
|
||||
return $('<div class="selection" />').css('opacity', .65).appendTo(document.body);
|
||||
}).drag(function (ev, dd) {
|
||||
setTimeout(function () {
|
||||
$(dd.proxy).css({
|
||||
top: Math.min(ev.pageY, dd.startY),
|
||||
left: Math.min(ev.pageX, dd.startX),
|
||||
height: Math.abs(ev.pageY - dd.startY),
|
||||
width: Math.abs(ev.pageX - dd.startX)
|
||||
});
|
||||
}, 0);
|
||||
}).drag("end", function (ev, dd) {
|
||||
$(dd.proxy).remove();
|
||||
});
|
||||
checkboxtd.drop("start", function () {
|
||||
Table.api.toggleattr(this);
|
||||
}).drop(function () {
|
||||
// Table.api.toggleattr(this);
|
||||
}).drop("end", function (e) {
|
||||
var that = this;
|
||||
setTimeout(function () {
|
||||
if (e.type === 'mousemove') {
|
||||
Table.api.toggleattr(that);
|
||||
//拖拽选择复选框
|
||||
var posx, posy, dragdiv, drag = false, prepare = false;
|
||||
var mousemove = function (e) {
|
||||
if (drag) {
|
||||
var left = Math.min(e.pageX, posx);
|
||||
var top = Math.min(e.pageY, posy);
|
||||
var width = Math.abs(posx - e.pageX);
|
||||
var height = Math.abs(posy - e.pageY);
|
||||
dragdiv.css({left: left + "px", top: top + "px", width: width + "px", height: height + "px"});
|
||||
var dragrect = {x: left, y: top, width: width, height: height};
|
||||
$(Table.config.checkboxtd, table).each(function () {
|
||||
var checkbox = $("input:checkbox", this);
|
||||
var tdrect = this.getBoundingClientRect();
|
||||
tdrect.x += document.documentElement.scrollLeft;
|
||||
tdrect.y += document.documentElement.scrollTop;
|
||||
|
||||
var td_min_x = tdrect.x;
|
||||
var td_min_y = tdrect.y;
|
||||
var td_max_x = tdrect.x + tdrect.width;
|
||||
var td_max_y = tdrect.y + tdrect.height;
|
||||
|
||||
var drag_min_x = dragrect.x;
|
||||
var drag_min_y = dragrect.y;
|
||||
var drag_max_x = dragrect.x + dragrect.width;
|
||||
var drag_max_y = dragrect.y + dragrect.height;
|
||||
var overlapped = td_min_x <= drag_max_x && td_max_x >= drag_min_x && td_min_y <= drag_max_y && td_max_y >= drag_min_y;
|
||||
if (overlapped) {
|
||||
if (!$(this).hasClass("overlaped")) {
|
||||
$(this).addClass("overlaped");
|
||||
checkbox.trigger("click");
|
||||
}
|
||||
} else {
|
||||
if ($(this).hasClass("overlaped")) {
|
||||
$(this).removeClass("overlaped");
|
||||
checkbox.trigger("click");
|
||||
}
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
$.drop({
|
||||
multi: true
|
||||
});
|
||||
}
|
||||
};
|
||||
var selectstart = function () {
|
||||
return false;
|
||||
};
|
||||
var mouseup = function () {
|
||||
if (drag) {
|
||||
$(document).off("mousemove", mousemove);
|
||||
$(document).off("selectstart", selectstart);
|
||||
dragdiv.remove();
|
||||
}
|
||||
drag = false;
|
||||
prepare = false;
|
||||
$(document.body).css({'MozUserSelect': '', 'webkitUserSelect': ''}).attr('unselectable', 'off');
|
||||
};
|
||||
|
||||
$(Table.config.checkboxtd, table).on("mousedown", function (e) {
|
||||
//禁止鼠标右键事件和文本框
|
||||
if (e.button === 2 || $(e.target).is("input")) {
|
||||
return false;
|
||||
}
|
||||
posx = e.pageX;
|
||||
posy = e.pageY;
|
||||
prepare = true;
|
||||
}).on("mousemove", function (e) {
|
||||
if (prepare && !drag) {
|
||||
drag = true;
|
||||
dragdiv = $("<div />");
|
||||
dragdiv.css({position: 'absolute', width: 0, height: 0, border: "1px dashed blue", background: "#0029ff", left: e.pageX + "px", top: e.pageY + "px", opacity: .1});
|
||||
dragdiv.appendTo(document.body);
|
||||
$(document.body).css({'MozUserSelect': 'none', 'webkitUserSelect': 'none'}).attr('unselectable', 'on');
|
||||
$(document).on("mousemove", mousemove).on("mouseup", mouseup).on("selectstart", selectstart);
|
||||
if (options.dragCheckboxMultiselect) {
|
||||
$(Table.config.checkboxtd, table).removeClass("overlaped");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
var exportDataType = options.exportDataType;
|
||||
|
|
@ -282,23 +328,40 @@ define(['jquery', 'bootstrap'], function ($, undefined) {
|
|||
options.selectedIds = selectedIds;
|
||||
options.selectedData = selectedData;
|
||||
}
|
||||
|
||||
//如果导出类型为auto时则自动判断
|
||||
if (exportDataType === 'auto') {
|
||||
options.exportDataType = selectedIds.length > 0 ? 'selected' : 'all';
|
||||
if ($(".export .exporttips").length === 0) {
|
||||
$(".export .dropdown-menu").prepend("<li class='exporttips alert alert-warning-light mb-0 no-border p-2'></li>")
|
||||
}
|
||||
$(".export .exporttips").html("导出记录:" + (selectedIds.length > 0 ? "选中" : "全部"));
|
||||
|
||||
}
|
||||
$(Table.config.disabledbtn, toolbar).toggleClass('disabled', !options.selectedIds.length);
|
||||
});
|
||||
// 提交通用搜索时判断是否和Tabs筛选一致
|
||||
table.on('common-search.bs.table', function (e, setting, query) {
|
||||
var tabs = $('.panel-heading [data-field]', table.closest(".panel-intro"));
|
||||
var field = tabs.data("field");
|
||||
var value = $("li.active > a", tabs).data("value");
|
||||
if (query.filter && typeof query.filter[field] !== 'undefined' && query.filter[field] != value) {
|
||||
$("li", tabs).removeClass("active");
|
||||
$("li > a[data-value='" + query.filter[field] + "']", tabs).parent().addClass("active");
|
||||
}
|
||||
});
|
||||
// 绑定TAB事件
|
||||
$('.panel-heading [data-field] a[data-toggle="tab"]', table.closest(".panel-intro")).on('shown.bs.tab', function (e) {
|
||||
var field = $(this).closest("[data-field]").data("field");
|
||||
var value = $(this).data("value");
|
||||
var object = $("[name='" + field + "']", table.closest(".bootstrap-table").find(".commonsearch-table"));
|
||||
if (object.prop('tagName') == "SELECT") {
|
||||
if (object.prop('tagName') === "SELECT") {
|
||||
$("option[value='" + value + "']", object).prop("selected", true);
|
||||
} else {
|
||||
object.val(value);
|
||||
}
|
||||
table.trigger("uncheckbox");
|
||||
table.bootstrapTable('getOptions').totalRows = 0;
|
||||
table.bootstrapTable('refresh', {pageNumber: 1});
|
||||
return false;
|
||||
});
|
||||
|
|
@ -677,25 +740,25 @@ define(['jquery', 'bootstrap'], function ($, undefined) {
|
|||
images: function (value, row, index) {
|
||||
value = value == null || value.length === 0 ? '' : value.toString();
|
||||
var classname = typeof this.classname !== 'undefined' ? this.classname : 'img-sm img-center';
|
||||
var arr = value !== '' ? value.split(',') : [];
|
||||
var arr = value !== '' ? (value.indexOf('data:image/') === -1 ? value.split(',') : [value]) : [];
|
||||
var html = [];
|
||||
var url;
|
||||
$.each(arr, function (i, value) {
|
||||
value = value ? value : '/assets/img/blank.gif';
|
||||
url = Fast.api.cdnurl(value, true);
|
||||
|
||||
url = url.match(/^(\/|data:image\\)/) ? url : url + Config.upload.thumbstyle;
|
||||
html.push('<a href="javascript:"><img class="' + classname + '" src="' + url + '" width="30" height="30" /></a>');
|
||||
//匹配本地、data:image、或已包含标识符首字符
|
||||
url = !Config.upload.thumbstyle || url.match(/^(\/|data:image\/)/) || url.indexOf(Config.upload.thumbstyle.substring(0, 1)) > -1 ? url : url + Config.upload.thumbstyle;
|
||||
html.push('<a href="javascript:"><img class="' + classname + '" src="' + url + '" /></a>');
|
||||
});
|
||||
return html.join(' ');
|
||||
},
|
||||
file: function (value, row, index) {
|
||||
return Table.api.formatter.files.call(this, value, row, index);
|
||||
Table.api.formatter.files.call(this, value, row, index);
|
||||
},
|
||||
files: function (value, row, index) {
|
||||
value = value == null || value.length === 0 ? '' : value.toString();
|
||||
var classname = typeof this.classname !== 'undefined' ? this.classname : 'img-sm img-center';
|
||||
var arr = value !== '' ? value.split(',') : [];
|
||||
var arr = value !== '' ? (value.indexOf('data:image/') === -1 ? value.split(',') : [value]) : [];
|
||||
var html = [];
|
||||
var suffix, url;
|
||||
$.each(arr, function (i, value) {
|
||||
|
|
@ -708,8 +771,9 @@ define(['jquery', 'bootstrap'], function ($, undefined) {
|
|||
return html.join(' ');
|
||||
},
|
||||
content: function (value, row, index) {
|
||||
var width = this.width != undefined ? (this.width.match(/^\d+$/) ? this.width + "px" : this.width) : "250px";
|
||||
return "<div style='white-space: nowrap; text-overflow:ellipsis; overflow: hidden; max-width:" + width + ";'>" + value + "</div>";
|
||||
var width = this.width != undefined ? (this.width.toString().match(/^\d+$/) ? this.width + "px" : this.width) : "250px";
|
||||
var hover = this.hover != undefined && this.hover ? "autocontent-hover" : "";
|
||||
return "<div class='autocontent-item " + hover + "' style='white-space: nowrap; text-overflow:ellipsis; overflow: hidden; max-width:" + width + ";'>" + value + "</div>";
|
||||
},
|
||||
status: function (value, row, index) {
|
||||
var custom = {normal: 'success', hidden: 'gray', deleted: 'danger', locked: 'info'};
|
||||
|
|
@ -932,7 +996,7 @@ define(['jquery', 'bootstrap'], function ($, undefined) {
|
|||
$.each(dropdowns, function (i, j) {
|
||||
dropdownHtml.push('<div class="btn-group"><button type="button" class="btn btn-primary dropdown-toggle btn-xs" data-toggle="dropdown">' + i + '</button><button type="button" class="btn btn-primary dropdown-toggle btn-xs" data-toggle="dropdown"><span class="caret"></span></button><ul class="dropdown-menu dropdown-menu-right"><li>' + j.join('</li><li>') + '</li></ul></div>');
|
||||
});
|
||||
html.unshift(dropdownHtml);
|
||||
html.unshift(dropdownHtml.join(' '));
|
||||
}
|
||||
return html.join(' ');
|
||||
},
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ define(['jquery', 'bootstrap', 'dropzone', 'template'], function ($, undefined,
|
|||
onDomUploadSuccess = Upload.api.custom[onDomUploadSuccess];
|
||||
}
|
||||
if (typeof onDomUploadSuccess === 'function') {
|
||||
var result = onDomUploadSuccess.call(button, data, ret);
|
||||
var result = onDomUploadSuccess.call(button, data, ret, up, file);
|
||||
if (result === false)
|
||||
return;
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ define(['jquery', 'bootstrap', 'dropzone', 'template'], function ($, undefined,
|
|||
}
|
||||
|
||||
if (typeof onUploadSuccess === 'function') {
|
||||
var result = onUploadSuccess.call(button, data, ret);
|
||||
var result = onUploadSuccess.call(button, data, ret, up, file);
|
||||
if (result === false)
|
||||
return;
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ define(['jquery', 'bootstrap', 'dropzone', 'template'], function ($, undefined,
|
|||
onDomUploadError = Upload.api.custom[onDomUploadError];
|
||||
}
|
||||
if (typeof onDomUploadError === 'function') {
|
||||
var result = onDomUploadError.call(button, data, ret);
|
||||
var result = onDomUploadError.call(button, data, ret, up, file);
|
||||
if (result === false)
|
||||
return;
|
||||
}
|
||||
|
|
@ -71,7 +71,7 @@ define(['jquery', 'bootstrap', 'dropzone', 'template'], function ($, undefined,
|
|||
}
|
||||
|
||||
if (typeof onUploadError === 'function') {
|
||||
var result = onUploadError.call(button, data, ret);
|
||||
var result = onUploadError.call(button, data, ret, up, file);
|
||||
if (result === false) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -398,6 +398,11 @@ define(['jquery', 'bootstrap', 'dropzone', 'template'], function ($, undefined,
|
|||
});
|
||||
}
|
||||
if (input_id) {
|
||||
$("#" + input_id).closest("form").on("reset", function () {
|
||||
setTimeout($.proxy(function () {
|
||||
$("#" + input_id, this).trigger("change");
|
||||
}, this), 0);
|
||||
});
|
||||
//粘贴上传、拖拽上传
|
||||
$("body").on('paste drop', "#" + input_id, function (event) {
|
||||
var originEvent = event.originalEvent;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -273,6 +273,15 @@
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* reset the items
|
||||
*/
|
||||
reset: function () {
|
||||
var val = this.$element.val();
|
||||
this.removeAll();
|
||||
this.add(val);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the items added as tags
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -888,6 +888,11 @@ form.form-horizontal .control-label {
|
|||
.bs-checkbox {
|
||||
min-width: 36px;
|
||||
}
|
||||
|
||||
//拖拽时隐藏tooltip,避免出现错位
|
||||
tr[data-origpos] > td > .tooltip.in {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/*修复nice-validator新版下的一处BUG*/
|
||||
|
|
@ -1547,6 +1552,10 @@ table.table-nowrap {
|
|||
}
|
||||
}
|
||||
|
||||
.sidebar-menu li.active > a > .fa-angle-left, .sidebar-menu li.active > a > .pull-right-container > .fa-angle-left {
|
||||
.rotate(0deg);
|
||||
}
|
||||
|
||||
.sidebar-menu li.treeview-open > a > .fa-angle-left, .sidebar-menu li.treeview-open > a > .pull-right-container > .fa-angle-left {
|
||||
.rotate(-90deg);
|
||||
}
|
||||
|
|
@ -1658,3 +1667,27 @@ table.table-nowrap {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
.autocontent {
|
||||
position: relative;
|
||||
|
||||
.autocontent-caret {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
line-height: 1;
|
||||
background: #eee;
|
||||
color: #ddd;
|
||||
vertical-align: middle;
|
||||
padding: 0 5px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -87,6 +87,12 @@ a {
|
|||
}
|
||||
}
|
||||
|
||||
.navbar-white {
|
||||
.navbar-brand {
|
||||
height: 60px;
|
||||
line-height: 27px;
|
||||
}
|
||||
}
|
||||
.navbar-white .navbar-nav {
|
||||
> li > a {
|
||||
height: 60px;
|
||||
|
|
@ -475,6 +481,27 @@ form.form-horizontal .control-label {
|
|||
padding: 15px;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.n-bootstrap {
|
||||
.n-right {
|
||||
margin-top: 0;
|
||||
top: -20px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
|
||||
.msg-wrap {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.col-xs-12 > .n-right {
|
||||
.msg-wrap {
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-pills > li {
|
||||
|
|
@ -948,3 +975,27 @@ main.content {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
.autocontent {
|
||||
position: relative;
|
||||
|
||||
.autocontent-caret {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
line-height: 1;
|
||||
background: #eee;
|
||||
color: #ddd;
|
||||
vertical-align: middle;
|
||||
padding: 0 5px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -99,6 +99,13 @@
|
|||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
li.treeview {
|
||||
&.active > a,&.treeview-open > a {
|
||||
background-color: @sidebar-dark-submenu-bg;
|
||||
border-left-color: @sidebar-dark-submenu-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.treeview-menu {
|
||||
padding-left: 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,13 @@
|
|||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
li.treeview {
|
||||
&.active > a,&.treeview-open > a {
|
||||
background-color: @sidebar-dark-submenu-bg;
|
||||
border-left-color: @sidebar-dark-submenu-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.treeview-menu {
|
||||
padding-left: 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,13 @@
|
|||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
li.treeview {
|
||||
&.active > a,&.treeview-open > a {
|
||||
background-color: @sidebar-dark-submenu-bg;
|
||||
border-left-color: @sidebar-dark-submenu-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.treeview-menu {
|
||||
padding-left: 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,13 @@
|
|||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
li.treeview {
|
||||
&.active > a,&.treeview-open > a {
|
||||
background-color: @sidebar-dark-submenu-bg;
|
||||
border-left-color: @sidebar-dark-submenu-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.treeview-menu {
|
||||
padding-left: 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,13 @@
|
|||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
li.treeview {
|
||||
&.active > a,&.treeview-open > a {
|
||||
background-color: @sidebar-dark-submenu-bg;
|
||||
border-left-color: @sidebar-dark-submenu-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.treeview-menu {
|
||||
padding-left: 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,13 @@
|
|||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
li.treeview {
|
||||
&.active > a,&.treeview-open > a {
|
||||
background-color: @sidebar-dark-submenu-bg;
|
||||
border-left-color: @sidebar-dark-submenu-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.treeview-menu {
|
||||
padding-left: 0;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue