diff --git a/application/admin/command/Crud.php b/application/admin/command/Crud.php index df2f7b17..edb41eea 100644 --- a/application/admin/command/Crud.php +++ b/application/admin/command/Crud.php @@ -27,22 +27,32 @@ class Crud extends Command /** * Enum类型识别为单选框的结尾字符,默认会识别为单选下拉列表 */ - protected $enumRadioSuffix = 'data'; + protected $enumRadioSuffix = ['data', 'state', 'status']; /** * 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('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('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'); } @@ -130,6 +150,47 @@ class Crud extends Command $relationForeignKey = $input->getOption('relationforeignkey'); //主键 $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'])) { @@ -140,14 +201,22 @@ class Crud extends Command $prefix = Config::get('database.prefix'); //检查主表 - $tableName = $prefix . $table; + $tableName = $table; + $modelTableType = 'table'; $tableInfo = Db::query("SHOW TABLE STATUS LIKE '{$tableName}'", [], TRUE); 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]; - + + $relationModelTableType = 'table'; //检查关联表 if ($relation) { @@ -155,7 +224,13 @@ class Crud extends Command $relationTableInfo = Db::query("SHOW TABLE STATUS LIKE '{$relationTableName}'", [], TRUE); 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; $attrArr['name'] = "row[{$fieldName}]"; - $itemArr = $this->getLangArray($itemArr, FALSE); + $this->getEnum($getEnumArr, $controllerAssignList, $field, $itemArr, $inputType); + $itemArr = $this->getLangArray($itemArr, FALSE); //添加一个获取器 $this->getAttr($getAttrArr, $field, $inputType); $this->appendAttr($appendAttrList, $field); @@ -478,20 +554,21 @@ class Crud extends Command { $search = $replace = ''; //特殊字段为关联搜索 - if (substr($field, -3) == '_id' || substr($field, -4) == '_ids') + if ($this->isMatchSuffix($field, $this->selectpageSuffix)) { $inputType = 'text'; $defaultValue = ''; $attrArr['data-rule'] = 'required'; $cssClassArr[] = 'selectpage'; $attrArr['data-db-table'] = substr($field, 0, strripos($field, '_')); + //如果是类型表需要特殊处理下 if ($attrArr['data-db-table'] == 'category') { $attrArr['data-params'] = '##replacetext##'; $search = '"##replacetext##"'; $replace = '\'{"custom[type]":"' . $table . '"}\''; } - if (substr($field, -4) == '_ids') + if ($this->isMatchSuffix($field, $this->selectpagesSuffix)) { $attrArr['data-multiple'] = 'true'; } @@ -508,13 +585,9 @@ class Crud extends Command $step = array_intersect($cssClassArr, ['selectpage']) ? 0 : $step; $attrArr['class'] = implode(' ', $cssClassArr); $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; - break; - } + $isUpload = true; } //如果是步长则加上步长 if ($step) @@ -556,11 +629,8 @@ class Crud extends Command $javascriptList[] = "{checkbox: true}"; } //构造JS列信息 - $javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE']); - if ($inputType && in_array($inputType, ['select', 'checkbox', 'radio'])) - { - $javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], '_text'); - } + $javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : ''); + //排序方式,如果有指定排序字段,否则按主键排序 $order = $field == $this->sortField ? $this->sortField : $order; } @@ -631,7 +701,9 @@ class Crud extends Command 'createTime' => in_array('createtime', $fieldArr) ? "'createtime'" : 'false', 'updateTime' => in_array('updatetime', $fieldArr) ? "'updatetime'" : 'false', 'modelTableName' => $table, + 'modelTableType' => $modelTableType, 'relationModelTableName' => $relation, + 'relationModelTableType' => $relationModelTableType, 'relationModelName' => $relationModelName, 'relationWith' => '', 'relationMethod' => '', @@ -842,8 +914,12 @@ EOD; $itemArr = [$field => $fieldLang]; foreach (explode(',', $item) as $k => $v) { - list($key, $value) = explode('=', $v); - $itemArr[$field . ' ' . $key] = $value; + $valArr = explode('=', $v); + if (count($valArr) == 2) + { + list($key, $value) = $valArr; + $itemArr[$field . ' ' . $key] = $value; + } } } else @@ -910,8 +986,12 @@ EOD; $itemArr = []; foreach (explode(',', $item) as $k => $v) { - list($key, $value) = explode('=', $v); - $itemArr[$key] = $field . ' ' . $key; + $valArr = explode('=', $v); + if (count($valArr) == 2) + { + list($key, $value) = $valArr; + $itemArr[$key] = $field . ' ' . $key; + } } } else @@ -964,28 +1044,47 @@ EOD; } $fieldsName = $v['COLUMN_NAME']; // 指定后缀说明也是个时间字段 - if (preg_match("/{$this->intDateSuffix}$/i", $fieldsName)) + if ($this->isMatchSuffix($fieldsName, $this->intDateSuffix)) { $inputType = 'datetime'; } // 指定后缀结尾且类型为enum,说明是个单选框 - if (preg_match("/{$this->enumRadioSuffix}$/i", $fieldsName) && $v['DATA_TYPE'] == 'enum') + if ($this->isMatchSuffix($fieldsName, $this->enumRadioSuffix) && $v['DATA_TYPE'] == 'enum') { $inputType = "radio"; } // 指定后缀结尾且类型为set,说明是个复选框 - if (preg_match("/{$this->setCheckboxSuffix}$/i", $fieldsName) && $v['DATA_TYPE'] == 'set') + if ($this->isMatchSuffix($fieldsName, $this->setCheckboxSuffix) && $v['DATA_TYPE'] == 'set') { $inputType = "checkbox"; } // 指定后缀结尾且类型为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"; } 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 @@ -1014,13 +1113,9 @@ EOD; protected function getImageUpload($field, $content) { $filter = ''; - foreach ($this->imageField as $k => $v) + if ($this->isMatchSuffix($field, $this->imageField)) { - if (preg_match("/{$v}$/i", $field)) - { - $filter = ' data-mimetype="image/*"'; - break; - } + $filter = ' data-mimetype="image/*"'; } $multiple = substr($field, -1) == 's' ? ' data-multiple="true"' : ' data-multiple="false"'; $preview = $filter ? ' data-preview-id="p-' . $field . '"' : ''; @@ -1064,9 +1159,16 @@ EOD; } } } + $formatter = $extend ? '' : $formatter; if ($extend) + { $html .= ", operate:false"; - if ($formatter && !$extend) + if ($datatype == 'set') + { + $formatter = 'label'; + } + } + if ($formatter) $html .= ", formatter: Table.api.formatter." . $formatter . "}"; else $html .= "}"; diff --git a/application/admin/command/Crud/stubs/add.stub b/application/admin/command/Crud/stubs/add.stub index 61a84b3b..68d6de24 100644 --- a/application/admin/command/Crud/stubs/add.stub +++ b/application/admin/command/Crud/stubs/add.stub @@ -4,7 +4,7 @@ diff --git a/application/admin/command/Crud/stubs/edit.stub b/application/admin/command/Crud/stubs/edit.stub index 1c8edf38..1a6f297c 100644 --- a/application/admin/command/Crud/stubs/edit.stub +++ b/application/admin/command/Crud/stubs/edit.stub @@ -4,7 +4,7 @@ diff --git a/application/admin/command/Crud/stubs/model.stub b/application/admin/command/Crud/stubs/model.stub index 79ed5074..ad2762eb 100644 --- a/application/admin/command/Crud/stubs/model.stub +++ b/application/admin/command/Crud/stubs/model.stub @@ -6,8 +6,8 @@ use think\Model; class {%modelName%} extends Model { - // 表名,不含前缀 - protected $name = '{%modelTableName%}'; + // 表名 + protected ${%modelTableType%} = '{%modelTableName%}'; // 自动写入时间戳字段 protected $autoWriteTimestamp = {%modelAutoWriteTimestamp%}; diff --git a/application/admin/command/Crud/stubs/relationmodel.stub b/application/admin/command/Crud/stubs/relationmodel.stub index e0a8c090..17f80693 100644 --- a/application/admin/command/Crud/stubs/relationmodel.stub +++ b/application/admin/command/Crud/stubs/relationmodel.stub @@ -6,7 +6,7 @@ use think\Model; class {%relationModelName%} extends Model { - // 表名,不含前缀 - protected $name = '{%relationModelTableName%}'; + // 表名 + protected ${%relationModelTableType%} = '{%relationModelTableName%}'; } diff --git a/application/admin/controller/Ajax.php b/application/admin/controller/Ajax.php index 3081c700..cf06e372 100644 --- a/application/admin/controller/Ajax.php +++ b/application/admin/controller/Ajax.php @@ -153,6 +153,7 @@ class Ajax extends Backend public function roletree() { $this->loadlang('auth/group'); + $model = model('AuthGroup'); $id = $this->request->post("id"); $pid = $this->request->post("pid"); @@ -165,22 +166,50 @@ class Ajax extends Backend if (($pid || $parentgroupmodel) && (!$id || $currentgroupmodel)) { $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集合 $admin_rule_ids = $this->auth->getRuleIds(); + //是否是超级管理员 $superadmin = $this->auth->isSuperAdmin(); + //当前拥有的规则ID集合 $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 = []; - foreach ($parentrulelist as $k => $v) + foreach ($parentRuleList as $k => $v) { if (!$superadmin && !in_array($v['id'], $admin_rule_ids)) 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); } $this->code = 1; @@ -206,7 +235,7 @@ class Ajax extends Backend { $this->code = -1; $file = $this->request->file('file'); - if (!$file) + if (empty($file)) { $this->msg = "未上传文件或超出服务器上传限制"; return; diff --git a/application/admin/controller/auth/Admin.php b/application/admin/controller/auth/Admin.php index 23a36e4f..f4a54872 100644 --- a/application/admin/controller/auth/Admin.php +++ b/application/admin/controller/auth/Admin.php @@ -52,10 +52,21 @@ class Admin extends Backend { if ($this->request->isAjax()) { - $childrenAdminIds = model('AuthGroupAccess') - ->field('uid') + $groupData = model('AuthGroup')->where('status', 'normal')->column('id,name'); + + $childrenAdminIds = []; + $authGroupList = model('AuthGroupAccess') + ->field('uid,group_id') ->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(); $total = $this->model ->where($where) @@ -70,6 +81,12 @@ class Admin extends Backend ->order($sort, $order) ->limit($offset, $limit) ->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); return json($result); diff --git a/application/admin/controller/auth/Rule.php b/application/admin/controller/auth/Rule.php index b8cae2a3..f2a418e5 100644 --- a/application/admin/controller/auth/Rule.php +++ b/application/admin/controller/auth/Rule.php @@ -17,6 +17,7 @@ class Rule extends Backend protected $model = null; protected $rulelist = []; + protected $multiFields = 'ismenu,status'; public function _initialize() { @@ -133,14 +134,4 @@ class Rule extends Backend return; } - /** - * 批量更新 - * @internal - */ - public function multi($ids = "") - { - // 节点禁止批量操作 - $this->code = -1; - } - } diff --git a/application/admin/controller/example/Bootstraptable.php b/application/admin/controller/example/Bootstraptable.php index 24502db0..914c84e1 100644 --- a/application/admin/controller/example/Bootstraptable.php +++ b/application/admin/controller/example/Bootstraptable.php @@ -14,6 +14,7 @@ class Bootstraptable extends Backend { protected $model = null; + protected $noNeedRight = ['change', 'detail']; public function _initialize() { @@ -44,7 +45,7 @@ class Bootstraptable extends Backend } return $this->view->fetch(); } - + /** * 详情 */ @@ -57,4 +58,13 @@ class Bootstraptable extends Backend return $this->view->fetch(); } + /** + * 变更 + * @internal + */ + public function change() + { + $this->code = 1; + } + } diff --git a/application/admin/controller/general/Config.php b/application/admin/controller/general/Config.php index 618bb3a6..dcfc4960 100644 --- a/application/admin/controller/general/Config.php +++ b/application/admin/controller/general/Config.php @@ -1,8 +1,7 @@ 这是一封测试邮件,用于测试邮件配置是否正常!'; - - $site = tpConfig::get("site"); + $receiver = $this->request->request("receiver"); $email = new Email; - $mailArr = Array(); - $mailArr['mTo'] = $site['mail_from']; //收件人 - $mailArr['subject'] = '这是一封测试邮件'; //邮件主题 - $mailArr['content'] = $content; //邮件内容(html) - $mailArr['fromNic'] = 'Fastadmin系统邮件'; //发件人昵称[可省略] - $mailArr['toNic'] = '亲爱的用户'; //收件人昵称[可省略]貌似无效 - $data = $email->sendMail($mailArr['mTo'],$mailArr['subject'],$mailArr['content'],$mailArr['fromNic'],$mailArr['toNic']); - return json(['data'=>$data,'code'=>200,'message'=>'操作完成']); + $result = $email + ->to($receiver) + ->subject(__("This is a test mail")) + ->message('
' . __('This is a test mail content') . '
') + ->send(); + if ($result) + { + $this->code = 1; + } + else + { + $this->code = -1; + $this->msg = $email->getError(); + } } + } diff --git a/application/admin/lang/zh-cn.php b/application/admin/lang/zh-cn.php index a55c770f..d9ad4c23 100644 --- a/application/admin/lang/zh-cn.php +++ b/application/admin/lang/zh-cn.php @@ -14,6 +14,7 @@ return [ 'Add' => '添加', 'Edit' => '编辑', 'Delete' => '删除', + 'Detail' => '详情', 'Move' => '移动', 'Name' => '名称', 'Status' => '状态', diff --git a/application/admin/lang/zh-cn/general/attachment.php b/application/admin/lang/zh-cn/general/attachment.php index 5eb97f9e..ad0c8047 100644 --- a/application/admin/lang/zh-cn/general/attachment.php +++ b/application/admin/lang/zh-cn/general/attachment.php @@ -1,16 +1,17 @@ '物理路径', - 'Imagewidth' => '宽度', - 'Imageheight' => '宽度', - 'Imagetype' => '图片类型', - 'Imageframes' => '图片帧数', - 'Preview' => '预览', - 'Filesize' => '文件大小', - 'Mimetype' => 'Mime类型', - 'Extparam' => '透传数据', - 'Createtime' => '创建日期', - 'Uploadtime' => '上传时间', - 'Storage' => '存储引擎' + 'Url' => '物理路径', + 'Imagewidth' => '宽度', + 'Imageheight' => '宽度', + 'Imagetype' => '图片类型', + 'Imageframes' => '图片帧数', + 'Preview' => '预览', + 'Filesize' => '文件大小', + 'Mimetype' => 'Mime类型', + 'Extparam' => '透传数据', + 'Createtime' => '创建日期', + 'Uploadtime' => '上传时间', + 'Storage' => '存储引擎', + 'Upload by summernote' => '从编辑器上传' ]; diff --git a/application/admin/lang/zh-cn/general/config.php b/application/admin/lang/zh-cn/general/config.php index a04a5e48..60511256 100644 --- a/application/admin/lang/zh-cn/general/config.php +++ b/application/admin/lang/zh-cn/general/config.php @@ -1,36 +1,39 @@ '变量名', - 'Tip' => '提示信息', - 'Group' => '分组', - 'Type' => '类型', - 'Title' => '变量标题', - 'Value' => '变量值', - 'Basic' => '基础配置', - 'Email' => '邮件配置', - 'Attachment' => '附件配置', - 'User' => '会员配置', - 'Example' => '示例分组', - 'Extend' => '扩展属性', - 'String' => '字符', - 'Text' => '文本', - 'Number' => '数字', - 'Date' => '日期', - 'Time' => '时间', - 'Datetime' => '日期时间', - 'Image' => '图片', - 'Images' => '图片(多)', - 'File' => '文件', - 'Files' => '文件(多)', - 'Select' => '列表', - 'Selects' => '列表(多选)', - 'Checkbox' => '复选', - 'Radio' => '单选', - 'Array' => '数组', - 'Array key' => '键名', - 'Array value' => '键值', - 'Content' => '数据列表', - 'Rule' => '校验规则', - 'Name already exist' => '变量名称已经存在', + 'Name' => '变量名', + 'Tip' => '提示信息', + 'Group' => '分组', + 'Type' => '类型', + 'Title' => '变量标题', + 'Value' => '变量值', + 'Basic' => '基础配置', + 'Email' => '邮件配置', + 'Attachment' => '附件配置', + 'User' => '会员配置', + 'Example' => '示例分组', + 'Extend' => '扩展属性', + 'String' => '字符', + 'Text' => '文本', + 'Number' => '数字', + 'Date' => '日期', + 'Time' => '时间', + 'Datetime' => '日期时间', + 'Image' => '图片', + 'Images' => '图片(多)', + 'File' => '文件', + 'Files' => '文件(多)', + 'Select' => '列表', + 'Selects' => '列表(多选)', + 'Checkbox' => '复选', + 'Radio' => '单选', + 'Array' => '数组', + 'Array key' => '键名', + 'Array value' => '键值', + 'Content' => '数据列表', + 'Rule' => '校验规则', + 'Name already exist' => '变量名称已经存在', + 'Send a test message' => '发送测试邮件', + 'This is a test mail content' => '这是一封测试邮件,用于测试邮件配置是否正常!', + 'This is a test mail' => '这是一封测试邮件', ]; diff --git a/application/admin/library/traits/Backend.php b/application/admin/library/traits/Backend.php index 093fa456..e166dc28 100644 --- a/application/admin/library/traits/Backend.php +++ b/application/admin/library/traits/Backend.php @@ -163,7 +163,7 @@ trait Backend if ($this->request->has('params')) { 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) { $count = $this->model->where($this->model->getPk(), 'in', $ids)->update($values); @@ -172,6 +172,10 @@ trait Backend $this->code = 1; } } + else + { + $this->msg = __('You have no permission'); + } } else { diff --git a/application/admin/view/auth/admin/add.html b/application/admin/view/auth/admin/add.html index eb2be51e..de739965 100644 --- a/application/admin/view/auth/admin/add.html +++ b/application/admin/view/auth/admin/add.html @@ -38,7 +38,7 @@ diff --git a/application/admin/view/auth/admin/edit.html b/application/admin/view/auth/admin/edit.html index c15bc203..0c15fa69 100644 --- a/application/admin/view/auth/admin/edit.html +++ b/application/admin/view/auth/admin/edit.html @@ -38,7 +38,7 @@ diff --git a/application/admin/view/auth/group/add.html b/application/admin/view/auth/group/add.html index 240e6c61..5e2aa8b2 100644 --- a/application/admin/view/auth/group/add.html +++ b/application/admin/view/auth/group/add.html @@ -30,7 +30,7 @@ diff --git a/application/admin/view/auth/group/edit.html b/application/admin/view/auth/group/edit.html index 669c2638..e7b433b2 100644 --- a/application/admin/view/auth/group/edit.html +++ b/application/admin/view/auth/group/edit.html @@ -30,7 +30,7 @@ diff --git a/application/admin/view/auth/rule/add.html b/application/admin/view/auth/rule/add.html index ea5c76c9..f6539d02 100644 --- a/application/admin/view/auth/rule/add.html +++ b/application/admin/view/auth/rule/add.html @@ -63,7 +63,7 @@ diff --git a/application/admin/view/auth/rule/edit.html b/application/admin/view/auth/rule/edit.html index b58fe79b..e4accf08 100644 --- a/application/admin/view/auth/rule/edit.html +++ b/application/admin/view/auth/rule/edit.html @@ -59,7 +59,7 @@ diff --git a/application/admin/view/category/add.html b/application/admin/view/category/add.html index 5fc3f376..edbdb699 100644 --- a/application/admin/view/category/add.html +++ b/application/admin/view/category/add.html @@ -51,7 +51,7 @@ diff --git a/application/admin/view/category/edit.html b/application/admin/view/category/edit.html index 02c25b70..a9e97153 100644 --- a/application/admin/view/category/edit.html +++ b/application/admin/view/category/edit.html @@ -51,7 +51,7 @@ diff --git a/application/admin/view/example/bootstraptable/index.html b/application/admin/view/example/bootstraptable/index.html index f3e3b5af..11e7f72e 100644 --- a/application/admin/view/example/bootstraptable/index.html +++ b/application/admin/view/example/bootstraptable/index.html @@ -16,6 +16,8 @@
  • {:__('Set to hidden')}
  • + 启动 + 暂停 diff --git a/application/admin/view/general/attachment/edit.html b/application/admin/view/general/attachment/edit.html index b101df65..2a9793ce 100644 --- a/application/admin/view/general/attachment/edit.html +++ b/application/admin/view/general/attachment/edit.html @@ -63,7 +63,7 @@ diff --git a/application/admin/view/general/config/index.html b/application/admin/view/general/config/index.html index 8234ac21..3e036224 100644 --- a/application/admin/view/general/config/index.html +++ b/application/admin/view/general/config/index.html @@ -126,7 +126,7 @@ @@ -205,7 +205,7 @@ key2|value2
    - +
    diff --git a/application/admin/view/general/configvalue/add.html b/application/admin/view/general/configvalue/add.html index 5d18915c..095a60e1 100644 --- a/application/admin/view/general/configvalue/add.html +++ b/application/admin/view/general/configvalue/add.html @@ -44,7 +44,7 @@ diff --git a/application/admin/view/general/configvalue/edit.html b/application/admin/view/general/configvalue/edit.html index b5e63831..dfd1e289 100644 --- a/application/admin/view/general/configvalue/edit.html +++ b/application/admin/view/general/configvalue/edit.html @@ -46,7 +46,7 @@ diff --git a/application/admin/view/general/crontab/add.html b/application/admin/view/general/crontab/add.html index f117d0c9..826e56b2 100644 --- a/application/admin/view/general/crontab/add.html +++ b/application/admin/view/general/crontab/add.html @@ -73,7 +73,7 @@ diff --git a/application/admin/view/general/crontab/edit.html b/application/admin/view/general/crontab/edit.html index c893e61b..caa2aea4 100644 --- a/application/admin/view/general/crontab/edit.html +++ b/application/admin/view/general/crontab/edit.html @@ -73,7 +73,7 @@ diff --git a/application/admin/view/page/add.html b/application/admin/view/page/add.html index e1bf0d59..021952e2 100644 --- a/application/admin/view/page/add.html +++ b/application/admin/view/page/add.html @@ -73,7 +73,7 @@ diff --git a/application/admin/view/page/edit.html b/application/admin/view/page/edit.html index 8133be3b..0620a4c4 100644 --- a/application/admin/view/page/edit.html +++ b/application/admin/view/page/edit.html @@ -74,7 +74,7 @@ diff --git a/application/admin/view/user/third/add.phtml b/application/admin/view/user/third/add.phtml index ba60f131..b0b61890 100644 --- a/application/admin/view/user/third/add.phtml +++ b/application/admin/view/user/third/add.phtml @@ -56,7 +56,7 @@ diff --git a/application/admin/view/user/third/edit.phtml b/application/admin/view/user/third/edit.phtml index dd2931a8..c89ccded 100644 --- a/application/admin/view/user/third/edit.phtml +++ b/application/admin/view/user/third/edit.phtml @@ -57,7 +57,7 @@ diff --git a/application/admin/view/user/user/add.phtml b/application/admin/view/user/user/add.phtml index 6d0b7192..a9803459 100644 --- a/application/admin/view/user/user/add.phtml +++ b/application/admin/view/user/user/add.phtml @@ -185,7 +185,7 @@ diff --git a/application/admin/view/user/user/edit.phtml b/application/admin/view/user/user/edit.phtml index d6f39b47..b4579aa1 100644 --- a/application/admin/view/user/user/edit.phtml +++ b/application/admin/view/user/user/edit.phtml @@ -180,7 +180,7 @@ diff --git a/application/admin/view/version/add.html b/application/admin/view/version/add.html index 43420ff2..6887392c 100644 --- a/application/admin/view/version/add.html +++ b/application/admin/view/version/add.html @@ -57,7 +57,7 @@ diff --git a/application/admin/view/version/edit.html b/application/admin/view/version/edit.html index cb295a21..34b1b73b 100644 --- a/application/admin/view/version/edit.html +++ b/application/admin/view/version/edit.html @@ -51,7 +51,7 @@ diff --git a/application/admin/view/wechat/autoreply/add.html b/application/admin/view/wechat/autoreply/add.html index 118cd13f..bd31f5cd 100644 --- a/application/admin/view/wechat/autoreply/add.html +++ b/application/admin/view/wechat/autoreply/add.html @@ -43,7 +43,7 @@ diff --git a/application/admin/view/wechat/autoreply/edit.html b/application/admin/view/wechat/autoreply/edit.html index cbc94851..9c74994e 100644 --- a/application/admin/view/wechat/autoreply/edit.html +++ b/application/admin/view/wechat/autoreply/edit.html @@ -44,7 +44,7 @@ diff --git a/application/admin/view/wechat/config/add.html b/application/admin/view/wechat/config/add.html index aa32d7c7..015f524f 100644 --- a/application/admin/view/wechat/config/add.html +++ b/application/admin/view/wechat/config/add.html @@ -38,7 +38,7 @@ diff --git a/application/admin/view/wechat/config/edit.html b/application/admin/view/wechat/config/edit.html index 7e43223a..334731cf 100644 --- a/application/admin/view/wechat/config/edit.html +++ b/application/admin/view/wechat/config/edit.html @@ -40,7 +40,7 @@ diff --git a/application/admin/view/wechat/response/add.html b/application/admin/view/wechat/response/add.html index b3a36b2a..6d718a5d 100644 --- a/application/admin/view/wechat/response/add.html +++ b/application/admin/view/wechat/response/add.html @@ -32,7 +32,7 @@
    - +
    diff --git a/application/admin/view/wechat/response/edit.html b/application/admin/view/wechat/response/edit.html index ceece66a..9ee6d32a 100644 --- a/application/admin/view/wechat/response/edit.html +++ b/application/admin/view/wechat/response/edit.html @@ -36,7 +36,7 @@ diff --git a/application/common/controller/Backend.php b/application/common/controller/Backend.php index 1526f028..d259bed6 100644 --- a/application/common/controller/Backend.php +++ b/application/common/controller/Backend.php @@ -78,6 +78,11 @@ class Backend extends Controller * 是否开启模型场景验证 */ protected $modelSceneValidate = false; + + /** + * Multi方法可批量修改的字段 + */ + protected $multiFields = 'status'; /** * 引入后台控制器的traits diff --git a/application/common/library/Email.php b/application/common/library/Email.php index e60ddadd..08b09a5d 100644 --- a/application/common/library/Email.php +++ b/application/common/library/Email.php @@ -6,81 +6,186 @@ use think\Config; 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 收件人 - * @param string $subject 邮件主题 - * @param string $content 邮件内容(html) - * @param string $fromNic 发件人昵称 - * @param string $toNic 收件人昵称 + * @return boolean */ - public function sendMail($mTo='',$subject='',$content='',$fromNic='',$toNic='') + public function send() { - $site = Config::get("site"); - $re = Vendor('phpmailer.phpmailer.PHPMailerAutoload'); - - $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 + $result = false; + switch ($this->options['mail_type']) { - case 1: - $mail->SMTPSecure = 'tls'; - break; - case 2: - $mail->SMTPSecure = 'ssl'; - break; - default: - $mail->SMTPSecure = ''; - } - $mail->Port = $site['mail_smtp_port']; // 设置ssl连接smtp服务器的远程服务器端口号 - $mail->setFrom($site['mail_from'], $fromNic); // [发件人],[昵称(可选)] - $mail->addAddress($mTo, $toNic); // [收件人],[昵称(可选)] - //$mail->addReplyTo('xxxxxx@qq.com', 'Information'); // 回复地址(可选) - //$mail->addCC('xxxxxx@qq.com'); //好像是密送 - //$mail->addBCC('xxxxxx@qq.com'); //好像是密送B - // $mail->addAttachment('/var/tmp/file.tar.gz'); // 添加附件 - // $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // 附件名选项 - $mail->isHTML(true); //邮件正文是否为html编码 - $mail->Subject = $subject; //添加邮件主题 - $mail->Body = $content; //邮件正文 - //$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';//附加信息,可以省略 + case 1: + //使用phpmailer发送 + $this->mail->setFrom($this->options['from'], $this->options['from_name']); + $this->mail->addAddress($this->options['to'], $this->options['to_name']); + $this->mail->Subject = $this->options['subject']; + if ($this->options['ishtml']) + { + $this->mail->msgHTML($this->options['body']); + } + else + { + $this->mail->Body = $this->options['body']; + } + try + { + $result = $this->mail->send(); + } + catch (\phpmailerException $e) + { + $this->setError($e->getMessage()); + } - switch ($site['mail_type']) - { - case 1: - if(!$mail->send()) {//这里如果提交错误的smpt配置PHPmailer会卡住暂时不清楚为什么 - $sendResult['text'] = $mail->ErrorInfo; - $sendResult['data'] = false; - return $sendResult; - } else { - $sendResult['text'] ='smtp发送成功'; - $sendResult['data'] = true; - return $sendResult; - } - break; - case 2://使用mail方法发送邮件 - $headers = 'MIME-Version: 1.0' . "\r\n"; - $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; + $this->setError($result ? '' : $this->mail->ErrorInfo); + break; + case 2: + //使用mail方法发送邮件 + $headers = 'MIME-Version: 1.0' . "\r\n"; + $headers .= "Content-type: text/html; charset=" . $this->options['charset'] . "\r\n"; + $headers .= "To: {$this->options['to_name']} <{$this->options['to']}>\r\n"; //收件人 + $headers .= "From: {$this->options['from_name']} <{$this->options['from']}>\r\n"; //发件人 + $result = mail($this->options['mail_to'], $this->options['subject'], $this->options['body'], $headers); + $this->setError($result ? '' : error_get_last()['message']); + break; + default: + //邮件功能已关闭 + $this->setError(__('Mail already closed')); + break; } + return $result; } + } diff --git a/public/assets/js/backend.js b/public/assets/js/backend.js index df7aaf8e..92b03b9a 100755 --- a/public/assets/js/backend.js +++ b/public/assets/js/backend.js @@ -119,15 +119,10 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang', 'moment'], function ($ }); }, open: function (url, title, options) { - title = title == undefined ? "" : title; + title = title ? title : ""; url = Backend.api.fixurl(url); url = url + (url.indexOf("?") > -1 ? "&" : "?") + "dialog=1"; - var area; - if ($(window).width() < 800) { - area = ["95%", "95%"]; - } else { - area = ['800px', '600px']; - } + var area = [$(window).width() > 800 ? '800px' : '95%', $(window).height() > 600 ? '600px' : '95%']; Backend.api.layer.open($.extend({ type: 2, title: title, @@ -188,7 +183,7 @@ define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang', 'moment'], function ($ var btnHeight = layero.find('.layui-layer-btn').outerHeight() || 0; 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) { maxheg = $(window).height(); } diff --git a/public/assets/js/backend/auth/admin.js b/public/assets/js/backend/auth/admin.js index c00b2f00..8fe1eae5 100755 --- a/public/assets/js/backend/auth/admin.js +++ b/public/assets/js/backend/auth/admin.js @@ -24,6 +24,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin {field: 'id', title: 'ID'}, {field: 'username', title: __('Username')}, {field: 'nickname', title: __('Nickname')}, + {field: 'groups_text', title: __('Group'), operate:false, formatter: Table.api.formatter.label}, {field: 'email', title: __('Email')}, {field: 'status', title: __("Status"), formatter: Table.api.formatter.status}, {field: 'logintime', title: __('Login time'), formatter: Table.api.formatter.datetime}, diff --git a/public/assets/js/backend/auth/rule.js b/public/assets/js/backend/auth/rule.js index 34b4fd11..1dc342f8 100755 --- a/public/assets/js/backend/auth/rule.js +++ b/public/assets/js/backend/auth/rule.js @@ -24,13 +24,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function [ {field: 'state', checkbox: true, }, {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: 'name', title: __('Name'), align: 'left'}, - {field: 'ismenu', title: __('Ismenu'), align: 'left'}, + {field: 'name', title: __('Name'), align: 'left', formatter: Controller.api.formatter.name}, {field: 'weigh', title: __('Weigh')}, {field: 'status', title: __('Status'), formatter: Table.api.formatter.status}, - {field: 'id', title: '', operate: false, formatter: Controller.api.formatter.subnode}, + {field: 'ismenu', title: __('Ismenu'), align: 'center', formatter: Controller.api.formatter.menu}, + {field: 'id', title: '', operate: false, formatter: Controller.api.formatter.subnode}, {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) { - $("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").hide(); - }); - //显示隐藏子节点 - $(document.body).on("click", ".btn-node-sub", function (e) { - var status = typeof status !== 'undefined' ? status : $(this).closest("tr").hasClass("selected"); - $("a.btn[data-pid='" + $(this).data("id") + "']").each(function () { - $(this).closest("tr").toggle(status).toggleClass("selected", status); - $(this).closest("tr").find("input[type=checkbox]").prop("checked", status); - // 展示全部子节点 - // $(this).trigger("click", status); + //$("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").hide(); + $(".btn-node-sub.disabled").closest("tr").hide(); + + //显示隐藏子节点 + $(".btn-node-sub").off("click").on("click", function (e) { + var status = $(this).data("shown") ? true : false; + $("a.btn[data-pid='" + $(this).data("id") + "']").each(function () { + $(this).closest("tr").toggle(!status); + }); + $(this).data("shown", !status); + return false; }); - return false; + }); + //展开隐藏一级 $(document.body).on("click", ".btn-toggle", function (e) { $("a.btn[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide(); 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-up", 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) { var that = this; var show = $("i", that).hasClass("fa-plus"); $("i", that).toggleClass("fa-plus", !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 () { @@ -81,11 +86,22 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function }, api: { formatter: { + title: function (value, row, index) { + return !row.ismenu ? "" + value + "" : value; + }, + name: function (value, row, index) { + return !row.ismenu ? "" + value + "" : value; + }, + menu: function (value, row, index) { + return "" + (value ? __('Yes') : __('No')) + ""; + }, icon: function (value, row, index) { return ''; }, subnode: function (value, row, index) { - return ''; + return ''; } }, bindevent: function () { diff --git a/public/assets/js/backend/example/bootstraptable.js b/public/assets/js/backend/example/bootstraptable.js index cc30b370..b3e2bc6d 100644 --- a/public/assets/js/backend/example/bootstraptable.js +++ b/public/assets/js/backend/example/bootstraptable.js @@ -30,9 +30,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin //模糊搜索 {field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '模糊搜索,*表示任意字符', style: 'width:200px'}, //通过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,同时普通搜索使用下拉列表的形式 {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是一个不存在的字段 //通过formatter来渲染数据,同时为它添加上事件 {field: 'browser', title: __('Browser'), operate: false, events: Controller.api.events.browser, formatter: Controller.api.formatter.browser}, @@ -49,6 +51,11 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin //可以控制是否默认显示搜索单表,false则隐藏,默认为false searchFormVisible: true }); + + //在表格内容渲染完成后回调的事件 + table.on('post-body.bs.table', function (e, settings, json, xhr) { + + }); // 为表格绑定事件 Table.api.bindevent(table); @@ -62,6 +69,14 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin $(document).on("click", ".btn-selected", function () { 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 () { Controller.api.bindevent(); @@ -84,6 +99,10 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin //这里我们直接使用row的数据 return '' + row.useragent.split(" ")[0] + ''; }, + custom: function (value, row, index) { + //添加上btn-change可以自定义请求的URL进行数据处理 + return '' + __('Locked') + ''; + }, operate: function (value, row, index) { //返回字符串加上Table.api.formatter.operate的结果 //默认需要按需显示排序/编辑/删除按钮,则需要在Table.api.formatter.operate将table传入 @@ -96,6 +115,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin ip: { //格式为:方法名+空格+DOM元素 'click .btn-ip': function (e, value, row, index) { + e.stopPropagation(); var options = $("#table").bootstrapTable('getOptions'); //这里我们手动将数据填充到表单然后提交 $("#commonSearchContent_" + options.idTable + " form [name='ip']").val(value); @@ -105,11 +125,13 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin }, browser: { 'click .btn-browser': function (e, value, row, index) { + e.stopPropagation(); Layer.alert("该行数据为: " + JSON.stringify(row) + ""); } }, operate: $.extend({ 'click .btn-detail': function (e, value, row, index) { + e.stopPropagation(); Backend.api.open('example/bootstraptable/detail/ids/' + row['id'], __('Detail')); } }, Table.api.events.operate) diff --git a/public/assets/js/backend/general/config.js b/public/assets/js/backend/general/config.js index 4b893811..4b4912d2 100644 --- a/public/assets/js/backend/general/config.js +++ b/public/assets/js/backend/general/config.js @@ -78,17 +78,10 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin }); //添加向发件人发送测试邮件按钮和方法 - testMail = '向发件人发送测试邮件' - $('input[name="row[mail_from]"]').parent().next().append(testMail); - $(document).on("click", ".testmail",function(){ - $.get("/admin/general.config/emailtest", function(result){ - if (result.data.data) { - Toastr.success(result.data.text) - }else{ - Toastr.warning(result.data.text) - } - }); - }) + $('input[name="row[mail_from]"]').parent().next().append('' + __('Send a test message') + ''); + $(document).on("click", ".testmail", function () { + Backend.api.ajax({url: "general/config/emailtest", data: {receiver: $('input[name="row[mail_from]"]').val()}}); + }); }, add: function () { Controller.api.bindevent(); diff --git a/public/assets/js/backend/index.js b/public/assets/js/backend/index.js index e05a458c..f477d20e 100755 --- a/public/assets/js/backend/index.js +++ b/public/assets/js/backend/index.js @@ -162,7 +162,7 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi if ($("ul.sidebar-menu li.active a").size() > 0) { $("ul.sidebar-menu li.active a").trigger("click"); } else { - $("ul.sidebar-menu li a[url!='javascript:;']").trigger("click"); + $("ul.sidebar-menu li a[url!='javascript:;']:first").trigger("click"); } if (Config.referer) { //刷新页面后跳到到刷新前的页面 diff --git a/public/assets/js/bootstrap-table-commonsearch.js b/public/assets/js/bootstrap-table-commonsearch.js index c6d597ab..a9fb98bb 100644 --- a/public/assets/js/bootstrap-table-commonsearch.js +++ b/public/assets/js/bootstrap-table-commonsearch.js @@ -97,7 +97,6 @@ var resultlist = ret; isArray = ret.constructor === Array ? true : isArray; } - console.log(resultlist); var optionList = []; $.each(resultlist, function (key, value) { var isSelect = (isArray ? value : key) == vObjCol.defaultValue ? 'selected' : ''; diff --git a/public/assets/js/require-form.js b/public/assets/js/require-form.js index 4d8df9b2..511b8d03 100755 --- a/public/assets/js/require-form.js +++ b/public/assets/js/require-form.js @@ -67,8 +67,6 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func return false; }, bindevent: function (form, onBeforeSubmit, onAfterSubmit) { - //移除提交按钮的disabled类 - $(".layer-footer .btn.disabled", form).removeClass("disabled"); //绑定表单事件 form.validator($.extend({ validClass: 'has-success', @@ -105,6 +103,9 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'upload', 'validator'], func return false; } }, form.data("validator-options") || {})); + + //移除提交按钮的disabled类 + $(".layer-footer .btn.disabled", form).removeClass("disabled"); //绑定select元素事件 if ($(".selectpicker", form).size() > 0) { diff --git a/public/assets/js/require-table.js b/public/assets/js/require-table.js index 19ebbb21..70041b31 100644 --- a/public/assets/js/require-table.js +++ b/public/assets/js/require-table.js @@ -219,6 +219,10 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table', $(table).on("click", "input[data-id][name='checkbox']", function (e) { 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) { e.preventDefault(); 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) { 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); - 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) { Toastr.success(__('Operation completed')); table.bootstrapTable('refresh'); @@ -257,10 +263,12 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table', events: { operate: { 'click .btn-editone': function (e, value, row, index) { + e.stopPropagation(); var options = $(this).closest('table').bootstrapTable('getOptions'); Backend.api.open(options.extend.edit_url + "/ids/" + row[options.pk], __('Edit')); }, 'click .btn-delone': function (e, value, row, index) { + e.stopPropagation(); var that = this; var top = $(that).offset().top - $(window).scrollTop(); 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); } ); - } } }, @@ -348,6 +355,18 @@ define(['jquery', 'bootstrap', 'backend', 'toastr', 'moment', 'bootstrap-table', }); 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('' + __(value) + ''); + }); + return html.join(' '); + }, datetime: function (value, row, index) { return value ? Moment(parseInt(value) * 1000).format("YYYY-MM-DD HH:mm:ss") : __('None'); },
    - +