diff --git a/application/admin/command/Api/library/Builder.php b/application/admin/command/Api/library/Builder.php index 1eb8b258..64a2ebd3 100755 --- a/application/admin/command/Api/library/Builder.php +++ b/application/admin/command/Api/library/Builder.php @@ -7,7 +7,7 @@ use think\Config; /** * @website https://github.com/calinrada/php-apidoc * @author Calin Rada - * @author Karson + * @author Karson */ class Builder { diff --git a/application/admin/command/Crud.php b/application/admin/command/Crud.php index 3c5a2359..42eb4386 100755 --- a/application/admin/command/Crud.php +++ b/application/admin/command/Crud.php @@ -11,6 +11,7 @@ use think\console\Output; use think\Db; use think\Exception; use think\exception\ErrorException; +use think\exception\PDOException; use think\Lang; use think\Loader; @@ -254,12 +255,14 @@ class Crud extends Command ->addOption('fields', 'i', Option::VALUE_OPTIONAL, 'model visible fields', null) ->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override or force delete,without tips', null) ->addOption('local', 'l', Option::VALUE_OPTIONAL, 'local model', 1) + ->addOption('import', 'a', Option::VALUE_OPTIONAL, 'enable import function', 0) ->addOption('relation', 'r', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation table name without prefix', null) ->addOption('relationmodel', 'e', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation model name', null) ->addOption('relationforeignkey', 'k', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation foreign key', null) ->addOption('relationprimarykey', 'p', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation primary key', null) ->addOption('relationfields', 's', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation table fields', null) - ->addOption('relationmode', 'o', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation table mode,hasone or belongsto', null) + ->addOption('relationmode', 'o', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation table mode,hasone/belongsto/hasmany', null) + ->addOption('relationcontroller', 'w', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation table controller,only work at hasmany mode', 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('setcheckboxsuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate checkbox component with suffix', null) @@ -303,6 +306,8 @@ class Crud extends Command $force = $input->getOption('force'); //是否为本地model,为0时表示为全局model将会把model放在app/common/model中 $local = $input->getOption('local'); + //是否启用导入功能 + $import = $input->getOption('import'); if (!$table) { throw new Exception('table name can\'t empty'); @@ -323,6 +328,8 @@ class Crud extends Command $relationPrimaryKey = $input->getOption('relationprimarykey'); //关联表显示字段 $relationFields = $input->getOption('relationfields'); + //关联表显示字段 + $relationController = $input->getOption('relationcontroller'); //复选框后缀 $setcheckboxsuffix = $input->getOption('setcheckboxsuffix'); //单选框后缀 @@ -482,8 +489,10 @@ class Crud extends Command 'relationFields' => isset($relationFields[$index]) ? explode(',', $relationFields[$index]) : [], //关联模式 'relationMode' => isset($relationMode[$index]) ? $relationMode[$index] : 'belongsto', + //关联模型控制器 + 'relationController' => isset($relationController[$index]) ? $relationController[$index] : '', //关联表外键 - 'relationForeignKey' => isset($relationForeignKey[$index]) ? $relationForeignKey[$index] : Loader::parseName($relationName) . '_id', + 'relationForeignKey' => isset($relationForeignKey[$index]) ? $relationForeignKey[$index] : '', //关联表主键 'relationPrimaryKey' => isset($relationPrimaryKey[$index]) ? $relationPrimaryKey[$index] : '', ]; @@ -506,7 +515,8 @@ class Crud extends Command $baseFileName = Loader::parseName(array_pop($baseNameArr), 0); array_push($baseNameArr, $baseFileName); $controllerBaseName = strtolower(implode(DS, $baseNameArr)); - $controllerUrl = strtolower(implode('/', $baseNameArr)); + //$controllerUrl = strtolower(implode('/', $baseNameArr)); + $controllerUrl = $this->getControllerUrl($moduleName, $baseNameArr); //视图文件 $viewArr = $controllerArr; @@ -630,6 +640,7 @@ class Crud extends Command $editList = []; $javascriptList = []; $langList = []; + $operateButtonList = []; $field = 'id'; $order = 'id'; $priDefined = false; @@ -662,7 +673,7 @@ class Crud extends Command if (!in_array($relationPrimaryKey, $fieldArr)) { throw new Exception('table [' . $modelTableName . '] must be contain field [' . $relationPrimaryKey . ']'); } - } else { + } elseif ($relation['relationMode'] == 'belongsto') { $relationForeignKey = $relation['relationForeignKey'] ? $relation['relationForeignKey'] : Loader::parseName($relation['relationName']) . "_id"; $relationPrimaryKey = $relation['relationPrimaryKey'] ? $relation['relationPrimaryKey'] : $relation['relationPriKey']; if (!in_array($relationForeignKey, $fieldArr)) { @@ -671,6 +682,17 @@ class Crud extends Command if (!in_array($relationPrimaryKey, $relation['relationFieldList'])) { throw new Exception('relation table [' . $relation['relationTableName'] . '] must be contain field [' . $relationPrimaryKey . ']'); } + } elseif ($relation['relationMode'] == 'hasmany') { + $relationForeignKey = $relation['relationForeignKey'] ? $relation['relationForeignKey'] : $table . "_id"; + $relationPrimaryKey = $relation['relationPrimaryKey'] ? $relation['relationPrimaryKey'] : $priKey; + if (!in_array($relationForeignKey, $relation['relationFieldList'])) { + throw new Exception('relation table [' . $relation['relationTableName'] . '] must be contain field [' . $relationForeignKey . ']'); + } + if (!in_array($relationPrimaryKey, $fieldArr)) { + throw new Exception('table [' . $modelTableName . '] must be contain field [' . $relationPrimaryKey . ']'); + } + $relation['relationColumnList'] = []; + $relation['relationFieldList'] = []; } $relation['relationForeignKey'] = $relationForeignKey; $relation['relationPrimaryKey'] = $relationPrimaryKey; @@ -686,8 +708,15 @@ class Crud extends Command $appendAttrList = []; $controllerAssignList = []; $headingHtml = '{:build_heading()}'; + $controllerImport = ''; + $importHtml = ''; $recyclebinHtml = ''; + if ($import) { + $controllerImport = $this->getReplacedStub('mixins/import', []); + $importHtml = ' {:__(\'Import\')}'; + } + //循环所有字段,开始构造视图的HTML和JS信息 foreach ($columnList as $k => $v) { $field = $v['COLUMN_NAME']; @@ -867,7 +896,9 @@ class Crud extends Command $defaultValue = ''; $attrArr['data-rule'] = 'required'; $cssClassArr[] = 'selectpage'; - $selectpageController = str_replace('_', '/', substr($field, 0, strripos($field, '_'))); + $selectpageTable = substr($field, 0, strripos($field, '_')); + $selectpageField = ''; + $selectpageController = str_replace('_', '/', $selectpageTable); $attrArr['data-source'] = $selectpageController . "/index"; //如果是类型表需要特殊处理下 if ($selectpageController == 'category') { @@ -883,10 +914,27 @@ class Crud extends Command if ($this->isMatchSuffix($field, $this->selectpagesSuffix)) { $attrArr['data-multiple'] = 'true'; } - foreach ($this->fieldSelectpageMap as $m => $n) { - if (in_array($field, $n)) { - $attrArr['data-field'] = $m; - break; + + $tableInfo = null; + try { + $tableInfo = \think\Db::name($selectpageTable)->getTableInfo(); + if (isset($tableInfo['fields'])) { + foreach ($tableInfo['fields'] as $m => $n) { + if (in_array($n, ['nickname', 'title', 'name'])) { + $selectpageField = $n; + break; + } + } + } + } catch (\Exception $e) { + + } + if (!$selectpageField) { + foreach ($this->fieldSelectpageMap as $m => $n) { + if (in_array($field, $n)) { + $attrArr['data-field'] = $m; + break; + } } } } @@ -948,6 +996,33 @@ class Crud extends Command //循环关联表,追加语言包和JS列 foreach ($relations as $index => $relation) { + if ($relation['relationMode'] == 'hasmany') { + $relationFieldText = ucfirst(strtolower($relation['relationName'])) . ' List'; + // 语言列表 + if ($relation['relationTableInfo']['Comment']) { + $langList[] = $this->getLangItem($relationFieldText, rtrim($relation['relationTableInfo']['Comment'], "表") . "列表"); + } + + $relationTableName = $relation['relationTableName']; + $relationTableName = stripos($relationTableName, $prefix) === 0 ? substr($relationTableName, strlen($prefix)) : $relationTableName; + + list($realtionControllerNamespace, $realtionControllerName, $realtionControllerFile, $realtionControllerArr) = $this->getControllerData($moduleName, $relation['relationController'], $relationTableName); + $realtionControllerArr = array_map("strtolower", $realtionControllerArr); + if (count($realtionControllerArr) > 1) { + $realtionControllerArr = [implode('.', $realtionControllerArr)]; + } + $realtionControllerArr[] = 'index'; + $realtionControllerArr[] = $relation['relationForeignKey'] . '/{ids}'; + $relationControllerUrl = implode('/', $realtionControllerArr); + + //构造JS列信息 + $operateButtonList[] = "{name: 'addtabs',title: __('{$relationFieldText}'),text: __('{$relationFieldText}'),classname: 'btn btn-xs btn-info btn-dialog',icon: 'fa fa-list',url: '" . $relationControllerUrl . "'}"; + //echo "php think crud -t {$relation['relationTableName']} -c {$relation['relationController']} -m {$relation['relationModel']} -i " . implode(',', $relation['relationFields']); + //不存在关联表控制器的情况下才进行生成 + if (!is_file($realtionControllerFile)) { + exec("php think crud -t {$relation['relationTableName']} -c {$relation['relationController']} -m {$relation['relationModel']} -i " . implode(',', $relation['relationFields'])); + } + } foreach ($relation['relationColumnList'] as $k => $v) { // 不显示的字段直接过滤掉 if ($relation['relationFields'] && !in_array($v['COLUMN_NAME'], $relation['relationFields'])) { @@ -969,7 +1044,7 @@ class Crud extends Command } //JS最后一列加上操作列 - $javascriptList[] = str_repeat(" ", 24) . "{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}"; + $javascriptList[] = str_repeat(" ", 24) . "{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, " . ($operateButtonList ? "buttons: [" . implode(',', $operateButtonList) . "], " : "") . "formatter: Table.api.formatter.operate}"; $addList = implode("\n", array_filter($addList)); $editList = implode("\n", array_filter($editList)); $javascriptList = implode(",\n", array_filter($javascriptList)); @@ -1032,9 +1107,11 @@ class Crud extends Command 'relationSearch' => $relations ? 'true' : 'false', 'relationWithList' => '', 'relationMethodList' => '', + 'controllerImport' => $controllerImport, 'controllerIndex' => '', 'recyclebinJs' => '', 'headingHtml' => $headingHtml, + 'importHtml' => $importHtml, 'recyclebinHtml' => $recyclebinHtml, 'visibleFieldList' => $fields ? "\$row->visible(['" . implode("','", array_filter(in_array($priKey, explode(',', $fields)) ? explode(',', $fields) : explode(',', $priKey . ',' . $fields))) . "']);" : '', 'appendAttrList' => implode(",\n", $appendAttrList), @@ -1047,24 +1124,30 @@ class Crud extends Command //如果使用关联模型 if ($relations) { $relationWithList = $relationMethodList = $relationVisibleFieldList = []; + $relationKeyArr = ['hasone' => 'hasOne', 'belongsto' => 'belongsTo', 'hasmany' => 'hasMany']; foreach ($relations as $index => $relation) { //需要构造关联的方法 $relation['relationMethod'] = strtolower($relation['relationName']); //关联的模式 - $relation['relationMode'] = $relation['relationMode'] == 'hasone' ? 'hasOne' : 'belongsTo'; + $relation['relationMode'] = strtolower($relation['relationMode']); + $relation['relationMode'] = array_key_exists($relation['relationMode'], $relationKeyArr) ? $relationKeyArr[$relation['relationMode']] : ''; //关联字段 $relation['relationPrimaryKey'] = $relation['relationPrimaryKey'] ? $relation['relationPrimaryKey'] : $priKey; + //构造关联模型的方法 + $relationMethodList[] = $this->getReplacedStub('mixins' . DS . 'modelrelationmethod' . ($relation['relationMode'] == 'hasMany' ? '-hasmany' : ''), $relation); + + if ($relation['relationMode'] == 'hasMany') { + continue; + } + //预载入的方法 $relationWithList[] = $relation['relationMethod']; unset($relation['relationColumnList'], $relation['relationFieldList'], $relation['relationTableInfo']); - //构造关联模型的方法 - $relationMethodList[] = $this->getReplacedStub('mixins' . DS . 'modelrelationmethod', $relation); - //如果设置了显示主表字段,则必须显式将关联表字段显示 if ($fields) { $relationVisibleFieldList[] = "\$row->visible(['{$relation['relationMethod']}']);"; @@ -1080,8 +1163,10 @@ class Crud extends Command $data['relationMethodList'] = implode("\n\n", $relationMethodList); $data['relationVisibleFieldList'] = implode("\n\t\t\t\t", $relationVisibleFieldList); - //需要重写index方法 - $data['controllerIndex'] = $this->getReplacedStub('controllerindex', $data); + if ($relationWithList) { + //需要重写index方法 + $data['controllerIndex'] = $this->getReplacedStub('controllerindex', $data); + } } elseif ($fields) { $data = array_merge($data, ['relationWithList' => '', 'relationMethodList' => '', 'relationVisibleFieldList' => '']); //需要重写index方法 @@ -1220,6 +1305,28 @@ EOD; return true; } + /** + * 获取控制器URL + * @param string $moduleName + * @param array $baseNameArr + * @return string + */ + protected function getControllerUrl($moduleName, $baseNameArr) + { + for ($i = 0; $i < count($baseNameArr) - 1; $i++) { + $temp = array_slice($baseNameArr, 0, $i + 1); + $temp[$i] = ucfirst($temp[$i]); + $controllerFile = APP_PATH . $moduleName . DS . 'controller' . DS . implode(DS, $temp) . '.php'; + //检测父级目录同名控制器是否存在,存在则变更URL格式 + if (is_file($controllerFile)) { + $baseNameArr = [implode('.', $baseNameArr)]; + break; + } + } + $controllerUrl = strtolower(implode('/', $baseNameArr)); + return $controllerUrl; + } + /** * 获取控制器相关信息 * @param $module @@ -1269,14 +1376,14 @@ EOD; $arr = []; if (!$name) { $parseName = Loader::parseName($table, 1); - $parseArr = [$table]; - } else { - $name = str_replace(['.', '/', '\\'], '/', $name); - $arr = explode('/', $name); - $parseName = ucfirst(array_pop($arr)); - $parseArr = $arr; - array_push($parseArr, $parseName); + $name = str_replace('_', '/', $table); } + + $name = str_replace(['.', '/', '\\'], '/', $name); + $arr = explode('/', $name); + $parseName = ucfirst(array_pop($arr)); + $parseArr = $arr; + array_push($parseArr, $parseName); //类名不能为内部关键字 if (in_array(strtolower($parseName), $this->internalKeywords)) { throw new Exception('Unable to use internal variable:' . $parseName); diff --git a/application/admin/command/Crud/stubs/controller.stub b/application/admin/command/Crud/stubs/controller.stub index 72a268e0..61a83cfa 100644 --- a/application/admin/command/Crud/stubs/controller.stub +++ b/application/admin/command/Crud/stubs/controller.stub @@ -11,7 +11,7 @@ use app\common\controller\Backend; */ class {%controllerName%} extends Backend { - + /** * {%modelName%}模型对象 * @var \{%modelNamespace%}\{%modelName%} @@ -25,16 +25,13 @@ class {%controllerName%} extends Backend {%controllerAssignList%} } - public function import() - { - parent::import(); - } +{%controllerImport%} /** * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法 * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑 * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改 */ - + {%controllerIndex%} } diff --git a/application/admin/command/Crud/stubs/index.stub b/application/admin/command/Crud/stubs/index.stub index 7a9e491b..7fea21f5 100644 --- a/application/admin/command/Crud/stubs/index.stub +++ b/application/admin/command/Crud/stubs/index.stub @@ -10,7 +10,7 @@ {:__('Add')} {:__('Edit')} {:__('Delete')} - {:__('Import')} + {%importHtml%}
diff --git a/application/admin/command/Crud/stubs/mixins/import.stub b/application/admin/command/Crud/stubs/mixins/import.stub new file mode 100644 index 00000000..f1db48ad --- /dev/null +++ b/application/admin/command/Crud/stubs/mixins/import.stub @@ -0,0 +1,4 @@ + public function import() + { + parent::import(); + } diff --git a/application/admin/command/Crud/stubs/mixins/modelrelationmethod-hasmany.stub b/application/admin/command/Crud/stubs/mixins/modelrelationmethod-hasmany.stub new file mode 100755 index 00000000..f75e56c8 --- /dev/null +++ b/application/admin/command/Crud/stubs/mixins/modelrelationmethod-hasmany.stub @@ -0,0 +1,5 @@ + + public function {%relationMethod%}s() + { + return $this->{%relationMode%}('{%relationClassName%}', '{%relationForeignKey%}', '{%relationPrimaryKey%}'); + } diff --git a/application/admin/common.php b/application/admin/common.php index a6f18429..14fcb5e8 100755 --- a/application/admin/common.php +++ b/application/admin/common.php @@ -194,33 +194,3 @@ if (!function_exists('build_heading')) { return $result; } } - -if (!function_exists('build_suffix_image')) { - /** - * 生成文件后缀图片 - * @param string $suffix 后缀 - * @param null $background - * @return string - */ - function build_suffix_image($suffix, $background = null) - { - $suffix = mb_substr(strtoupper($suffix), 0, 4); - $total = unpack('L', hash('adler32', $suffix, true))[1]; - $hue = $total % 360; - list($r, $g, $b) = hsv2rgb($hue / 360, 0.3, 0.9); - - $background = $background ? $background : "rgb({$r},{$g},{$b})"; - - $icon = << - - - - - - {$suffix} - -EOT; - return $icon; - } -} diff --git a/application/admin/controller/Addon.php b/application/admin/controller/Addon.php index a7e843ad..a6ae0097 100644 --- a/application/admin/controller/Addon.php +++ b/application/admin/controller/Addon.php @@ -25,13 +25,13 @@ class Addon extends Backend public function _initialize() { parent::_initialize(); - if (!$this->auth->isSuperAdmin() && in_array($this->request->action(), ['install', 'uninstall', 'local', 'upgrade'])) { + if (!$this->auth->isSuperAdmin() && in_array($this->request->action(), ['install', 'uninstall', 'local', 'upgrade', 'authorization', 'testdata'])) { $this->error(__('Access is allowed only to the super management group')); } } /** - * 查看 + * 插件列表 */ public function index() { @@ -41,6 +41,18 @@ class Addon extends Backend $v['config'] = $config ? 1 : 0; $v['url'] = str_replace($this->request->server('SCRIPT_NAME'), '', $v['url']); } + if ($this->request->isAjax()) { + $result = []; + debug('begin'); + try { + $result = Service::addons($this->request->get()); + } catch (\Exception $e) { + $this->error($e->getMessage()); + } + debug('end'); + \think\Log::record("tx:" . debug('begin', 'end', 6) . 's'); + return json($result); + } $this->assignconfig(['addons' => $addons, 'api_url' => config('fastadmin.api_url'), 'faversion' => config('fastadmin.version')]); return $this->view->fetch(); } @@ -57,13 +69,10 @@ class Addon extends Backend if (!preg_match("/^[a-zA-Z0-9]+$/", $name)) { $this->error(__('Addon name incorrect')); } - if (!is_dir(ADDON_PATH . $name)) { - $this->error(__('Directory not found')); - } $info = get_addon_info($name); $config = get_addon_fullconfig($name); if (!$info) { - $this->error(__('No Results were found')); + $this->error(__('Addon not exists')); } if ($this->request->isPost()) { $params = $this->request->post("row/a", [], 'trim'); @@ -80,13 +89,19 @@ class Addon extends Backend } } try { - //更新配置文件 - set_addon_fullconfig($name, $config); - Service::refresh(); - $this->success(); + $addon = get_addon_instance($name); + //插件自定义配置实现逻辑 + if (method_exists($addon, 'config')) { + $addon->config($name, $config); + } else { + //更新配置文件 + set_addon_fullconfig($name, $config); + Service::refresh(); + } } catch (Exception $e) { $this->error(__($e->getMessage())); } + $this->success(); } $this->error(__('Parameter %s can not be empty', '')); } @@ -212,6 +227,9 @@ class Addon extends Backend { Config::set('default_return_type', 'json'); + if (!config('app_debug')) { + $this->error(__('Only work at debug mode')); + } $info = []; $file = $this->request->file('file'); try { @@ -275,6 +293,29 @@ class Addon extends Backend $this->success(__('Operate successful'), '', ['addon' => $info]); } + /** + * 测试数据 + */ + public function testdata() + { + $name = $this->request->post("name"); + if (!$name) { + $this->error(__('Parameter %s can not be empty', 'name')); + } + if (!preg_match("/^[a-zA-Z0-9]+$/", $name)) { + $this->error(__('Addon name incorrect')); + } + + try { + Service::importsql($name, 'testdata.sql'); + } catch (AddonException $e) { + $this->result($e->getData(), $e->getCode(), __($e->getMessage())); + } catch (Exception $e) { + $this->error(__($e->getMessage()), $e->getCode()); + } + $this->success(__('Import successful'), ''); + } + /** * 已装插件 */ @@ -285,22 +326,7 @@ class Addon extends Backend $filter = $this->request->get("filter"); $search = $this->request->get("search"); $search = htmlspecialchars(strip_tags($search)); - $onlineaddons = Cache::get("onlineaddons"); - if (!is_array($onlineaddons) && config('fastadmin.api_url')) { - $onlineaddons = []; - $result = Http::sendRequest(config('fastadmin.api_url') . '/addon/index', [], 'GET', [ - CURLOPT_HTTPHEADER => ['Accept-Encoding:gzip'], - CURLOPT_ENCODING => "gzip" - ]); - if ($result['ret']) { - $json = (array)json_decode($result['msg'], true); - $rows = isset($json['rows']) ? $json['rows'] : []; - foreach ($rows as $index => $row) { - $onlineaddons[$row['name']] = $row; - } - } - Cache::set("onlineaddons", $onlineaddons, 600); - } + $onlineaddons = $this->getAddonList(); $filter = (array)json_decode($filter, true); $addons = get_addon_list(); $list = []; @@ -311,6 +337,7 @@ class Addon extends Backend if (isset($onlineaddons[$v['name']])) { $v = array_merge($v, $onlineaddons[$v['name']]); + $v['price'] = '-'; } else { $v['category_id'] = 0; $v['flag'] = ''; @@ -321,9 +348,9 @@ class Addon extends Backend $v['price'] = __('None'); $v['screenshots'] = []; $v['releaselist'] = []; + $v['url'] = addon_url($v['name']); + $v['url'] = str_replace($this->request->server('SCRIPT_NAME'), '', $v['url']); } - $v['url'] = addon_url($v['name']); - $v['url'] = str_replace($this->request->server('SCRIPT_NAME'), '', $v['url']); $v['createtime'] = filemtime(ADDON_PATH . $v['name']); if ($filter && isset($filter['category_id']) && is_numeric($filter['category_id']) && $filter['category_id'] != $v['category_id']) { continue; @@ -340,6 +367,105 @@ class Addon extends Backend return $callback($result); } + /** + * 登录 + */ + public function login() + { + $params = [ + 'account' => $this->request->post('account'), + 'password' => $this->request->post('password'), + 'url' => $this->request->url(true), + 'faversion' => config('fastadmin.version') + ]; + try { + $result = Service::login($params); + } catch (Exception $e) { + $this->error(__($e->getMessage())); + } + return json($result); + } + + /** + * 会员信息 + */ + public function userinfo() + { + $params = [ + 'uid' => $this->request->post('uid'), + 'token' => $this->request->post('token'), + 'url' => $this->request->url(true), + 'faversion' => config('fastadmin.version') + ]; + try { + $result = Service::userinfo($params); + } catch (Exception $e) { + $this->error($e->getMessage()); + } + return json($result); + } + + /** + * 退出 + */ + public function logout() + { + $params = [ + 'uid' => $this->request->post('uid'), + 'token' => $this->request->post('token'), + 'url' => $this->request->url(true), + 'faversion' => config('fastadmin.version') + ]; + try { + $result = Service::logout($params); + } catch (Exception $e) { + $this->error(__($e->getMessage())); + } + return json($result); + } + + /** + * 检测 + */ + public function isbuy() + { + $name = $this->request->post("name"); + $uid = $this->request->post("uid"); + $token = $this->request->post("token"); + $version = $this->request->post("version"); + $faversion = $this->request->post("faversion"); + $extend = [ + 'uid' => $uid, + 'token' => $token, + 'version' => $version, + 'faversion' => $faversion + ]; + try { + $result = Service::isBuy($name, $extend); + } catch (Exception $e) { + $this->error(__($e->getMessage())); + } + return json($result); + } + + /** + * 刷新授权 + */ + public function authorization() + { + $params = [ + 'uid' => $this->request->post('uid'), + 'token' => $this->request->post('token'), + 'faversion' => $this->request->post('faversion'), + ]; + try { + Service::authorization($params); + } catch (Exception $e) { + $this->error(__($e->getMessage())); + } + $this->success(__('Operate successful')); + } + /** * 获取插件相关表 */ @@ -360,4 +486,31 @@ class Addon extends Backend $tables = array_values($tables); $this->success('', null, ['tables' => $tables]); } + + protected function getAddonList() + { + $onlineaddons = Cache::get("onlineaddons"); + if (!is_array($onlineaddons) && config('fastadmin.api_url')) { + $onlineaddons = []; + $params = [ + 'uid' => $this->request->post('uid'), + 'token' => $this->request->post('token'), + 'version' => config('fastadmin.version'), + 'faversion' => config('fastadmin.version'), + ]; + $json = []; + try { + $json = Service::addons($params); + } catch (\Exception $e) { + + } + $rows = isset($json['rows']) ? $json['rows'] : []; + foreach ($rows as $index => $row) { + $onlineaddons[$row['name']] = $row; + } + Cache::set("onlineaddons", $onlineaddons, 600); + } + return $onlineaddons; + } + } diff --git a/application/admin/controller/Ajax.php b/application/admin/controller/Ajax.php index bd0b5d00..f256906a 100644 --- a/application/admin/controller/Ajax.php +++ b/application/admin/controller/Ajax.php @@ -11,6 +11,7 @@ use think\Cache; use think\Config; use think\Db; use think\Lang; +use think\Response; use think\Validate; /** @@ -37,17 +38,19 @@ class Ajax extends Backend */ public function lang() { - header('Content-Type: application/javascript'); - header("Cache-Control: public"); - header("Pragma: cache"); - $offset = 30 * 60 * 60 * 24; // 缓存一个月 - header("Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT"); + $header = ['Content-Type' => 'application/javascript']; + if (!config('app_debug')) { + $offset = 30 * 60 * 60 * 24; // 缓存一个月 + $header['Cache-Control'] = 'public'; + $header['Pragma'] = 'cache'; + $header['Expires'] = gmdate("D, d M Y H:i:s", time() + $offset) . " GMT"; + } $controllername = input("controllername"); //默认只加载了控制器对应的语言名,你还根据控制器名来加载额外的语言包 $this->loadlang($controllername); - return jsonp(Lang::get(), 200, [], ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]); + return jsonp(Lang::get(), 200, $header, ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]); } /** @@ -296,10 +299,15 @@ class Ajax extends Backend public function icon() { $suffix = $this->request->request("suffix"); - header('Content-type: image/svg+xml'); $suffix = $suffix ? $suffix : "FILE"; - echo build_suffix_image($suffix); - exit; + $data = build_suffix_image($suffix); + $header = ['Content-Type' => 'image/svg+xml']; + $offset = 30 * 60 * 60 * 24; // 缓存一个月 + $header['Cache-Control'] = 'public'; + $header['Pragma'] = 'cache'; + $header['Expires'] = gmdate("D, d M Y H:i:s", time() + $offset) . " GMT"; + $response = Response::create($data, '', 200, $header); + return $response; } } diff --git a/application/admin/controller/Index.php b/application/admin/controller/Index.php index c24134a7..df8d3466 100644 --- a/application/admin/controller/Index.php +++ b/application/admin/controller/Index.php @@ -6,6 +6,7 @@ use app\admin\model\AdminLog; use app\common\controller\Backend; use think\Config; use think\Hook; +use think\Session; use think\Validate; /** @@ -31,6 +32,13 @@ class Index extends Backend */ public function index() { + $cookieArr = ['adminskin' => "/^skin\-([a-z\-]+)\$/i", 'multiplenav' => "/^(0|1)\$/", 'multipletab' => "/^(0|1)\$/"]; + foreach ($cookieArr as $key => $regex) { + $cookieValue = $this->request->cookie($key); + if (!is_null($cookieValue) && preg_match($regex, $cookieValue)) { + config('fastadmin.' . $key, $cookieValue); + } + } //左侧菜单 list($menulist, $navlist, $fixedmenu, $referermenu) = $this->auth->getSidebar([ 'dashboard' => 'hot', @@ -44,6 +52,7 @@ class Index extends Backend $this->success('', null, ['menulist' => $menulist, 'navlist' => $navlist]); } } + $this->assignconfig('cookie', ['prefix' => config('cookie.prefix')]); $this->view->assign('menulist', $menulist); $this->view->assign('navlist', $navlist); $this->view->assign('fixedmenu', $fixedmenu); @@ -99,6 +108,7 @@ class Index extends Backend // 根据客户端的cookie,判断是否可以自动登录 if ($this->auth->autologin()) { + Session::delete("referer"); $this->redirect($url); } $background = Config::get('fastadmin.login_background'); diff --git a/application/admin/controller/auth/Rule.php b/application/admin/controller/auth/Rule.php index 9ca60c02..8ae23cb4 100644 --- a/application/admin/controller/auth/Rule.php +++ b/application/admin/controller/auth/Rule.php @@ -118,7 +118,7 @@ class Rule extends Backend //这里需要针对name做唯一验证 $ruleValidate = \think\Loader::validate('AuthRule'); $ruleValidate->rule([ - 'name' => 'require|format|unique:AuthRule,name,' . $row->id, + 'name' => 'require|unique:AuthRule,name,' . $row->id, ]); $result = $row->validate()->save($params); if ($result === false) { diff --git a/application/admin/controller/general/Config.php b/application/admin/controller/general/Config.php index bab69e84..a77125c0 100644 --- a/application/admin/controller/general/Config.php +++ b/application/admin/controller/general/Config.php @@ -88,6 +88,9 @@ class Config extends Backend */ public function add() { + if (!config('app_debug')) { + $this->error(__('Only work at development environment')); + } if ($this->request->isPost()) { $this->token(); $params = $this->request->post("row/a", [], 'trim'); @@ -166,6 +169,9 @@ class Config extends Backend */ public function del($ids = "") { + if (!config('app_debug')) { + $this->error(__('Only work at development environment')); + } $name = $this->request->post('name'); $config = ConfigModel::getByName($name); if ($name && $config) { diff --git a/application/admin/lang/zh-cn.php b/application/admin/lang/zh-cn.php index 337a38a5..5f2df6fd 100755 --- a/application/admin/lang/zh-cn.php +++ b/application/admin/lang/zh-cn.php @@ -201,13 +201,13 @@ return [ 'Third group 2' => '三级管理组2', 'Dashboard tips' => '用于展示当前系统中的统计数据、统计报表及重要实时数据', 'Config tips' => '可以在此增改系统的变量和分组,也可以自定义分组和变量', - 'Category tips' => '用于管理网站的所有分类,分类可进行无限级分类,分类类型请在常规管理->系统配置->字典配置中添加', + 'Category tips' => '分类类型请在常规管理->系统配置->字典配置中添加', 'Attachment tips' => '主要用于管理上传到服务器或第三方存储的数据', 'Addon tips' => '可在线安装、卸载、禁用、启用、配置、升级插件,插件升级前请做好备份。', 'Admin tips' => '一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成', 'Admin log tips' => '管理员可以查看自己所拥有的权限的管理员日志', 'Group tips' => '角色组可以有多个,角色有上下级层级关系,如果子角色有角色组和管理员的权限则可以派生属于自己组别的下级角色组或管理员', - 'Rule tips' => '规则通常对应一个控制器的方法,同时左侧的菜单栏数据也从规则中体现,通常建议通过命令行进行生成规则节点', + 'Rule tips' => '菜单规则通常对应一个控制器的方法,同时菜单栏数据也从规则中获取', 'Access is allowed only to the super management group' => '仅超级管理组能访问', 'Local addon' => '本地插件', // 前台菜单 diff --git a/application/admin/lang/zh-cn/addon.php b/application/admin/lang/zh-cn/addon.php index 3428aa1b..6c999d2a 100755 --- a/application/admin/lang/zh-cn/addon.php +++ b/application/admin/lang/zh-cn/addon.php @@ -10,26 +10,31 @@ return [ 'Donate' => '打赏作者', 'Warmtips' => '温馨提示', 'Pay now' => '立即支付', - 'Offline install' => '离线安装', + 'Local install' => '本地安装', 'Refresh addon cache' => '刷新插件缓存', 'Userinfo' => '会员信息', + 'Reload authorization' => '刷新授权', 'Online store' => '在线商店', 'Local addon' => '本地插件', 'Conflict tips' => '此插件中发现和现有系统中部分文件发现冲突!以下文件将会被影响,请备份好相关文件后再继续操作', 'Login tips' => '此处登录账号为FastAdmin官网账号', 'Logined tips' => '你好!%s
当前你已经登录,将同步保存你的购买记录', - 'Pay tips' => '扫码支付后如果仍然无法立即下载,请不要重复支付,请稍后再重试安装!', + 'Pay tips' => '扫码支付后如果仍然无法安装,请不要重复支付,请稍后再重试安装!', + 'Pay successful tips' => '购买成功!请点击继续安装按钮完成安装!', 'Pay click tips' => '请点击这里在新窗口中进行支付!', 'Pay new window tips' => '请在新弹出的窗口中进行支付,支付完成后再重新点击安装按钮进行安装!', 'Upgrade tips' => '确认升级《%s》

1、请务必做好代码和数据库备份!备份!备份!
2、升级后如出现冗余数据,请根据需要移除即可!
3、不建议在生产环境升级,请在本地完成升级测试

如有重要数据请备份后再操作!', 'Offline installed tips' => '安装成功!清除浏览器缓存和框架缓存后生效!', 'Online installed tips' => '安装成功!清除浏览器缓存和框架缓存后生效!', - 'Not login tips' => '你当前未登录FastAdmin,登录后将同步已购买的记录,下载时无需二次付费!', + 'Not login tips' => '你当前未登录FastAdmin,请登录后操作!', 'Please login and try to install' => '请登录FastAdmin后再进行离线安装!', 'Not installed tips' => '请安装后再访问插件前台页面!', 'Not enabled tips' => '插件已经禁用,请启用后再访问插件前台页面!', 'New version tips' => '发现新版本:%s 点击查看更新日志', - 'Store now available tips' => '插件市场暂不可用,是否切换到本地插件?', + 'Testdata tips' => '你还可以继续导入测试数据!', + 'Import testdata' => '导入测试数据', + 'Skip testdata' => '暂不导入', + 'Store not available tips' => '插件市场暂不可用,是否切换到本地插件?', 'Switch to the local' => '切换到本地插件', 'try to reload' => '重新尝试加载', 'Please disable the add before trying to upgrade' => '请先禁用插件再进行升级', @@ -41,6 +46,7 @@ return [ 'View addon screenshots' => '点击查看插件截图', 'Click to toggle status' => '点击切换插件状态', 'Click to contact developer' => '点击与插件开发者取得联系', + 'Continue installation' => '继续安装', 'My addons' => '我购买的插件', 'Index' => '前台', 'All' => '全部', @@ -84,13 +90,18 @@ return [ 'Install successful' => '安装成功', 'Uninstall successful' => '卸载成功', 'Operate successful' => '操作成功', + 'Import successful' => '导入测试数据成功!清除浏览器缓存和框架缓存后生效!', + 'Initialize successful' => '初始化成功', + 'Initialize template not found' => '初始化模板未找到', 'Addon name incorrect' => '插件名称不正确', 'Addon info file was not found' => '插件配置文件未找到', 'Addon info file data incorrect' => '插件配置信息不正确', 'Addon already exists' => '插件已经存在', + 'Addon not exists' => '插件不存在', 'Addon package download failed' => '插件下载失败', 'Conflicting file found' => '发现冲突文件', 'Invalid addon package' => '未验证的插件', + 'No initialize method' => '未找到初始化方法', 'No permission to write temporary files' => '没有权限写入临时文件', 'The addon file does not exist' => '插件主启动程序不存在', 'The configuration file content is incorrect' => '配置文件不完整', @@ -98,6 +109,7 @@ return [ 'Unable to extract the file' => '无法解压ZIP文件', 'Unable to open file \'%s\' for writing' => '文件(%s)没有写入权限', 'Are you sure you want to unstall %s?' => '确认卸载《%s》?', + 'Are you sure you want to refresh authorization?' => '确认刷新应用插件授权?', 'Delete all the addon file and cannot be recovered!' => '卸载将会删除所有插件文件且不可找回!!!', 'Delete all the addon database and cannot be recovered!' => '删除所有插件相关数据表且不可找回!!!', 'Please backup important data manually before uninstall!' => '如有重要数据请备份后再操作!!!', diff --git a/application/admin/lang/zh-cn/general/config.php b/application/admin/lang/zh-cn/general/config.php index b21ef4e4..6939a667 100644 --- a/application/admin/lang/zh-cn/general/config.php +++ b/application/admin/lang/zh-cn/general/config.php @@ -1,81 +1,82 @@ '变量名', - 'Tip' => '提示信息', - 'Group' => '分组', - 'Type' => '类型', - 'Title' => '变量标题', - 'Value' => '变量值', - 'Basic' => '基础配置', - 'Email' => '邮件配置', - 'Attachment' => '附件配置', - 'Dictionary' => '字典配置', - 'User' => '会员配置', - 'Example' => '示例分组', - 'Extend' => '扩展属性', - 'String' => '字符', - 'Password' => '密码', - 'Text' => '文本', - 'Editor' => '编辑器', - 'Number' => '数字', - 'Date' => '日期', - 'Time' => '时间', - 'Datetime' => '日期时间', - 'Datetimerange' => '日期时间区间', - 'Image' => '图片', - 'Images' => '图片(多)', - 'File' => '文件', - 'Files' => '文件(多)', - 'Select' => '列表', - 'Selects' => '列表(多选)', - 'Switch' => '开关', - 'Checkbox' => '复选', - 'Radio' => '单选', - 'Array' => '数组', - 'Array key' => '键名', - 'Array value' => '键值', - 'City' => '城市地区', - 'Selectpage' => '关联表', - 'Selectpages' => '关联表(多选)', - 'Custom' => '自定义', - 'Please select table' => '关联表', - 'Selectpage table' => '关联表', - 'Selectpage primarykey' => '存储字段', - 'Selectpage field' => '显示字段', - 'Selectpage conditions' => '筛选条件', - 'Field title' => '字段名', - 'Field value' => '字段值', - 'Content' => '数据列表', - 'Rule' => '校验规则', - 'Site name' => '站点名称', - 'Beian' => '备案号', - 'Cdn url' => 'CDN地址', - 'Version' => '版本号', - 'Timezone' => '时区', - 'Forbidden ip' => '禁止IP', - 'Languages' => '语言', - 'Fixed page' => '后台固定页', - 'Category type' => '分类类型', - 'Config group' => '配置分组', - 'Attachment category' => '附件类别', - 'Category1' => '分类一', - 'Category2' => '分类二', - 'Rule tips' => '校验规则使用请参考Nice-validator文档', - 'Extend tips' => '扩展属性支持{id}、{name}、{group}、{title}、{value}、{content}、{rule}替换', - 'Mail type' => '邮件发送方式', - 'Mail smtp host' => 'SMTP服务器', - 'Mail smtp port' => 'SMTP端口', - 'Mail smtp user' => 'SMTP用户名', - 'Mail smtp password' => 'SMTP密码', - 'Mail vertify type' => 'SMTP验证方式', - 'Mail from' => '发件人邮箱', - 'Site name incorrect' => '网站名称错误', - 'Name already exist' => '变量名称已经存在', - 'Add new config' => '点击添加新的配置', - 'Send a test message' => '发送测试邮件', - 'This is a test mail content' => '这是一封来自%s的校验邮件,用于校验邮件配置是否正常!', - 'This is a test mail' => '这是一封来自%s的邮件', - 'Please input your email' => '请输入测试接收者邮箱', - 'Please input correct email' => '请输入正确的邮箱地址', + 'Name' => '变量名', + 'Tip' => '提示信息', + 'Group' => '分组', + 'Type' => '类型', + 'Title' => '变量标题', + 'Value' => '变量值', + 'Basic' => '基础配置', + 'Email' => '邮件配置', + 'Attachment' => '附件配置', + 'Dictionary' => '字典配置', + 'User' => '会员配置', + 'Example' => '示例分组', + 'Extend' => '扩展属性', + 'String' => '字符', + 'Password' => '密码', + 'Text' => '文本', + 'Editor' => '编辑器', + 'Number' => '数字', + 'Date' => '日期', + 'Time' => '时间', + 'Datetime' => '日期时间', + 'Datetimerange' => '日期时间区间', + 'Image' => '图片', + 'Images' => '图片(多)', + 'File' => '文件', + 'Files' => '文件(多)', + 'Select' => '列表', + 'Selects' => '列表(多选)', + 'Switch' => '开关', + 'Checkbox' => '复选', + 'Radio' => '单选', + 'Array' => '数组', + 'Array key' => '键名', + 'Array value' => '键值', + 'City' => '城市地区', + 'Selectpage' => '关联表', + 'Selectpages' => '关联表(多选)', + 'Custom' => '自定义', + 'Please select table' => '关联表', + 'Selectpage table' => '关联表', + 'Selectpage primarykey' => '存储字段', + 'Selectpage field' => '显示字段', + 'Selectpage conditions' => '筛选条件', + 'Field title' => '字段名', + 'Field value' => '字段值', + 'Content' => '数据列表', + 'Rule' => '校验规则', + 'Site name' => '站点名称', + 'Beian' => '备案号', + 'Cdn url' => 'CDN地址', + 'Version' => '版本号', + 'Timezone' => '时区', + 'Forbidden ip' => '禁止IP', + 'Languages' => '语言', + 'Fixed page' => '后台固定页', + 'Category type' => '分类类型', + 'Config group' => '配置分组', + 'Attachment category' => '附件类别', + 'Category1' => '分类一', + 'Category2' => '分类二', + 'Rule tips' => '校验规则使用请参考Nice-validator文档', + 'Extend tips' => '扩展属性支持{id}、{name}、{group}、{title}、{value}、{content}、{rule}替换', + 'Mail type' => '邮件发送方式', + 'Mail smtp host' => 'SMTP服务器', + 'Mail smtp port' => 'SMTP端口', + 'Mail smtp user' => 'SMTP用户名', + 'Mail smtp password' => 'SMTP密码', + 'Mail vertify type' => 'SMTP验证方式', + 'Mail from' => '发件人邮箱', + 'Site name incorrect' => '网站名称错误', + 'Name already exist' => '变量名称已经存在', + 'Add new config' => '点击添加新的配置', + 'Send a test message' => '发送测试邮件', + 'Only work at development environment' => '只允许在开发环境开操作', + 'This is a test mail content' => '这是一封来自%s的校验邮件,用于校验邮件配置是否正常!', + 'This is a test mail' => '这是一封来自%s的邮件', + 'Please input your email' => '请输入测试接收者邮箱', + 'Please input correct email' => '请输入正确的邮箱地址', ]; diff --git a/application/admin/lang/zh-cn/index.php b/application/admin/lang/zh-cn/index.php index 21146677..316de2aa 100644 --- a/application/admin/lang/zh-cn/index.php +++ b/application/admin/lang/zh-cn/index.php @@ -8,14 +8,18 @@ return [ 'You can\'t use fixed and boxed layouts together' => '盒子模型和固定布局不能同时启作用', 'Boxed Layout' => '盒子布局', 'Activate the boxed layout' => '盒子布局最大宽度将被限定为1250px', - 'Toggle Sidebar' => '切换菜单栏', - 'Toggle the left sidebar\'s state (open or collapse)' => '切换菜单栏的展示或收起', + 'Toggle Sidebar' => '收起菜单栏', + 'Toggle the left sidebar\'s state (open or collapse)' => '切换菜单栏的展开或收起', 'Sidebar Expand on Hover' => '菜单栏自动展开', 'Let the sidebar mini expand on hover' => '鼠标移到菜单栏自动展开', 'Toggle Right Sidebar Slide' => '切换右侧操作栏', 'Toggle between slide over content and push content effects' => '切换右侧操作栏覆盖或独占', 'Toggle Right Sidebar Skin' => '切换右侧操作栏背景', 'Toggle between dark and light skins for the right sidebar' => '将右侧操作栏背景亮色或深色切换', + 'Multiple nav' => '多级菜单导航', + 'Toggle the top menu state (multiple or single)' => '切换顶部菜单为多级菜单导航模式', + 'Multiple tab' => '多选项卡', + 'Always show multiple tab when multiple nav is set' => '当配置为多级菜单导航时是否启用多选项卡', 'Show sub menu' => '显示菜单栏子菜单', 'Always show sub menu' => '菜单栏子菜单将始终显示', 'Disable top menu badge' => '禁用顶部彩色小角标', diff --git a/application/admin/validate/AuthRule.php b/application/admin/validate/AuthRule.php index a1cb9e77..3919ea0c 100644 --- a/application/admin/validate/AuthRule.php +++ b/application/admin/validate/AuthRule.php @@ -16,7 +16,7 @@ class AuthRule extends Validate * 验证规则 */ protected $rule = [ - 'name' => 'require|format|unique:AuthRule', + 'name' => 'require|unique:AuthRule', 'title' => 'require', ]; diff --git a/application/admin/view/addon/config.html b/application/admin/view/addon/config.html index 2ea47f39..70a1c1ca 100644 --- a/application/admin/view/addon/config.html +++ b/application/admin/view/addon/config.html @@ -111,7 +111,7 @@ diff --git a/application/admin/view/addon/index.html b/application/admin/view/addon/index.html index 770fdc2a..3ec2ff78 100644 --- a/application/admin/view/addon/index.html +++ b/application/admin/view/addon/index.html @@ -61,6 +61,7 @@ .btn-toggle { padding: 0; } +
@@ -80,9 +81,11 @@
{if $Think.config.fastadmin.api_url} + {if $Think.config.app_debug} + {/if} {:__('Userinfo')} + {:__('Reload authorization')} {/if}
@@ -190,29 +194,17 @@ {:__('Warning')}
{:__('Logined tips', '<%=username%>')} - + - diff --git a/application/admin/view/auth/admin/add.html b/application/admin/view/auth/admin/add.html index 6f984d28..35913cbf 100644 --- a/application/admin/view/auth/admin/add.html +++ b/application/admin/view/auth/admin/add.html @@ -39,8 +39,8 @@ - \ No newline at end of file + diff --git a/application/admin/view/auth/admin/edit.html b/application/admin/view/auth/admin/edit.html index 64131d3e..cf9b1879 100644 --- a/application/admin/view/auth/admin/edit.html +++ b/application/admin/view/auth/admin/edit.html @@ -45,8 +45,8 @@ - \ No newline at end of file + diff --git a/application/admin/view/auth/group/add.html b/application/admin/view/auth/group/add.html index 0eb848b5..a7c566f7 100644 --- a/application/admin/view/auth/group/add.html +++ b/application/admin/view/auth/group/add.html @@ -31,7 +31,7 @@ diff --git a/application/admin/view/auth/group/edit.html b/application/admin/view/auth/group/edit.html index c691bd16..d183ff5e 100644 --- a/application/admin/view/auth/group/edit.html +++ b/application/admin/view/auth/group/edit.html @@ -31,7 +31,7 @@ diff --git a/application/admin/view/auth/rule/add.html b/application/admin/view/auth/rule/add.html index b5a5c790..33fd4598 100644 --- a/application/admin/view/auth/rule/add.html +++ b/application/admin/view/auth/rule/add.html @@ -34,17 +34,12 @@ -
- -
- -
-
@@ -69,6 +64,12 @@
+
+ +
+ +
+
@@ -78,7 +79,7 @@ diff --git a/application/admin/view/auth/rule/edit.html b/application/admin/view/auth/rule/edit.html index 64ecd723..658a408b 100644 --- a/application/admin/view/auth/rule/edit.html +++ b/application/admin/view/auth/rule/edit.html @@ -34,17 +34,12 @@
-
- -
- -
-
@@ -66,7 +61,13 @@
- + +
+
+
+ +
+
@@ -78,7 +79,7 @@ diff --git a/application/admin/view/category/add.html b/application/admin/view/category/add.html index 5ca1ae07..e92f56c7 100644 --- a/application/admin/view/category/add.html +++ b/application/admin/view/category/add.html @@ -93,7 +93,7 @@ diff --git a/application/admin/view/category/edit.html b/application/admin/view/category/edit.html index 7a554f36..4beea83d 100644 --- a/application/admin/view/category/edit.html +++ b/application/admin/view/category/edit.html @@ -89,7 +89,7 @@ diff --git a/application/admin/view/common/control.html b/application/admin/view/common/control.html index 77efe7c0..27f66a6e 100644 --- a/application/admin/view/common/control.html +++ b/application/admin/view/common/control.html @@ -9,6 +9,13 @@ display: block; float:left; } + .skin-list li.active a { + opacity: 1; + filter: alpha(opacity=100); + } + .skin-list li.active p { + color: #fff; + }
@@ -264,7 +265,7 @@
{:__('Seven dau')}
-
+
@@ -274,7 +275,7 @@
{:__('Thirty dau')}
-
+
@@ -308,7 +309,7 @@
-
+
{:__('Real time')} diff --git a/application/admin/view/general/attachment/add.html b/application/admin/view/general/attachment/add.html index d5248172..6c632730 100644 --- a/application/admin/view/general/attachment/add.html +++ b/application/admin/view/general/attachment/add.html @@ -3,16 +3,25 @@
- + +
    - +
    + +
    + {if $config.upload.chunking} - + {/if}
    @@ -21,27 +30,29 @@
    - + +
      - +
      + +
      + {if $config.upload.chunking} - + {/if}
      - -
      - -
      - -
      -
      + {if $Think.config.app_debug} + {/if} @@ -174,8 +179,10 @@ + {if $Think.config.app_debug} - + + {/if} {/foreach} @@ -183,11 +190,15 @@ + {if $Think.config.app_debug} + {/if}
      {:__('Title')} {:__('Value')}{:__('Name')}
      {php}echo "{\$site.". $item['name'] . "}";{/php}{if $item['id']>17}{/if}{if $item['id']>18}{/if}
      - - +
      @@ -321,8 +332,12 @@ value2|title2
      - + {if !$Think.config.app_debug} + + {else/} + + {/if}
      diff --git a/application/admin/view/index/index.html b/application/admin/view/index/index.html index 48d7fbdd..8abaa048 100644 --- a/application/admin/view/index/index.html +++ b/application/admin/view/index/index.html @@ -4,7 +4,7 @@ {include file="common/meta" /} - +
      diff --git a/application/admin/view/user/group/add.html b/application/admin/view/user/group/add.html index 3ad5f08d..b60e0f77 100644 --- a/application/admin/view/user/group/add.html +++ b/application/admin/view/user/group/add.html @@ -31,7 +31,7 @@ diff --git a/application/admin/view/user/group/edit.html b/application/admin/view/user/group/edit.html index 12e1e30a..075ce123 100644 --- a/application/admin/view/user/group/edit.html +++ b/application/admin/view/user/group/edit.html @@ -31,7 +31,7 @@ diff --git a/application/admin/view/user/rule/add.html b/application/admin/view/user/rule/add.html index b9dfaa27..63b29d15 100644 --- a/application/admin/view/user/rule/add.html +++ b/application/admin/view/user/rule/add.html @@ -46,7 +46,7 @@ diff --git a/application/admin/view/user/rule/edit.html b/application/admin/view/user/rule/edit.html index fade3bb2..7b1978ec 100644 --- a/application/admin/view/user/rule/edit.html +++ b/application/admin/view/user/rule/edit.html @@ -45,7 +45,7 @@ diff --git a/application/admin/view/user/user/edit.html b/application/admin/view/user/user/edit.html index 77da6045..5ca407d6 100644 --- a/application/admin/view/user/user/edit.html +++ b/application/admin/view/user/user/edit.html @@ -144,7 +144,7 @@ diff --git a/application/common.php b/application/common.php index 2d4eb4d0..b331b135 100755 --- a/application/common.php +++ b/application/common.php @@ -258,7 +258,8 @@ if (!function_exists('addtion')) { if (isset($v[$n])) { $curr = array_flip(explode(',', $v[$n])); - $v[$fieldsArr[$n]['display']] = implode(',', array_intersect_key($result[$n], $curr)); + $linedata = array_intersect_key($result[$n], $curr); + $v[$fieldsArr[$n]['display']] = $fieldsArr[$n]['column'] == '*' ? $linedata : implode(',', $linedata); } } } @@ -481,3 +482,33 @@ if (!function_exists('check_ip_allowed')) { } } } + +if (!function_exists('build_suffix_image')) { + /** + * 生成文件后缀图片 + * @param string $suffix 后缀 + * @param null $background + * @return string + */ + function build_suffix_image($suffix, $background = null) + { + $suffix = mb_substr(strtoupper($suffix), 0, 4); + $total = unpack('L', hash('adler32', $suffix, true))[1]; + $hue = $total % 360; + list($r, $g, $b) = hsv2rgb($hue / 360, 0.3, 0.9); + + $background = $background ? $background : "rgb({$r},{$g},{$b})"; + + $icon = << + + + + + + {$suffix} + +EOT; + return $icon; + } +} diff --git a/application/common/library/Auth.php b/application/common/library/Auth.php index 91a7e507..38a19a06 100644 --- a/application/common/library/Auth.php +++ b/application/common/library/Auth.php @@ -227,9 +227,7 @@ class Auth } //直接登录会员 - $this->direct($user->id); - - return true; + return $this->direct($user->id); } /** @@ -558,7 +556,7 @@ class Auth /** * 设置错误信息 * - * @param $error 错误信息 + * @param string $error 错误信息 * @return Auth */ public function setError($error) diff --git a/application/common/library/Email.php b/application/common/library/Email.php index 4ddb0b65..f51b0689 100644 --- a/application/common/library/Email.php +++ b/application/common/library/Email.php @@ -18,7 +18,7 @@ class Email /** * phpmailer对象 */ - protected $mail = []; + protected $mail = null; /** * 错误内容 @@ -96,7 +96,7 @@ class Email /** * 设置收件人 - * @param mixed $email 收件人,多个收件人以,进行分隔 + * @param mixed $email 收件人,多个收件人以,进行分隔 * @return $this */ public function to($email) @@ -122,7 +122,7 @@ class Email $emailArr[key($emailArr)] = $name; } foreach ($emailArr as $address => $name) { - $this->mail->addCC($address, $name); + $this->mail->addCC($name, $address); } return $this; } diff --git a/application/common/library/Token.php b/application/common/library/Token.php index f9e231a0..3486c46a 100644 --- a/application/common/library/Token.php +++ b/application/common/library/Token.php @@ -25,8 +25,8 @@ class Token /** * 连接Token驱动 * @access public - * @param array $options 配置数组 - * @param bool|string $name Token连接标识 true 强制重新连接 + * @param array $options 配置数组 + * @param bool|string $name Token连接标识 true 强制重新连接 * @return Driver */ public static function connect(array $options = [], $name = false) @@ -58,7 +58,7 @@ class Token /** * 自动初始化Token * @access public - * @param array $options 配置数组 + * @param array $options 配置数组 * @return Driver */ public static function init(array $options = []) @@ -81,7 +81,8 @@ class Token /** * 判断Token是否可用(check别名) * @access public - * @param string $token Token标识 + * @param string $token Token标识 + * @param int $user_id 会员ID * @return bool */ public static function has($token, $user_id) @@ -91,7 +92,8 @@ class Token /** * 判断Token是否可用 - * @param string $token Token标识 + * @param string $token Token标识 + * @param int $user_id 会员ID * @return bool */ public static function check($token, $user_id) @@ -102,8 +104,8 @@ class Token /** * 读取Token * @access public - * @param string $token Token标识 - * @param mixed $default 默认值 + * @param string $token Token标识 + * @param mixed $default 默认值 * @return mixed */ public static function get($token, $default = false) @@ -114,9 +116,9 @@ class Token /** * 写入Token * @access public - * @param string $token Token标识 - * @param mixed $user_id 存储数据 - * @param int|null $expire 有效时间 0为永久 + * @param string $token Token标识 + * @param mixed $user_id 会员ID + * @param int|null $expire 有效时间 0为永久 * @return boolean */ public static function set($token, $user_id, $expire = null) @@ -127,7 +129,7 @@ class Token /** * 删除Token(delete别名) * @access public - * @param string $token Token标识 + * @param string $token Token标识 * @return boolean */ public static function rm($token) @@ -148,7 +150,7 @@ class Token /** * 清除Token * @access public - * @param int user_id 用户编号 + * @param int user_id 会员ID * @return boolean */ public static function clear($user_id = null) diff --git a/application/common/library/Upload.php b/application/common/library/Upload.php index 0a31f69a..9769a651 100644 --- a/application/common/library/Upload.php +++ b/application/common/library/Upload.php @@ -16,18 +16,6 @@ use think\Hook; class Upload { - /** - * 验证码有效时长 - * @var int - */ - protected static $expire = 120; - - /** - * 最大允许检测的次数 - * @var int - */ - protected static $maxCheckNums = 10; - protected $merging = false; protected $chunkDir = null; @@ -37,7 +25,7 @@ class Upload protected $error = ''; /** - * @var \think\File + * @var File */ protected $file = null; protected $fileInfo = null; @@ -51,16 +39,29 @@ class Upload } } + /** + * 设置分片目录 + * @param $dir + */ public function setChunkDir($dir) { $this->chunkDir = $dir; } + /** + * 获取文件 + * @return File + */ public function getFile() { return $this->file; } + /** + * 设置文件 + * @param $file + * @throws UploadException + */ public function setFile($file) { if (empty($file)) { @@ -79,6 +80,11 @@ class Upload $this->checkExecutable(); } + /** + * 检测是否为可执行脚本 + * @return bool + * @throws UploadException + */ protected function checkExecutable() { //禁止上传PHP和HTML文件 @@ -88,6 +94,11 @@ class Upload return true; } + /** + * 检测文件类型 + * @return bool + * @throws UploadException + */ protected function checkMimetype() { $mimetypeArr = explode(',', strtolower($this->config['mimetype'])); @@ -105,6 +116,12 @@ class Upload throw new UploadException(__('Uploaded file format is limited')); } + /** + * 检测是否图片 + * @param bool $force + * @return bool + * @throws UploadException + */ protected function checkImage($force = false) { //验证是否为图片文件 @@ -121,6 +138,10 @@ class Upload } } + /** + * 检测文件大小 + * @throws UploadException + */ protected function checkSize() { preg_match('/([0-9\.]+)(\w+)/', $this->config['maxsize'], $matches); @@ -135,11 +156,22 @@ class Upload } } + /** + * 获取后缀 + * @return string + */ public function getSuffix() { return $this->fileInfo['suffix'] ?: 'file'; } + /** + * 获取存储的文件名 + * @param string $savekey + * @param string $filename + * @param string $md5 + * @return mixed|null + */ public function getSavekey($savekey = null, $filename = null, $md5 = null) { if ($filename) { @@ -384,11 +416,19 @@ class Upload return $attachment; } + /** + * 设置错误信息 + * @param $msg + */ public function setError($msg) { $this->error = $msg; } + /** + * 获取错误信息 + * @return string + */ public function getError() { return $this->error; diff --git a/application/common/model/Attachment.php b/application/common/model/Attachment.php index 4c047819..67f71787 100644 --- a/application/common/model/Attachment.php +++ b/application/common/model/Attachment.php @@ -65,6 +65,10 @@ class Attachment extends Model return ''; } + /** + * 获取Mimetype列表 + * @return array + */ public static function getMimetypeList() { $data = [ diff --git a/application/common/model/Config.php b/application/common/model/Config.php index 195506bf..aa7ee0be 100644 --- a/application/common/model/Config.php +++ b/application/common/model/Config.php @@ -175,19 +175,23 @@ class Config extends Model if (!preg_match("/^((?:[a-z]+:)?\/\/)(.*)/i", $uploadurl) && substr($uploadurl, 0, 1) !== '/') { $uploadurl = url($uploadurl, '', false); } + $uploadcfg['fullmode'] = isset($uploadcfg['fullmode']) && $uploadcfg['fullmode'] ? true : false; + $uploadcfg['thumbstyle'] = $uploadcfg['thumbstyle'] ?? ''; $upload = [ - 'cdnurl' => $uploadcfg['cdnurl'], - 'uploadurl' => $uploadurl, - 'bucket' => 'local', - 'maxsize' => $uploadcfg['maxsize'], - 'mimetype' => $uploadcfg['mimetype'], - 'chunking' => $uploadcfg['chunking'], - 'chunksize' => $uploadcfg['chunksize'], - 'savekey' => $uploadcfg['savekey'], - 'multipart' => [], - 'multiple' => $uploadcfg['multiple'], - 'storage' => 'local' + 'cdnurl' => $uploadcfg['cdnurl'], + 'uploadurl' => $uploadurl, + 'bucket' => 'local', + 'maxsize' => $uploadcfg['maxsize'], + 'mimetype' => $uploadcfg['mimetype'], + 'chunking' => $uploadcfg['chunking'], + 'chunksize' => $uploadcfg['chunksize'], + 'savekey' => $uploadcfg['savekey'], + 'multipart' => [], + 'multiple' => $uploadcfg['multiple'], + 'fullmode' => $uploadcfg['fullmode'], + 'thumbstyle' => $uploadcfg['thumbstyle'], + 'storage' => 'local' ]; return $upload; } diff --git a/application/common/view/tpl/dispatch_jump.tpl b/application/common/view/tpl/dispatch_jump.tpl index 50dd96d8..64ed63dd 100755 --- a/application/common/view/tpl/dispatch_jump.tpl +++ b/application/common/view/tpl/dispatch_jump.tpl @@ -7,7 +7,7 @@