新增兼容无前缀表生成CRUD

新增CRUD自定义参数
新增左侧菜单可控制显示功能
新增部分表格操作示例
新增管理员列表可查看所属组别
新增multi方法可自定义过滤的字段
新增表格内元素.btn-change的类功能
视图文件表单提交按钮新增disabled
完善邮件发送和测试功能
修复上传在特殊情况下会返回错误的BUG
修复弹出框在特定情况下被遮挡的BUG
修复在默认页设置错误导致后台异常的BUG
pull/135/MERGE
Karson 2017-06-27 14:31:52 +08:00
parent 937ebe6dca
commit 26f95f19bd
54 changed files with 588 additions and 265 deletions

View File

@ -27,22 +27,32 @@ class Crud extends Command
/** /**
* Enum类型识别为单选框的结尾字符,默认会识别为单选下拉列表 * Enum类型识别为单选框的结尾字符,默认会识别为单选下拉列表
*/ */
protected $enumRadioSuffix = 'data'; protected $enumRadioSuffix = ['data', 'state', 'status'];
/** /**
* Set类型识别为复选框的结尾字符,默认会识别为多选下拉列表 * Set类型识别为复选框的结尾字符,默认会识别为多选下拉列表
*/ */
protected $setCheckboxSuffix = 'data'; protected $setCheckboxSuffix = ['data', 'state', 'status'];
/** /**
* Int类型识别为日期时间的结尾字符,默认会识别为数字文本框 * Int类型识别为日期时间的结尾字符,默认会识别为日期文本框
*/ */
protected $intDateSuffix = 'time'; protected $intDateSuffix = ['time'];
/** /**
* 开关后缀 * 开关后缀
*/ */
protected $switchSuffix = 'switch'; protected $switchSuffix = ['switch'];
/**
* Selectpage对应的后缀
*/
protected $selectpageSuffix = ['_id', '_ids'];
/**
* Selectpage多选对应的后缀
*/
protected $selectpagesSuffix = ['_ids'];
/** /**
* 以指定字符结尾的字段格式化函数 * 以指定字符结尾的字段格式化函数
@ -98,6 +108,16 @@ class Crud extends Command
->addOption('mode', 'o', Option::VALUE_OPTIONAL, 'relation table mode,hasone or belongsto', 'belongsto') ->addOption('mode', 'o', Option::VALUE_OPTIONAL, 'relation table mode,hasone or belongsto', 'belongsto')
->addOption('delete', 'd', Option::VALUE_OPTIONAL, 'delete all files generated by CRUD', null) ->addOption('delete', 'd', Option::VALUE_OPTIONAL, 'delete all files generated by CRUD', null)
->addOption('menu', 'u', Option::VALUE_OPTIONAL, 'create menu when CRUD completed', null) ->addOption('menu', 'u', Option::VALUE_OPTIONAL, 'create menu when CRUD completed', null)
->addOption('setcheckboxsuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate checkbox component with suffix', null)
->addOption('enumradiosuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate radio component with suffix', null)
->addOption('imagefield', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate image component with suffix', null)
->addOption('filefield', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate file component with suffix', null)
->addOption('intdatesuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate date component with suffix', null)
->addOption('switchsuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate switch component with suffix', null)
->addOption('selectpagesuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate selectpage component with suffix', null)
->addOption('selectpagessuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate multiple selectpage component with suffix', null)
->addOption('sortfield', null, Option::VALUE_OPTIONAL, 'sort field', null)
->addOption('editorclass', null, Option::VALUE_OPTIONAL, 'automatically generate editor class', null)
->setDescription('Build CRUD controller and model from table'); ->setDescription('Build CRUD controller and model from table');
} }
@ -130,6 +150,47 @@ class Crud extends Command
$relationForeignKey = $input->getOption('relationforeignkey'); $relationForeignKey = $input->getOption('relationforeignkey');
//主键 //主键
$relationPrimaryKey = $input->getOption('relationprimarykey'); $relationPrimaryKey = $input->getOption('relationprimarykey');
//复选框后缀
$setcheckboxsuffix = $input->getOption('setcheckboxsuffix');
//单选框后缀
$enumradiosuffix = $input->getOption('enumradiosuffix');
//图片后缀
$imagefield = $input->getOption('imagefield');
//文件后缀
$filefield = $input->getOption('filefield');
//日期后缀
$intdatesuffix = $input->getOption('intdatesuffix');
//开关后缀
$switchsuffix = $input->getOption('switchsuffix');
//selectpage后缀
$selectpagesuffix = $input->getOption('selectpagesuffix');
//selectpage多选后缀
$selectpagessuffix = $input->getOption('selectpagessuffix');
//排序字段
$sortfield = $input->getOption('sortfield');
//编辑器Class
$editorclass = $input->getOption('editorclass');
if ($setcheckboxsuffix)
$this->setCheckboxSuffix = $setcheckboxsuffix;
if ($enumradiosuffix)
$this->enumRadioSuffix = $enumradiosuffix;
if ($imagefield)
$this->imageField = $imagefield;
if ($filefield)
$this->fileField = $filefield;
if ($intdatesuffix)
$this->intDateSuffix = $intdatesuffix;
if ($switchsuffix)
$this->switchSuffix = $switchsuffix;
if ($selectpagesuffix)
$this->selectpageSuffix = $selectpagesuffix;
if ($selectpagessuffix)
$this->selectpagesSuffix = $selectpagessuffix;
if ($editorclass)
$this->editorClass = $editorclass;
if ($sortfield)
$this->sortField = $sortfield;
//如果有启用关联模式 //如果有启用关联模式
if ($relation && !in_array($mode, ['hasone', 'belongsto'])) if ($relation && !in_array($mode, ['hasone', 'belongsto']))
{ {
@ -140,14 +201,22 @@ class Crud extends Command
$prefix = Config::get('database.prefix'); $prefix = Config::get('database.prefix');
//检查主表 //检查主表
$tableName = $prefix . $table; $tableName = $table;
$modelTableType = 'table';
$tableInfo = Db::query("SHOW TABLE STATUS LIKE '{$tableName}'", [], TRUE); $tableInfo = Db::query("SHOW TABLE STATUS LIKE '{$tableName}'", [], TRUE);
if (!$tableInfo) if (!$tableInfo)
{ {
throw new Exception("table not found"); $tableName = $prefix . $table;
$modelTableType = 'name';
$tableInfo = Db::query("SHOW TABLE STATUS LIKE '{$tableName}'", [], TRUE);
if (!$tableInfo)
{
throw new Exception("table not found");
}
} }
$tableInfo = $tableInfo[0]; $tableInfo = $tableInfo[0];
$relationModelTableType = 'table';
//检查关联表 //检查关联表
if ($relation) if ($relation)
{ {
@ -155,7 +224,13 @@ class Crud extends Command
$relationTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$relationTableName}'", [], TRUE); $relationTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$relationTableName}'", [], TRUE);
if (!$relationTableInfo) if (!$relationTableInfo)
{ {
throw new Exception("relation table not found"); $relationTableName = $relation;
$relationModelTableType = 'name';
$relationTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$relationTableName}'", [], TRUE);
if (!$relationTableInfo)
{
throw new Exception("relation table not found");
}
} }
} }
@ -438,8 +513,9 @@ class Crud extends Command
{ {
$fieldName = $inputType == 'checkbox' ? $fieldName .= "[]" : $fieldName; $fieldName = $inputType == 'checkbox' ? $fieldName .= "[]" : $fieldName;
$attrArr['name'] = "row[{$fieldName}]"; $attrArr['name'] = "row[{$fieldName}]";
$itemArr = $this->getLangArray($itemArr, FALSE);
$this->getEnum($getEnumArr, $controllerAssignList, $field, $itemArr, $inputType); $this->getEnum($getEnumArr, $controllerAssignList, $field, $itemArr, $inputType);
$itemArr = $this->getLangArray($itemArr, FALSE);
//添加一个获取器 //添加一个获取器
$this->getAttr($getAttrArr, $field, $inputType); $this->getAttr($getAttrArr, $field, $inputType);
$this->appendAttr($appendAttrList, $field); $this->appendAttr($appendAttrList, $field);
@ -478,20 +554,21 @@ class Crud extends Command
{ {
$search = $replace = ''; $search = $replace = '';
//特殊字段为关联搜索 //特殊字段为关联搜索
if (substr($field, -3) == '_id' || substr($field, -4) == '_ids') if ($this->isMatchSuffix($field, $this->selectpageSuffix))
{ {
$inputType = 'text'; $inputType = 'text';
$defaultValue = ''; $defaultValue = '';
$attrArr['data-rule'] = 'required'; $attrArr['data-rule'] = 'required';
$cssClassArr[] = 'selectpage'; $cssClassArr[] = 'selectpage';
$attrArr['data-db-table'] = substr($field, 0, strripos($field, '_')); $attrArr['data-db-table'] = substr($field, 0, strripos($field, '_'));
//如果是类型表需要特殊处理下
if ($attrArr['data-db-table'] == 'category') if ($attrArr['data-db-table'] == 'category')
{ {
$attrArr['data-params'] = '##replacetext##'; $attrArr['data-params'] = '##replacetext##';
$search = '"##replacetext##"'; $search = '"##replacetext##"';
$replace = '\'{"custom[type]":"' . $table . '"}\''; $replace = '\'{"custom[type]":"' . $table . '"}\'';
} }
if (substr($field, -4) == '_ids') if ($this->isMatchSuffix($field, $this->selectpagesSuffix))
{ {
$attrArr['data-multiple'] = 'true'; $attrArr['data-multiple'] = 'true';
} }
@ -508,13 +585,9 @@ class Crud extends Command
$step = array_intersect($cssClassArr, ['selectpage']) ? 0 : $step; $step = array_intersect($cssClassArr, ['selectpage']) ? 0 : $step;
$attrArr['class'] = implode(' ', $cssClassArr); $attrArr['class'] = implode(' ', $cssClassArr);
$isUpload = false; $isUpload = false;
foreach (array_merge($this->imageField, $this->fileField) as $m => $n) if ($this->isMatchSuffix($field, array_merge($this->imageField, $this->fileField)))
{ {
if (preg_match("/{$n}$/i", $field)) $isUpload = true;
{
$isUpload = true;
break;
}
} }
//如果是步长则加上步长 //如果是步长则加上步长
if ($step) if ($step)
@ -556,11 +629,8 @@ class Crud extends Command
$javascriptList[] = "{checkbox: true}"; $javascriptList[] = "{checkbox: true}";
} }
//构造JS列信息 //构造JS列信息
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE']); $javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : '');
if ($inputType && in_array($inputType, ['select', 'checkbox', 'radio']))
{
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], '_text');
}
//排序方式,如果有指定排序字段,否则按主键排序 //排序方式,如果有指定排序字段,否则按主键排序
$order = $field == $this->sortField ? $this->sortField : $order; $order = $field == $this->sortField ? $this->sortField : $order;
} }
@ -631,7 +701,9 @@ class Crud extends Command
'createTime' => in_array('createtime', $fieldArr) ? "'createtime'" : 'false', 'createTime' => in_array('createtime', $fieldArr) ? "'createtime'" : 'false',
'updateTime' => in_array('updatetime', $fieldArr) ? "'updatetime'" : 'false', 'updateTime' => in_array('updatetime', $fieldArr) ? "'updatetime'" : 'false',
'modelTableName' => $table, 'modelTableName' => $table,
'modelTableType' => $modelTableType,
'relationModelTableName' => $relation, 'relationModelTableName' => $relation,
'relationModelTableType' => $relationModelTableType,
'relationModelName' => $relationModelName, 'relationModelName' => $relationModelName,
'relationWith' => '', 'relationWith' => '',
'relationMethod' => '', 'relationMethod' => '',
@ -842,8 +914,12 @@ EOD;
$itemArr = [$field => $fieldLang]; $itemArr = [$field => $fieldLang];
foreach (explode(',', $item) as $k => $v) foreach (explode(',', $item) as $k => $v)
{ {
list($key, $value) = explode('=', $v); $valArr = explode('=', $v);
$itemArr[$field . ' ' . $key] = $value; if (count($valArr) == 2)
{
list($key, $value) = $valArr;
$itemArr[$field . ' ' . $key] = $value;
}
} }
} }
else else
@ -910,8 +986,12 @@ EOD;
$itemArr = []; $itemArr = [];
foreach (explode(',', $item) as $k => $v) foreach (explode(',', $item) as $k => $v)
{ {
list($key, $value) = explode('=', $v); $valArr = explode('=', $v);
$itemArr[$key] = $field . ' ' . $key; if (count($valArr) == 2)
{
list($key, $value) = $valArr;
$itemArr[$key] = $field . ' ' . $key;
}
} }
} }
else else
@ -964,28 +1044,47 @@ EOD;
} }
$fieldsName = $v['COLUMN_NAME']; $fieldsName = $v['COLUMN_NAME'];
// 指定后缀说明也是个时间字段 // 指定后缀说明也是个时间字段
if (preg_match("/{$this->intDateSuffix}$/i", $fieldsName)) if ($this->isMatchSuffix($fieldsName, $this->intDateSuffix))
{ {
$inputType = 'datetime'; $inputType = 'datetime';
} }
// 指定后缀结尾且类型为enum,说明是个单选框 // 指定后缀结尾且类型为enum,说明是个单选框
if (preg_match("/{$this->enumRadioSuffix}$/i", $fieldsName) && $v['DATA_TYPE'] == 'enum') if ($this->isMatchSuffix($fieldsName, $this->enumRadioSuffix) && $v['DATA_TYPE'] == 'enum')
{ {
$inputType = "radio"; $inputType = "radio";
} }
// 指定后缀结尾且类型为set,说明是个复选框 // 指定后缀结尾且类型为set,说明是个复选框
if (preg_match("/{$this->setCheckboxSuffix}$/i", $fieldsName) && $v['DATA_TYPE'] == 'set') if ($this->isMatchSuffix($fieldsName, $this->setCheckboxSuffix) && $v['DATA_TYPE'] == 'set')
{ {
$inputType = "checkbox"; $inputType = "checkbox";
} }
// 指定后缀结尾且类型为char或tinyint且长度为1,说明是个Switch复选框 // 指定后缀结尾且类型为char或tinyint且长度为1,说明是个Switch复选框
if (preg_match("/{$this->switchSuffix}$/i", $fieldsName) && ($v['COLUMN_TYPE'] == 'tinyint(1)' || $v['COLUMN_TYPE'] == 'char(1)') && $v['COLUMN_DEFAULT'] !== '' && $v['COLUMN_DEFAULT'] !== null) if ($this->isMatchSuffix($fieldsName, $this->switchSuffix) && ($v['COLUMN_TYPE'] == 'tinyint(1)' || $v['COLUMN_TYPE'] == 'char(1)') && $v['COLUMN_DEFAULT'] !== '' && $v['COLUMN_DEFAULT'] !== null)
{ {
$inputType = "switch"; $inputType = "switch";
} }
return $inputType; return $inputType;
} }
/**
* 判断是否符合指定后缀
* @param string $field 字段名称
* @param mixed $suffixArr 后缀
* @return boolean
*/
protected function isMatchSuffix($field, $suffixArr)
{
$suffixArr = is_array($suffixArr) ? $suffixArr : explode(',', $suffixArr);
foreach ($suffixArr as $k => $v)
{
if (preg_match("/{$v}$/i", $field))
{
return true;
}
}
return false;
}
/** /**
* 获取表单分组数据 * 获取表单分组数据
* @param string $field * @param string $field
@ -1014,13 +1113,9 @@ EOD;
protected function getImageUpload($field, $content) protected function getImageUpload($field, $content)
{ {
$filter = ''; $filter = '';
foreach ($this->imageField as $k => $v) if ($this->isMatchSuffix($field, $this->imageField))
{ {
if (preg_match("/{$v}$/i", $field)) $filter = ' data-mimetype="image/*"';
{
$filter = ' data-mimetype="image/*"';
break;
}
} }
$multiple = substr($field, -1) == 's' ? ' data-multiple="true"' : ' data-multiple="false"'; $multiple = substr($field, -1) == 's' ? ' data-multiple="true"' : ' data-multiple="false"';
$preview = $filter ? ' data-preview-id="p-' . $field . '"' : ''; $preview = $filter ? ' data-preview-id="p-' . $field . '"' : '';
@ -1064,9 +1159,16 @@ EOD;
} }
} }
} }
$formatter = $extend ? '' : $formatter;
if ($extend) if ($extend)
{
$html .= ", operate:false"; $html .= ", operate:false";
if ($formatter && !$extend) if ($datatype == 'set')
{
$formatter = 'label';
}
}
if ($formatter)
$html .= ", formatter: Table.api.formatter." . $formatter . "}"; $html .= ", formatter: Table.api.formatter." . $formatter . "}";
else else
$html .= "}"; $html .= "}";

View File

@ -4,7 +4,7 @@
<div class="form-group layer-footer"> <div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -4,7 +4,7 @@
<div class="form-group layer-footer"> <div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -6,8 +6,8 @@ use think\Model;
class {%modelName%} extends Model class {%modelName%} extends Model
{ {
// 表名,不含前缀 // 表名
protected $name = '{%modelTableName%}'; protected ${%modelTableType%} = '{%modelTableName%}';
// 自动写入时间戳字段 // 自动写入时间戳字段
protected $autoWriteTimestamp = {%modelAutoWriteTimestamp%}; protected $autoWriteTimestamp = {%modelAutoWriteTimestamp%};

View File

@ -6,7 +6,7 @@ use think\Model;
class {%relationModelName%} extends Model class {%relationModelName%} extends Model
{ {
// 表名,不含前缀 // 表名
protected $name = '{%relationModelTableName%}'; protected ${%relationModelTableType%} = '{%relationModelTableName%}';
} }

View File

@ -153,6 +153,7 @@ class Ajax extends Backend
public function roletree() public function roletree()
{ {
$this->loadlang('auth/group'); $this->loadlang('auth/group');
$model = model('AuthGroup'); $model = model('AuthGroup');
$id = $this->request->post("id"); $id = $this->request->post("id");
$pid = $this->request->post("pid"); $pid = $this->request->post("pid");
@ -165,22 +166,50 @@ class Ajax extends Backend
if (($pid || $parentgroupmodel) && (!$id || $currentgroupmodel)) if (($pid || $parentgroupmodel) && (!$id || $currentgroupmodel))
{ {
$id = $id ? $id : NULL; $id = $id ? $id : NULL;
$ruleList = collection(model('AuthRule')->order('weigh', 'desc')->select())->toArray();
//读取父类角色所有节点列表 //读取父类角色所有节点列表
$parentrulelist = model('AuthRule')->all(in_array('*', explode(',', $parentgroupmodel->rules)) ? NULL : $parentgroupmodel->rules); $parentRuleList = [];
if (in_array('*', explode(',', $parentgroupmodel->rules)))
{
$parentRuleList = $ruleList;
}
else
{
$parent_rule_ids = explode(',', $parentgroupmodel->rules);
foreach ($ruleList as $k => $v)
{
if (in_array($v['id'], $parent_rule_ids))
{
$parentRuleList[] = $v;
}
}
}
//当前所有正常规则列表
Tree::instance()->init($ruleList);
//读取当前角色下规则ID集合 //读取当前角色下规则ID集合
$admin_rule_ids = $this->auth->getRuleIds(); $admin_rule_ids = $this->auth->getRuleIds();
//是否是超级管理员
$superadmin = $this->auth->isSuperAdmin(); $superadmin = $this->auth->isSuperAdmin();
//当前拥有的规则ID集合
$current_rule_ids = $id ? explode(',', $currentgroupmodel->rules) : []; $current_rule_ids = $id ? explode(',', $currentgroupmodel->rules) : [];
if (!$id || !in_array($pid, Tree::instance()->init($model->all(['status' => 'normal']))->getChildrenIds($id, TRUE))) if (!$id || !in_array($pid, Tree::instance()->getChildrenIds($id, TRUE)))
{ {
//构造jstree所需的数据 $ruleList = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'name');
$hasChildrens = [];
foreach ($ruleList as $k => $v)
{
if ($v['haschild'])
$hasChildrens[] = $v['id'];
}
$nodelist = []; $nodelist = [];
foreach ($parentrulelist as $k => $v) foreach ($parentRuleList as $k => $v)
{ {
if (!$superadmin && !in_array($v['id'], $admin_rule_ids)) if (!$superadmin && !in_array($v['id'], $admin_rule_ids))
continue; continue;
$state = array('selected' => !$v['ismenu'] && in_array($v['id'], $current_rule_ids)); $state = array('selected' => in_array($v['id'], $current_rule_ids) && !in_array($v['id'], $hasChildrens));
$nodelist[] = array('id' => $v['id'], 'parent' => $v['pid'] ? $v['pid'] : '#', 'text' => $v['title'], 'type' => 'menu', 'state' => $state); $nodelist[] = array('id' => $v['id'], 'parent' => $v['pid'] ? $v['pid'] : '#', 'text' => $v['title'], 'type' => 'menu', 'state' => $state);
} }
$this->code = 1; $this->code = 1;
@ -206,7 +235,7 @@ class Ajax extends Backend
{ {
$this->code = -1; $this->code = -1;
$file = $this->request->file('file'); $file = $this->request->file('file');
if (!$file) if (empty($file))
{ {
$this->msg = "未上传文件或超出服务器上传限制"; $this->msg = "未上传文件或超出服务器上传限制";
return; return;

View File

@ -52,10 +52,21 @@ class Admin extends Backend
{ {
if ($this->request->isAjax()) if ($this->request->isAjax())
{ {
$childrenAdminIds = model('AuthGroupAccess') $groupData = model('AuthGroup')->where('status', 'normal')->column('id,name');
->field('uid')
$childrenAdminIds = [];
$authGroupList = model('AuthGroupAccess')
->field('uid,group_id')
->where('group_id', 'in', $this->childrenIds) ->where('group_id', 'in', $this->childrenIds)
->column('uid'); ->select();
$adminGroupName = [];
foreach ($authGroupList as $k => $v)
{
$childrenAdminIds[] = $v['uid'];
if (isset($groupData[$v['group_id']]))
$adminGroupName[$v['uid']][$v['group_id']] = $groupData[$v['group_id']];
}
list($where, $sort, $order, $offset, $limit) = $this->buildparams(); list($where, $sort, $order, $offset, $limit) = $this->buildparams();
$total = $this->model $total = $this->model
->where($where) ->where($where)
@ -70,6 +81,12 @@ class Admin extends Backend
->order($sort, $order) ->order($sort, $order)
->limit($offset, $limit) ->limit($offset, $limit)
->select(); ->select();
foreach ($list as $k => &$v)
{
$groups = isset($adminGroupName[$v['id']]) ? $adminGroupName[$v['id']] : [];
$v['groups'] = implode(',', array_keys($groups));
$v['groups_text'] = implode(',', array_values($groups));
}
$result = array("total" => $total, "rows" => $list); $result = array("total" => $total, "rows" => $list);
return json($result); return json($result);

View File

@ -17,6 +17,7 @@ class Rule extends Backend
protected $model = null; protected $model = null;
protected $rulelist = []; protected $rulelist = [];
protected $multiFields = 'ismenu,status';
public function _initialize() public function _initialize()
{ {
@ -133,14 +134,4 @@ class Rule extends Backend
return; return;
} }
/**
* 批量更新
* @internal
*/
public function multi($ids = "")
{
// 节点禁止批量操作
$this->code = -1;
}
} }

View File

@ -14,6 +14,7 @@ class Bootstraptable extends Backend
{ {
protected $model = null; protected $model = null;
protected $noNeedRight = ['change', 'detail'];
public function _initialize() public function _initialize()
{ {
@ -57,4 +58,13 @@ class Bootstraptable extends Backend
return $this->view->fetch(); return $this->view->fetch();
} }
/**
* 变更
* @internal
*/
public function change()
{
$this->code = 1;
}
} }

View File

@ -2,7 +2,6 @@
namespace app\admin\controller\general; namespace app\admin\controller\general;
use think\Config as tpConfig;
use app\common\library\Email; use app\common\library\Email;
use app\common\controller\Backend; use app\common\controller\Backend;
@ -235,20 +234,28 @@ class Config extends Backend
} }
} }
/**
* 发送测试邮件
* @internal
*/
public function emailtest() public function emailtest()
{ {
$content = '<table style="width: 99.8%; "><tbody><tr><td id="QQMAILSTATIONERY" style="background:url(https://rescdn.qqmail.com/zh_CN/htmledition/images/xinzhi/bg/a_07.jpg) repeat-x #e4ebf5; min-height:550px; padding: 100px 55px 200px;">这是一封测试邮件,用于测试邮件配置是否正常!</td></tr></tbody></table>'; $receiver = $this->request->request("receiver");
$site = tpConfig::get("site");
$email = new Email; $email = new Email;
$mailArr = Array(); $result = $email
$mailArr['mTo'] = $site['mail_from']; //收件人 ->to($receiver)
$mailArr['subject'] = '这是一封测试邮件'; //邮件主题 ->subject(__("This is a test mail"))
$mailArr['content'] = $content; //邮件内容(html) ->message('<div style="min-height:550px; padding: 100px 55px 200px;">' . __('This is a test mail content') . '</div>')
$mailArr['fromNic'] = 'Fastadmin系统邮件'; //发件人昵称[可省略] ->send();
$mailArr['toNic'] = '亲爱的用户'; //收件人昵称[可省略]貌似无效 if ($result)
$data = $email->sendMail($mailArr['mTo'],$mailArr['subject'],$mailArr['content'],$mailArr['fromNic'],$mailArr['toNic']); {
return json(['data'=>$data,'code'=>200,'message'=>'操作完成']); $this->code = 1;
}
else
{
$this->code = -1;
$this->msg = $email->getError();
}
} }
} }

View File

@ -14,6 +14,7 @@ return [
'Add' => '添加', 'Add' => '添加',
'Edit' => '编辑', 'Edit' => '编辑',
'Delete' => '删除', 'Delete' => '删除',
'Detail' => '详情',
'Move' => '移动', 'Move' => '移动',
'Name' => '名称', 'Name' => '名称',
'Status' => '状态', 'Status' => '状态',

View File

@ -1,16 +1,17 @@
<?php <?php
return [ return [
'Url' => '物理路径', 'Url' => '物理路径',
'Imagewidth' => '宽度', 'Imagewidth' => '宽度',
'Imageheight' => '宽度', 'Imageheight' => '宽度',
'Imagetype' => '图片类型', 'Imagetype' => '图片类型',
'Imageframes' => '图片帧数', 'Imageframes' => '图片帧数',
'Preview' => '预览', 'Preview' => '预览',
'Filesize' => '文件大小', 'Filesize' => '文件大小',
'Mimetype' => 'Mime类型', 'Mimetype' => 'Mime类型',
'Extparam' => '透传数据', 'Extparam' => '透传数据',
'Createtime' => '创建日期', 'Createtime' => '创建日期',
'Uploadtime' => '上传时间', 'Uploadtime' => '上传时间',
'Storage' => '存储引擎' 'Storage' => '存储引擎',
'Upload by summernote' => '从编辑器上传'
]; ];

View File

@ -1,36 +1,39 @@
<?php <?php
return [ return [
'Name' => '变量名', 'Name' => '变量名',
'Tip' => '提示信息', 'Tip' => '提示信息',
'Group' => '分组', 'Group' => '分组',
'Type' => '类型', 'Type' => '类型',
'Title' => '变量标题', 'Title' => '变量标题',
'Value' => '变量值', 'Value' => '变量值',
'Basic' => '基础配置', 'Basic' => '基础配置',
'Email' => '邮件配置', 'Email' => '邮件配置',
'Attachment' => '附件配置', 'Attachment' => '附件配置',
'User' => '会员配置', 'User' => '会员配置',
'Example' => '示例分组', 'Example' => '示例分组',
'Extend' => '扩展属性', 'Extend' => '扩展属性',
'String' => '字符', 'String' => '字符',
'Text' => '文本', 'Text' => '文本',
'Number' => '数字', 'Number' => '数字',
'Date' => '日期', 'Date' => '日期',
'Time' => '时间', 'Time' => '时间',
'Datetime' => '日期时间', 'Datetime' => '日期时间',
'Image' => '图片', 'Image' => '图片',
'Images' => '图片(多)', 'Images' => '图片(多)',
'File' => '文件', 'File' => '文件',
'Files' => '文件(多)', 'Files' => '文件(多)',
'Select' => '列表', 'Select' => '列表',
'Selects' => '列表(多选)', 'Selects' => '列表(多选)',
'Checkbox' => '复选', 'Checkbox' => '复选',
'Radio' => '单选', 'Radio' => '单选',
'Array' => '数组', 'Array' => '数组',
'Array key' => '键名', 'Array key' => '键名',
'Array value' => '键值', 'Array value' => '键值',
'Content' => '数据列表', 'Content' => '数据列表',
'Rule' => '校验规则', 'Rule' => '校验规则',
'Name already exist' => '变量名称已经存在', 'Name already exist' => '变量名称已经存在',
'Send a test message' => '发送测试邮件',
'This is a test mail content' => '这是一封测试邮件,用于测试邮件配置是否正常!',
'This is a test mail' => '这是一封测试邮件',
]; ];

View File

@ -163,7 +163,7 @@ trait Backend
if ($this->request->has('params')) if ($this->request->has('params'))
{ {
parse_str($this->request->post("params"), $values); parse_str($this->request->post("params"), $values);
$values = array_intersect_key($values, array_flip(array('status'))); $values = array_intersect_key($values, array_flip(is_array($this->multiFields) ? $this->multiFields : explode(',', $this->multiFields)));
if ($values) if ($values)
{ {
$count = $this->model->where($this->model->getPk(), 'in', $ids)->update($values); $count = $this->model->where($this->model->getPk(), 'in', $ids)->update($values);
@ -172,6 +172,10 @@ trait Backend
$this->code = 1; $this->code = 1;
} }
} }
else
{
$this->msg = __('You have no permission');
}
} }
else else
{ {

View File

@ -38,7 +38,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -38,7 +38,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -30,7 +30,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -30,7 +30,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2 col-xs-2"></label> <label class="control-label col-xs-12 col-sm-2 col-xs-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -63,7 +63,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<div class="col-xs-2"></div> <div class="col-xs-2"></div>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -59,7 +59,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<div class="col-xs-2"></div> <div class="col-xs-2"></div>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -51,7 +51,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -51,7 +51,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -16,6 +16,8 @@
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li> <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
</ul> </ul>
</div> </div>
<a class="btn btn-success btn-change btn-start" data-params="action=start" data-url="example/bootstraptable/change" href="javascript:;"><i class="fa fa-play"></i> 启动</a>
<a class="btn btn-danger btn-change btn-pause" data-params="action=pause" data-url="example/bootstraptable/change" href="javascript:;"><i class="fa fa-pause"></i> 暂停</a>
</div> </div>
<table id="table" class="table table-striped table-bordered table-hover" width="100%"> <table id="table" class="table table-striped table-bordered table-hover" width="100%">

View File

@ -63,7 +63,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -126,7 +126,7 @@
<tr> <tr>
<td></td> <td></td>
<td> <td>
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</td> </td>
<td></td> <td></td>
@ -205,7 +205,7 @@ key2|value2</textarea>
<div class="form-group"> <div class="form-group">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-4"> <div class="col-xs-12 col-sm-4">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -44,7 +44,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -46,7 +46,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<div class="col-xs-2"></div> <div class="col-xs-2"></div>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -73,7 +73,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -73,7 +73,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -73,7 +73,7 @@
<div class="form-group layer-footer"> <div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -74,7 +74,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -56,7 +56,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -57,7 +57,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -185,7 +185,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -180,7 +180,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -57,7 +57,7 @@
<div class="form-group layer-footer"> <div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -51,7 +51,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -43,7 +43,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -44,7 +44,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -38,7 +38,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -40,7 +40,7 @@
<div class="form-group hide layer-footer"> <div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label> <label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -32,7 +32,7 @@
<div class="form-group {:input('get.callback')?'':'hidden layer-footer'}"> <div class="form-group {:input('get.callback')?'':'hidden layer-footer'}">
<div class="col-xs-2"></div> <div class="col-xs-2"></div>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -36,7 +36,7 @@
<div class="form-group hidden layer-footer"> <div class="form-group hidden layer-footer">
<div class="col-xs-2"></div> <div class="col-xs-2"></div>
<div class="col-xs-12 col-sm-8"> <div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button> <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button> <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div> </div>
</div> </div>

View File

@ -79,6 +79,11 @@ class Backend extends Controller
*/ */
protected $modelSceneValidate = false; protected $modelSceneValidate = false;
/**
* Multi方法可批量修改的字段
*/
protected $multiFields = 'status';
/** /**
* 引入后台控制器的traits * 引入后台控制器的traits
*/ */

View File

@ -6,81 +6,186 @@ use think\Config;
class Email class Email
{ {
/**
* 单例对象
*/
protected static $instance;
/**
* phpmailer对象
*/
protected $mail = [];
/**
* 错误内容
*/
protected $_error = '';
/**
* 默认配置
*/
public $options = [
'charset' => 'utf-8', //编码格式
'debug' => 0, //调式模式
];
/**
* 初始化
* @access public
* @param array $options 参数
* @return Email
*/
public static function instance($options = [])
{
if (is_null(self::$instance))
{
self::$instance = new static($options);
}
return self::$instance;
}
/**
* 构造函数
* @param array $options
*/
public function __construct($options = [])
{
if ($config = Config::get('site'))
{
$this->options = array_merge($this->options, $config);
}
$this->options = array_merge($this->options, $options);
vendor('phpmailer.phpmailer.PHPMailerAutoload');
$securArr = [1 => 'tls', 2 => 'ssl'];
$this->mail = new \PHPMailer(true);
$this->mail->CharSet = $this->options['charset'];
$this->mail->SMTPDebug = $this->options['debug'];
$this->mail->isSMTP();
$this->mail->SMTPAuth = true;
$this->mail->Host = $this->options['mail_smtp_host'];
$this->mail->Username = $this->options['mail_smtp_user'];
$this->mail->Password = $this->options['mail_smtp_pass'];
$this->mail->SMTPSecure = isset($securArr[$this->options['mail_verify_type']]) ? $securArr[$this->options['mail_verify_type']] : '';
$this->mail->Port = $this->options['mail_smtp_port'];
//设置发件人
$this->from($this->options['mail_from']);
}
/**
* 设置邮件主题
* @param string $subject
* @return $this
*/
public function subject($subject)
{
$this->options['subject'] = $subject;
return $this;
}
/**
* 设置发件人
* @param string $email
* @param string $name
* @return $this
*/
public function from($email, $name = '')
{
$this->options['from'] = $email;
$this->options['from_name'] = $name;
return $this;
}
/**
* 设置收件人
* @param string $email
* @param string $name
* @return $this
*/
public function to($email, $name = '')
{
$this->options['to'] = $email;
$this->options['to_name'] = $name;
return $this;
}
/**
* 设置邮件正文
* @param string $body
* @param boolean $ishtml
* @return $this
*/
public function message($body, $ishtml = true)
{
$this->options['body'] = $body;
$this->options['ishtml'] = $ishtml;
return $this;
}
/**
* 获取最后产生的错误
*/
public function getError()
{
return $this->_error;
}
protected function setError($error)
{
$this->_error = $error;
}
/** /**
* 发送邮件 * 发送邮件
* @param string $mTo 收件人 * @return boolean
* @param string $subject 邮件主题
* @param string $content 邮件内容(html)
* @param string $fromNic 发件人昵称
* @param string $toNic 收件人昵称
*/ */
public function sendMail($mTo='',$subject='',$content='',$fromNic='',$toNic='') public function send()
{ {
$site = Config::get("site"); $result = false;
$re = Vendor('phpmailer.phpmailer.PHPMailerAutoload'); switch ($this->options['mail_type'])
$mail = new \PHPMailer ();
//$mail->SMTPDebug = 3; // Enable verbose debug output
$mail->isSMTP(); //smtp需要鉴权 这个必须是true
$mail->Host = $site['mail_smtp_host']; //SMTP服务器地址
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = $site['mail_smtp_user']; // SMTP 用戶名
$mail->Password = $site['mail_smtp_pass']; // SMTP 密碼
switch ($site['mail_verify_type']) // Enable TLS encryption, `ssl` also accepted
{ {
case 1: case 1:
$mail->SMTPSecure = 'tls'; //使用phpmailer发送
break; $this->mail->setFrom($this->options['from'], $this->options['from_name']);
case 2: $this->mail->addAddress($this->options['to'], $this->options['to_name']);
$mail->SMTPSecure = 'ssl'; $this->mail->Subject = $this->options['subject'];
break; if ($this->options['ishtml'])
default: {
$mail->SMTPSecure = ''; $this->mail->msgHTML($this->options['body']);
} }
$mail->Port = $site['mail_smtp_port']; // 设置ssl连接smtp服务器的远程服务器端口号 else
$mail->setFrom($site['mail_from'], $fromNic); // [发件人],[昵称(可选)] {
$mail->addAddress($mTo, $toNic); // [收件人],[昵称(可选)] $this->mail->Body = $this->options['body'];
//$mail->addReplyTo('xxxxxx@qq.com', 'Information'); // 回复地址(可选) }
//$mail->addCC('xxxxxx@qq.com'); //好像是密送 try
//$mail->addBCC('xxxxxx@qq.com'); //好像是密送B {
// $mail->addAttachment('/var/tmp/file.tar.gz'); // 添加附件 $result = $this->mail->send();
// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // 附件名选项 }
$mail->isHTML(true); //邮件正文是否为html编码 catch (\phpmailerException $e)
$mail->Subject = $subject; //添加邮件主题 {
$mail->Body = $content; //邮件正文 $this->setError($e->getMessage());
//$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';//附加信息,可以省略 }
switch ($site['mail_type']) $this->setError($result ? '' : $this->mail->ErrorInfo);
{ break;
case 1: case 2:
if(!$mail->send()) {//这里如果提交错误的smpt配置PHPmailer会卡住暂时不清楚为什么 //使用mail方法发送邮件
$sendResult['text'] = $mail->ErrorInfo; $headers = 'MIME-Version: 1.0' . "\r\n";
$sendResult['data'] = false; $headers .= "Content-type: text/html; charset=" . $this->options['charset'] . "\r\n";
return $sendResult; $headers .= "To: {$this->options['to_name']} <{$this->options['to']}>\r\n"; //收件人
} else { $headers .= "From: {$this->options['from_name']} <{$this->options['from']}>\r\n"; //发件人
$sendResult['text'] ='smtp发送成功'; $result = mail($this->options['mail_to'], $this->options['subject'], $this->options['body'], $headers);
$sendResult['data'] = true; $this->setError($result ? '' : error_get_last()['message']);
return $sendResult; break;
} default:
break; //邮件功能已关闭
case 2://使用mail方法发送邮件 $this->setError(__('Mail already closed'));
$headers = 'MIME-Version: 1.0' . "\r\n"; break;
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'To: '.$toNic.' <'.$mTo.'>' . "\r\n";//收件人
$headers .= 'From: '.$fromNic.' <'.$site['mail_from'].'>' . "\r\n";//发件人
$sendResult['data'] = mail($mTo, $subject, $content, $headers);
if ($sendResult['data']) {
$sendResult['text'] ='mail函数发送成功';
}else{
$sendResult['text'] ='mail函数发送失败';
}
return $sendResult;
break;
default:
$sendResult['data'] = false;
$sendResult['text'] ='已关闭邮件发送';
return $sendResult;
} }
return $result;
} }
} }

View File

@ -119,15 +119,10 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang', 'moment'], function ($
}); });
}, },
open: function (url, title, options) { open: function (url, title, options) {
title = title == undefined ? "" : title; title = title ? title : "";
url = Backend.api.fixurl(url); url = Backend.api.fixurl(url);
url = url + (url.indexOf("?") > -1 ? "&" : "?") + "dialog=1"; url = url + (url.indexOf("?") > -1 ? "&" : "?") + "dialog=1";
var area; var area = [$(window).width() > 800 ? '800px' : '95%', $(window).height() > 600 ? '600px' : '95%'];
if ($(window).width() < 800) {
area = ["95%", "95%"];
} else {
area = ['800px', '600px'];
}
Backend.api.layer.open($.extend({ Backend.api.layer.open($.extend({
type: 2, type: 2,
title: title, title: title,
@ -188,7 +183,7 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang', 'moment'], function ($
var btnHeight = layero.find('.layui-layer-btn').outerHeight() || 0; var btnHeight = layero.find('.layui-layer-btn').outerHeight() || 0;
var oldheg = heg + titHeight + btnHeight; var oldheg = heg + titHeight + btnHeight;
var maxheg = 600; var maxheg = $(window).height() < 600 ? $(window).height() : 600;
if (frame.outerWidth() < 768 || that.area[0].indexOf("%") > -1) { if (frame.outerWidth() < 768 || that.area[0].indexOf("%") > -1) {
maxheg = $(window).height(); maxheg = $(window).height();
} }

View File

@ -24,6 +24,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
{field: 'id', title: 'ID'}, {field: 'id', title: 'ID'},
{field: 'username', title: __('Username')}, {field: 'username', title: __('Username')},
{field: 'nickname', title: __('Nickname')}, {field: 'nickname', title: __('Nickname')},
{field: 'groups_text', title: __('Group'), operate:false, formatter: Table.api.formatter.label},
{field: 'email', title: __('Email')}, {field: 'email', title: __('Email')},
{field: 'status', title: __("Status"), formatter: Table.api.formatter.status}, {field: 'status', title: __("Status"), formatter: Table.api.formatter.status},
{field: 'logintime', title: __('Login time'), formatter: Table.api.formatter.datetime}, {field: 'logintime', title: __('Login time'), formatter: Table.api.formatter.datetime},

View File

@ -24,13 +24,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
[ [
{field: 'state', checkbox: true, }, {field: 'state', checkbox: true, },
{field: 'id', title: 'ID'}, {field: 'id', title: 'ID'},
{field: 'title', title: __('Title'), align: 'left'}, {field: 'title', title: __('Title'), align: 'left', align: 'left', formatter: Controller.api.formatter.title},
{field: 'icon', title: __('Icon'), formatter: Controller.api.formatter.icon}, {field: 'icon', title: __('Icon'), formatter: Controller.api.formatter.icon},
{field: 'name', title: __('Name'), align: 'left'}, {field: 'name', title: __('Name'), align: 'left', formatter: Controller.api.formatter.name},
{field: 'ismenu', title: __('Ismenu'), align: 'left'},
{field: 'weigh', title: __('Weigh')}, {field: 'weigh', title: __('Weigh')},
{field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, {field: 'status', title: __('Status'), formatter: Table.api.formatter.status},
{field: 'id', title: '<a href="javascript:;" class="btn btn-primary btn-xs btn-toggle"><i class="fa fa-chevron-down"></i></a>', operate: false, formatter: Controller.api.formatter.subnode}, {field: 'ismenu', title: __('Ismenu'), align: 'center', formatter: Controller.api.formatter.menu},
{field: 'id', title: '<a href="javascript:;" class="btn btn-success btn-xs btn-toggle"><i class="fa fa-chevron-up"></i></a>', operate: false, formatter: Controller.api.formatter.subnode},
{field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate} {field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate}
] ]
], ],
@ -44,19 +44,21 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
//默认隐藏所有子节点 //默认隐藏所有子节点
table.on('post-body.bs.table', function (e, settings, json, xhr) { table.on('post-body.bs.table', function (e, settings, json, xhr) {
$("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").hide(); //$("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").hide();
}); $(".btn-node-sub.disabled").closest("tr").hide();
//显示隐藏子节点
$(document.body).on("click", ".btn-node-sub", function (e) { //显示隐藏子节点
var status = typeof status !== 'undefined' ? status : $(this).closest("tr").hasClass("selected"); $(".btn-node-sub").off("click").on("click", function (e) {
$("a.btn[data-pid='" + $(this).data("id") + "']").each(function () { var status = $(this).data("shown") ? true : false;
$(this).closest("tr").toggle(status).toggleClass("selected", status); $("a.btn[data-pid='" + $(this).data("id") + "']").each(function () {
$(this).closest("tr").find("input[type=checkbox]").prop("checked", status); $(this).closest("tr").toggle(!status);
// 展示全部子节点 });
// $(this).trigger("click", status); $(this).data("shown", !status);
return false;
}); });
return false;
}); });
//展开隐藏一级
$(document.body).on("click", ".btn-toggle", function (e) { $(document.body).on("click", ".btn-toggle", function (e) {
$("a.btn[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide(); $("a.btn[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide();
var that = this; var that = this;
@ -64,13 +66,16 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
$("i", that).toggleClass("fa-chevron-down", !show); $("i", that).toggleClass("fa-chevron-down", !show);
$("i", that).toggleClass("fa-chevron-up", show); $("i", that).toggleClass("fa-chevron-up", show);
$("a.btn[data-id][data-pid][data-pid!=0]").not('.disabled').closest("tr").toggle(show); $("a.btn[data-id][data-pid][data-pid!=0]").not('.disabled').closest("tr").toggle(show);
$(".btn-node-sub[data-pid=0]").data("shown", show);
}); });
//展开隐藏全部
$(document.body).on("click", ".btn-toggle-all", function (e) { $(document.body).on("click", ".btn-toggle-all", function (e) {
var that = this; var that = this;
var show = $("i", that).hasClass("fa-plus"); var show = $("i", that).hasClass("fa-plus");
$("i", that).toggleClass("fa-plus", !show); $("i", that).toggleClass("fa-plus", !show);
$("i", that).toggleClass("fa-minus", show); $("i", that).toggleClass("fa-minus", show);
$("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").toggle(show); $(".btn-node-sub.disabled").closest("tr").toggle(show);
$(".btn-node-sub").data("shown", show);
}); });
}, },
add: function () { add: function () {
@ -81,11 +86,22 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
}, },
api: { api: {
formatter: { formatter: {
title: function (value, row, index) {
return !row.ismenu ? "<span class='text-muted'>" + value + "</span>" : value;
},
name: function (value, row, index) {
return !row.ismenu ? "<span class='text-muted'>" + value + "</span>" : value;
},
menu: function (value, row, index) {
return "<a href='javascript:;' class='btn btn-" + (value ? "info" : "default") + " btn-xs btn-change' data-id='"
+ row.id + "' data-params='ismenu=" + (value ? 0 : 1) + "'>" + (value ? __('Yes') : __('No')) + "</a>";
},
icon: function (value, row, index) { icon: function (value, row, index) {
return '<i class="' + value + '"></i>'; return '<i class="' + value + '"></i>';
}, },
subnode: function (value, row, index) { subnode: function (value, row, index) {
return '<a href="javascript:;" data-id="' + row['id'] + '" data-pid="' + row['pid'] + '" class="btn btn-primary btn-xs ' + (row['haschild'] == 1 ? '' : 'disabled') + ' btn-node-sub"><i class="fa fa-sitemap"></i></a>'; return '<a href="javascript:;" data-id="' + row['id'] + '" data-pid="' + row['pid'] + '" class="btn btn-xs '
+ (row['haschild'] == 1 ? 'btn-success' : 'btn-default disabled') + ' btn-node-sub"><i class="fa fa-sitemap"></i></a>';
} }
}, },
bindevent: function () { bindevent: function () {

View File

@ -30,9 +30,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
//模糊搜索 //模糊搜索
{field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '模糊搜索,*表示任意字符', style: 'width:200px'}, {field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '模糊搜索,*表示任意字符', style: 'width:200px'},
//通过Ajax渲染searchList也可以使用JSON数据 //通过Ajax渲染searchList也可以使用JSON数据
{field: 'url', title: __('Url'), align: 'left', defaultValue:3, searchList: $.getJSON('ajax/typeahead?search=a&field=row[user_id]'), formatter: Controller.api.formatter.url}, {field: 'url', title: __('Url'), align: 'left', defaultValue: 3, searchList: $.getJSON('ajax/typeahead?search=a&field=row[user_id]'), formatter: Controller.api.formatter.url},
//点击IP时同时执行搜索此IP,同时普通搜索使用下拉列表的形式 //点击IP时同时执行搜索此IP,同时普通搜索使用下拉列表的形式
{field: 'ip', title: __('IP'), searchList: ['127.0.0.1', '127.0.0.2'], events: Controller.api.events.ip, formatter: Controller.api.formatter.ip}, {field: 'ip', title: __('IP'), searchList: ['127.0.0.1', '127.0.0.2'], events: Controller.api.events.ip, formatter: Controller.api.formatter.ip},
//自定义栏位
{field: 'custom', title: __('Custom'), operate: false, formatter: Controller.api.formatter.custom},
//browser是一个不存在的字段 //browser是一个不存在的字段
//通过formatter来渲染数据,同时为它添加上事件 //通过formatter来渲染数据,同时为它添加上事件
{field: 'browser', title: __('Browser'), operate: false, events: Controller.api.events.browser, formatter: Controller.api.formatter.browser}, {field: 'browser', title: __('Browser'), operate: false, events: Controller.api.events.browser, formatter: Controller.api.formatter.browser},
@ -50,6 +52,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
searchFormVisible: true searchFormVisible: true
}); });
//在表格内容渲染完成后回调的事件
table.on('post-body.bs.table', function (e, settings, json, xhr) {
});
// 为表格绑定事件 // 为表格绑定事件
Table.api.bindevent(table); Table.api.bindevent(table);
@ -62,6 +69,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
$(document).on("click", ".btn-selected", function () { $(document).on("click", ".btn-selected", function () {
Layer.alert(JSON.stringify(table.bootstrapTable('getSelections'))); Layer.alert(JSON.stringify(table.bootstrapTable('getSelections')));
}); });
//启动和暂停按钮
$(document).on("click", ".btn-start,.btn-pause", function () {
//在table外不可以使用添加.btn-change的方法
//只能自己调用Table.api.multi实现
Table.api.multi("changestatus", 0, table, this);
});
}, },
add: function () { add: function () {
Controller.api.bindevent(); Controller.api.bindevent();
@ -84,6 +99,10 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
//这里我们直接使用row的数据 //这里我们直接使用row的数据
return '<a class="btn btn-xs btn-browser">' + row.useragent.split(" ")[0] + '</a>'; return '<a class="btn btn-xs btn-browser">' + row.useragent.split(" ")[0] + '</a>';
}, },
custom: function (value, row, index) {
//添加上btn-change可以自定义请求的URL进行数据处理
return '<a class="btn btn-xs btn-danger btn-change" data-url="example/bootstraptable/change" data-id="' + row.id + '">' + __('Locked') + '</a>';
},
operate: function (value, row, index) { operate: function (value, row, index) {
//返回字符串加上Table.api.formatter.operate的结果 //返回字符串加上Table.api.formatter.operate的结果
//默认需要按需显示排序/编辑/删除按钮,则需要在Table.api.formatter.operate将table传入 //默认需要按需显示排序/编辑/删除按钮,则需要在Table.api.formatter.operate将table传入
@ -96,6 +115,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
ip: { ip: {
//格式为:方法名+空格+DOM元素 //格式为:方法名+空格+DOM元素
'click .btn-ip': function (e, value, row, index) { 'click .btn-ip': function (e, value, row, index) {
e.stopPropagation();
var options = $("#table").bootstrapTable('getOptions'); var options = $("#table").bootstrapTable('getOptions');
//这里我们手动将数据填充到表单然后提交 //这里我们手动将数据填充到表单然后提交
$("#commonSearchContent_" + options.idTable + " form [name='ip']").val(value); $("#commonSearchContent_" + options.idTable + " form [name='ip']").val(value);
@ -105,11 +125,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
}, },
browser: { browser: {
'click .btn-browser': function (e, value, row, index) { 'click .btn-browser': function (e, value, row, index) {
e.stopPropagation();
Layer.alert("该行数据为: <code>" + JSON.stringify(row) + "</code>"); Layer.alert("该行数据为: <code>" + JSON.stringify(row) + "</code>");
} }
}, },
operate: $.extend({ operate: $.extend({
'click .btn-detail': function (e, value, row, index) { 'click .btn-detail': function (e, value, row, index) {
e.stopPropagation();
Backend.api.open('example/bootstraptable/detail/ids/' + row['id'], __('Detail')); Backend.api.open('example/bootstraptable/detail/ids/' + row['id'], __('Detail'));
} }
}, Table.api.events.operate) }, Table.api.events.operate)

View File

@ -78,17 +78,10 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
}); });
//添加向发件人发送测试邮件按钮和方法 //添加向发件人发送测试邮件按钮和方法
testMail = '<a class="btn btn-info testmail">向发件人发送测试邮件</a>' $('input[name="row[mail_from]"]').parent().next().append('<a class="btn btn-info testmail">' + __('Send a test message') + '</a>');
$('input[name="row[mail_from]"]').parent().next().append(testMail); $(document).on("click", ".testmail", function () {
$(document).on("click", ".testmail",function(){ Backend.api.ajax({url: "general/config/emailtest", data: {receiver: $('input[name="row[mail_from]"]').val()}});
$.get("/admin/general.config/emailtest", function(result){ });
if (result.data.data) {
Toastr.success(result.data.text)
}else{
Toastr.warning(result.data.text)
}
});
})
}, },
add: function () { add: function () {
Controller.api.bindevent(); Controller.api.bindevent();

View File

@ -162,7 +162,7 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
if ($("ul.sidebar-menu li.active a").size() > 0) { if ($("ul.sidebar-menu li.active a").size() > 0) {
$("ul.sidebar-menu li.active a").trigger("click"); $("ul.sidebar-menu li.active a").trigger("click");
} else { } else {
$("ul.sidebar-menu li a[url!='javascript:;']").trigger("click"); $("ul.sidebar-menu li a[url!='javascript:;']:first").trigger("click");
} }
if (Config.referer) { if (Config.referer) {
//刷新页面后跳到到刷新前的页面 //刷新页面后跳到到刷新前的页面

View File

@ -97,7 +97,6 @@
var resultlist = ret; var resultlist = ret;
isArray = ret.constructor === Array ? true : isArray; isArray = ret.constructor === Array ? true : isArray;
} }
console.log(resultlist);
var optionList = []; var optionList = [];
$.each(resultlist, function (key, value) { $.each(resultlist, function (key, value) {
var isSelect = (isArray ? value : key) == vObjCol.defaultValue ? 'selected' : ''; var isSelect = (isArray ? value : key) == vObjCol.defaultValue ? 'selected' : '';

View File

@ -67,8 +67,6 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func
return false; return false;
}, },
bindevent: function (form, onBeforeSubmit, onAfterSubmit) { bindevent: function (form, onBeforeSubmit, onAfterSubmit) {
//移除提交按钮的disabled类
$(".layer-footer .btn.disabled", form).removeClass("disabled");
//绑定表单事件 //绑定表单事件
form.validator($.extend({ form.validator($.extend({
validClass: 'has-success', validClass: 'has-success',
@ -106,6 +104,9 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func
} }
}, form.data("validator-options") || {})); }, form.data("validator-options") || {}));
//移除提交按钮的disabled类
$(".layer-footer .btn.disabled", form).removeClass("disabled");
//绑定select元素事件 //绑定select元素事件
if ($(".selectpicker", form).size() > 0) { if ($(".selectpicker", form).size() > 0) {
require(['bootstrap-select'], function () { require(['bootstrap-select'], function () {

View File

@ -219,6 +219,10 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
$(table).on("click", "input[data-id][name='checkbox']", function (e) { $(table).on("click", "input[data-id][name='checkbox']", function (e) {
table.trigger('fa.event.check'); table.trigger('fa.event.check');
}); });
$(table).on("click", "[data-id].btn-change", function (e) {
e.preventDefault();
Table.api.multi($(this).data("action") ? $(this).data("action") : '', [$(this).data("id")], table, this);
});
$(table).on("click", "[data-id].btn-edit", function (e) { $(table).on("click", "[data-id].btn-edit", function (e) {
e.preventDefault(); e.preventDefault();
Backend.api.open(options.extend.edit_url + "/ids/" + $(this).data("id"), __('Edit')); Backend.api.open(options.extend.edit_url + "/ids/" + $(this).data("id"), __('Edit'));
@ -245,9 +249,11 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
// 批量操作请求 // 批量操作请求
multi: function (action, ids, table, element) { multi: function (action, ids, table, element) {
var options = table.bootstrapTable('getOptions'); var options = table.bootstrapTable('getOptions');
var url = action == "del" ? options.extend.del_url : options.extend.multi_url; var data = element ? $(element).data() : {};
var url = typeof data.url !== "undefined" ? data.url : (action == "del" ? options.extend.del_url : options.extend.multi_url);
url = url + "/ids/" + ($.isArray(ids) ? ids.join(",") : ids); url = url + "/ids/" + ($.isArray(ids) ? ids.join(",") : ids);
var options = {url: url, data: {action: action, ids: ids, params: element ? $(element).data("params") : ''}}; var params = typeof data.params !== "undefined" ? (typeof data.params == 'object' ? $.param(data.params) : data.params) : '';
var options = {url: url, data: {action: action, ids: ids, params: params}};
Backend.api.ajax(options, function (data) { Backend.api.ajax(options, function (data) {
Toastr.success(__('Operation completed')); Toastr.success(__('Operation completed'));
table.bootstrapTable('refresh'); table.bootstrapTable('refresh');
@ -257,10 +263,12 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
events: { events: {
operate: { operate: {
'click .btn-editone': function (e, value, row, index) { 'click .btn-editone': function (e, value, row, index) {
e.stopPropagation();
var options = $(this).closest('table').bootstrapTable('getOptions'); var options = $(this).closest('table').bootstrapTable('getOptions');
Backend.api.open(options.extend.edit_url + "/ids/" + row[options.pk], __('Edit')); Backend.api.open(options.extend.edit_url + "/ids/" + row[options.pk], __('Edit'));
}, },
'click .btn-delone': function (e, value, row, index) { 'click .btn-delone': function (e, value, row, index) {
e.stopPropagation();
var that = this; var that = this;
var top = $(that).offset().top - $(window).scrollTop(); var top = $(that).offset().top - $(window).scrollTop();
var left = $(that).offset().left - $(window).scrollLeft() - 260; var left = $(that).offset().left - $(window).scrollLeft() - 260;
@ -280,7 +288,6 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
Backend.api.layer.close(index); Backend.api.layer.close(index);
} }
); );
} }
} }
}, },
@ -348,6 +355,18 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table',
}); });
return html.join(' '); return html.join(' ');
}, },
label: function (value, row, index, custom) {
var colorArr = ['success', 'warning', 'danger', 'info'];
//渲染Flag
var html = [];
var arr = value.split(',');
$.each(arr, function (i, value) {
value = value.toString();
var color = colorArr[i % colorArr.length];
html.push('<span class="label label-' + color + '">' + __(value) + '</span>');
});
return html.join(' ');
},
datetime: function (value, row, index) { datetime: function (value, row, index) {
return value ? Moment(parseInt(value) * 1000).format("YYYY-MM-DD HH:mm:ss") : __('None'); return value ? Moment(parseInt(value) * 1000).format("YYYY-MM-DD HH:mm:ss") : __('None');
}, },