diff --git a/application/admin/command/Addon.php b/application/admin/command/Addon.php index 7bca186e..c738c6a0 100644 --- a/application/admin/command/Addon.php +++ b/application/admin/command/Addon.php @@ -201,16 +201,20 @@ class Addon extends Command new \RecursiveDirectoryIterator($addonDir), \RecursiveIteratorIterator::LEAVES_ONLY ); + $addonDir = str_replace(DS, '/', $addonDir); + $excludeDirRegex = "/\/(\.git|\.svn|\.vscode|\.idea|unpackage)\//i"; foreach ($files as $name => $file) { - if (!$file->isDir()) { - $filePath = $file->getRealPath(); - $relativePath = str_replace(DS, '/', substr($filePath, strlen($addonDir))); - if (!in_array($file->getFilename(), ['.git', '.DS_Store', 'Thumbs.db'])) { - $zip->addFile($filePath, $relativePath); - } + $filePath = str_replace(DS, '/', $file->getPathname()); + if ($file->isDir() || preg_match($excludeDirRegex, $filePath)) + continue; + $relativePath = substr($filePath, strlen($addonDir)); + if (!in_array($file->getFilename(), ['.DS_Store', 'Thumbs.db'])) { + $zip->addFile($filePath, $relativePath); } } + $zip->close(); + $output->info("Package Resource Path:" . $addonFile); $output->info("Package Successed!"); break; case 'move': diff --git a/application/admin/command/Crud.php b/application/admin/command/Crud.php index b55f338a..3c54d39f 100755 --- a/application/admin/command/Crud.php +++ b/application/admin/command/Crud.php @@ -920,6 +920,7 @@ class Crud extends Command $replace = '\'{"custom[type]":"' . $table . '"}\''; } elseif ($selectpageController == 'admin') { $attrArr['data-source'] = 'auth/admin/selectpage'; + $attrArr['data-field'] = 'nickname'; } elseif ($selectpageController == 'user') { $attrArr['data-source'] = 'user/user/index'; $attrArr['data-field'] = 'nickname'; diff --git a/application/admin/command/Crud/stubs/mixins/checkbox.stub b/application/admin/command/Crud/stubs/mixins/checkbox.stub index d5f7b664..ba87ac81 100644 --- a/application/admin/command/Crud/stubs/mixins/checkbox.stub +++ b/application/admin/command/Crud/stubs/mixins/checkbox.stub @@ -1,7 +1,7 @@ public function {%methodName%}($value, $data) { - $value = $value ? $value : (isset($data['{%field%}']) ? $data['{%field%}'] : ''); + $value = $value ?: ($data['{%field%}'] ?? ''); $valueArr = explode(',', $value); $list = $this->{%listMethodName%}(); return implode(',', array_intersect_key($list, array_flip($valueArr))); diff --git a/application/admin/command/Crud/stubs/mixins/datetime.stub b/application/admin/command/Crud/stubs/mixins/datetime.stub index 591dd4dd..60044487 100644 --- a/application/admin/command/Crud/stubs/mixins/datetime.stub +++ b/application/admin/command/Crud/stubs/mixins/datetime.stub @@ -1,6 +1,6 @@ public function {%methodName%}($value, $data) { - $value = $value ? $value : (isset($data['{%field%}']) ? $data['{%field%}'] : ''); + $value = $value ?: ($data['{%field%}'] ?? ''); return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; } \ No newline at end of file diff --git a/application/admin/command/Crud/stubs/mixins/radio.stub b/application/admin/command/Crud/stubs/mixins/radio.stub index 71234a63..030d373d 100644 --- a/application/admin/command/Crud/stubs/mixins/radio.stub +++ b/application/admin/command/Crud/stubs/mixins/radio.stub @@ -1,7 +1,7 @@ public function {%methodName%}($value, $data) { - $value = $value ? $value : (isset($data['{%field%}']) ? $data['{%field%}'] : ''); + $value = $value ?: ($data['{%field%}'] ?? ''); $list = $this->{%listMethodName%}(); - return isset($list[$value]) ? $list[$value] : ''; + return $list[$value] ?? ''; } \ No newline at end of file diff --git a/application/admin/command/Crud/stubs/mixins/select.stub b/application/admin/command/Crud/stubs/mixins/select.stub index 71234a63..030d373d 100644 --- a/application/admin/command/Crud/stubs/mixins/select.stub +++ b/application/admin/command/Crud/stubs/mixins/select.stub @@ -1,7 +1,7 @@ public function {%methodName%}($value, $data) { - $value = $value ? $value : (isset($data['{%field%}']) ? $data['{%field%}'] : ''); + $value = $value ?: ($data['{%field%}'] ?? ''); $list = $this->{%listMethodName%}(); - return isset($list[$value]) ? $list[$value] : ''; + return $list[$value] ?? ''; } \ No newline at end of file diff --git a/application/admin/command/Install.php b/application/admin/command/Install.php index 572cc979..c4330599 100644 --- a/application/admin/command/Install.php +++ b/application/admin/command/Install.php @@ -214,22 +214,27 @@ class Install extends Command $adminFile = ROOT_PATH . 'public' . DS . 'admin.php'; // 数据库配置文件 - $dbConfigFile = APP_PATH . 'database.php'; - $dbConfigText = @file_get_contents($dbConfigFile); + $envSampleFile = ROOT_PATH . '.env.sample'; + $envFile = ROOT_PATH . '.env'; + if (!file_exists($envFile)) { + if (!copy($envSampleFile, $envFile)) { + throw new Exception(__('Failed to copy %s to %s', '.env.sample', '.env')); + } + } + + $envText = @file_get_contents($envFile); + $callback = function ($matches) use ($mysqlHostname, $mysqlHostport, $mysqlUsername, $mysqlPassword, $mysqlDatabase, $mysqlPrefix) { $field = "mysql" . ucfirst($matches[1]); $replace = $$field; - if ($matches[1] == 'hostport' && $mysqlHostport == 3306) { - $replace = ''; - } - return "'{$matches[1]}'{$matches[2]}=>{$matches[3]}Env::get('database.{$matches[1]}', '{$replace}'),"; + return "{$matches[1]} = {$replace}"; }; - $dbConfigText = preg_replace_callback("/'(hostname|database|username|password|hostport|prefix)'(\s+)=>(\s+)Env::get\((.*)\)\,/", $callback, $dbConfigText); + $envText = preg_replace_callback("/(hostname|database|username|password|hostport|prefix)\s*=\s*(.*)/", $callback, $envText); // 检测能否成功写入数据库配置 - $result = @file_put_contents($dbConfigFile, $dbConfigText); + $result = @file_put_contents($envFile, $envText); if (!$result) { - throw new Exception(__('The current permissions are insufficient to write the file %s', 'application/database.php')); + throw new Exception(__('The current permissions are insufficient to write the file %s', '.env')); } // 设置新的Token随机密钥key @@ -244,7 +249,7 @@ class Install extends Command throw new Exception(__('The current permissions are insufficient to write the file %s', 'application/config.php')); } - $avatar = request()->domain() . '/assets/img/avatar.png'; + $avatar = '/assets/img/avatar.png'; // 变更默认管理员密码 $adminPassword = $adminPassword ? $adminPassword : Random::alnum(8); $adminEmail = $adminEmail ? $adminEmail : "admin@admin.com"; diff --git a/application/admin/controller/Ajax.php b/application/admin/controller/Ajax.php index 32748b01..4fd33e1f 100644 --- a/application/admin/controller/Ajax.php +++ b/application/admin/controller/Ajax.php @@ -21,7 +21,6 @@ use think\Validate; */ class Ajax extends Backend { - protected $noNeedLogin = ['lang']; protected $noNeedRight = ['*']; protected $layout = ''; @@ -207,7 +206,6 @@ class Ajax extends Backend $type = $this->request->request("type"); switch ($type) { case 'all': - // no break case 'content': //内容缓存 rmdirs(CACHE_PATH, false); @@ -215,18 +213,21 @@ class Ajax extends Backend if ($type == 'content') { break; } + // no break case 'template': // 模板缓存 rmdirs(TEMP_PATH, false); if ($type == 'template') { break; } + // no break case 'addons': // 插件缓存 Service::refresh(); if ($type == 'addons') { break; } + // no break case 'browser': // 浏览器缓存 // 只有生产环境下才修改 @@ -323,5 +324,4 @@ class Ajax extends Backend $response = Response::create($data, '', 200, $header); return $response; } - } diff --git a/application/admin/lang/zh-cn.php b/application/admin/lang/zh-cn.php index f7420df2..f0e1bc49 100755 --- a/application/admin/lang/zh-cn.php +++ b/application/admin/lang/zh-cn.php @@ -7,6 +7,7 @@ return [ 'Mobile' => '手机', 'Email' => '邮箱', 'Password' => '密码', + 'Mobile' => '手机号', 'Sign up' => '注 册', 'Sign in' => '登 录', 'Sign out' => '退 出', diff --git a/application/admin/lang/zh-cn/index.php b/application/admin/lang/zh-cn/index.php index 3bde7d59..dcb72058 100644 --- a/application/admin/lang/zh-cn/index.php +++ b/application/admin/lang/zh-cn/index.php @@ -30,6 +30,7 @@ return [ 'You\'ve logged in, do not login again' => '你已经登录,无需重复登录', 'Username or password can not be empty' => '用户名密码不能为空', 'Username or password is incorrect' => '用户名或密码不正确', + 'Username must be 3 to 30 characters' => '用户名只能由3-30位数字、字母、下划线组合', 'Username is incorrect' => '用户名不正确', 'Password is incorrect' => '密码不正确', 'Admin is forbidden' => '管理员已经被禁止登录', diff --git a/application/admin/view/common/script.html b/application/admin/view/common/script.html index 01c615e3..04d1e80f 100644 --- a/application/admin/view/common/script.html +++ b/application/admin/view/common/script.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/application/admin/view/general/attachment/add.html b/application/admin/view/general/attachment/add.html index 829adc45..f535e16a 100644 --- a/application/admin/view/general/attachment/add.html +++ b/application/admin/view/general/attachment/add.html @@ -46,9 +46,9 @@ {/foreach} - + {if $config.upload.chunking} - + {/if} diff --git a/application/common/library/Log.php b/application/common/library/Log.php index c6192ca8..d9aff8df 100644 --- a/application/common/library/Log.php +++ b/application/common/library/Log.php @@ -19,10 +19,8 @@ class Log extends AbstractLogger * @param array $context * * @return void - * - * @throws \Psr\Log\InvalidArgumentException */ - public function log($level, $message, array $context = array()) + public function log($level, $message, array $context = []) { \think\Log::write($message); } diff --git a/application/common/model/Config.php b/application/common/model/Config.php index d3f49ad1..d0904923 100644 --- a/application/common/model/Config.php +++ b/application/common/model/Config.php @@ -219,7 +219,7 @@ class Config extends Model } file_put_contents( CONF_PATH . 'extra' . DS . 'site.php', - ' false, + /** + * 上传超时时长,这里仅用于JS上传超时控制 + */ + 'timeout' => 60000, /** * 是否支持分片上传 */ diff --git a/extend/fast/Http.php b/extend/fast/Http.php index b3bb31f7..0af26dc4 100644 --- a/extend/fast/Http.php +++ b/extend/fast/Http.php @@ -11,11 +11,11 @@ class Http /** * 发送一个POST请求 * @param string $url 请求URL - * @param array $params 请求参数 - * @param array $options 扩展参数 + * @param array $params 请求参数 + * @param array $options 扩展参数 * @return mixed|string */ - public static function post($url, $params = [], $options = []) + public static function post(string $url, array $params = [], array $options = []) { $req = self::sendRequest($url, $params, 'POST', $options); return $req['ret'] ? $req['msg'] : ''; @@ -24,11 +24,11 @@ class Http /** * 发送一个GET请求 * @param string $url 请求URL - * @param array $params 请求参数 - * @param array $options 扩展参数 + * @param array $params 请求参数 + * @param array $options 扩展参数 * @return mixed|string */ - public static function get($url, $params = [], $options = []) + public static function get(string $url, array $params = [], array $options = []) { $req = self::sendRequest($url, $params, 'GET', $options); return $req['ret'] ? $req['msg'] : ''; @@ -42,7 +42,7 @@ class Http * @param mixed $options CURL的参数 * @return array */ - public static function sendRequest($url, $params = [], $method = 'POST', $options = []) + public static function sendRequest(string $url, $params = [], string $method = 'POST', $options = []): array { $method = strtoupper($method); $protocol = substr($url, 0, 5); @@ -108,7 +108,7 @@ class Http * @param string $method 请求的方法 * @return boolean TRUE */ - public static function sendAsyncRequest($url, $params = [], $method = 'POST') + public static function sendAsyncRequest(string $url, $params = [], string $method = 'POST'): bool { $method = strtoupper($method); $method = $method == 'POST' ? 'POST' : 'GET'; @@ -157,10 +157,10 @@ class Http /** * 发送文件到客户端 * @param string $file - * @param bool $delaftersend - * @param bool $exitaftersend + * @param bool $deleteAfterSend + * @param bool $exitAfterSend */ - public static function sendToBrowser($file, $delaftersend = true, $exitaftersend = true) + public static function sendToBrowser(string $file, bool $deleteAfterSend = true, bool $exitAfterSend = true) { if (file_exists($file) && is_readable($file)) { header('Content-Description: File Transfer'); @@ -174,10 +174,10 @@ class Http ob_clean(); flush(); readfile($file); - if ($delaftersend) { + if ($deleteAfterSend) { unlink($file); } - if ($exitaftersend) { + if ($exitAfterSend) { exit; } } diff --git a/extend/fast/Random.php b/extend/fast/Random.php index 88109171..db1f6f9a 100644 --- a/extend/fast/Random.php +++ b/extend/fast/Random.php @@ -14,7 +14,7 @@ class Random * @param int $len 长度 * @return string */ - public static function alnum($len = 6) + public static function alnum(int $len = 6): string { return self::build('alnum', $len); } @@ -25,7 +25,7 @@ class Random * @param int $len 长度 * @return string */ - public static function alpha($len = 6) + public static function alpha(int $len = 6): string { return self::build('alpha', $len); } @@ -36,7 +36,7 @@ class Random * @param int $len 长度 * @return string */ - public static function numeric($len = 4) + public static function numeric(int $len = 4): string { return self::build('numeric', $len); } @@ -47,7 +47,7 @@ class Random * @param int $len 长度 * @return string */ - public static function nozero($len = 4) + public static function nozero(int $len = 4): string { return self::build('nozero', $len); } @@ -58,7 +58,7 @@ class Random * @param int $len 长度 * @return string */ - public static function build($type = 'alnum', $len = 8) + public static function build(string $type = 'alnum', int $len = 8): string { switch ($type) { case 'alpha': @@ -93,7 +93,7 @@ class Random * 获取全球唯一标识 * @return string */ - public static function uuid() + public static function uuid(): string { return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', diff --git a/extend/fast/Tree.php b/extend/fast/Tree.php index 2c1997c2..1f9e97fc 100644 --- a/extend/fast/Tree.php +++ b/extend/fast/Tree.php @@ -325,7 +325,7 @@ class Tree '@url' => $childdata || !isset($value['@url']) ? "javascript:;" : $value['@url'], '@addtabs' => $childdata || !isset($value['@url']) ? "" : (stripos($value['@url'], "?") !== false ? "&" : "?") . "ref=addtabs", '@caret' => ($childdata && (!isset($value['@badge']) || !$value['@badge']) ? '' : ''), - '@badge' => isset($value['@badge']) ? $value['@badge'] : '', + '@badge' => $value['@badge'] ?? '', '@class' => ($selected ? ' active' : '') . ($disabled ? ' disabled' : '') . ($childdata ? ' treeview' . (config('fastadmin.show_submenu') ? ' treeview-open' : '') : ''), ); $str .= strtr($nstr, $value); @@ -422,7 +422,7 @@ class Tree { $arr = []; foreach ($data as $k => $v) { - $childlist = isset($v['childlist']) ? $v['childlist'] : []; + $childlist = $v['childlist'] ?? []; unset($v['childlist']); $v[$field] = $v['spacer'] . ' ' . $v[$field]; $v['haschild'] = $childlist ? 1 : 0; diff --git a/public/assets/js/backend/addon.js b/public/assets/js/backend/addon.js index 42eb9d22..defe5b52 100644 --- a/public/assets/js/backend/addon.js +++ b/public/assets/js/backend/addon.js @@ -165,7 +165,10 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie'] title: __('Operate'), table: table, formatter: Controller.api.formatter.operate, - align: 'right' + align: 'right', + cellStyle: function (value, row, index) { + return {css: {'min-width': '158px'}}; + } }, ] ], @@ -238,6 +241,27 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie'] Layer.close(index); }); return false; + } else if (ret && ret.code === -3) { + //插件目录发现影响全局的文件 + Layer.open({ + content: Template("conflicttpl", ret.data), + shade: 0.8, + area: area, + title: __('Warning'), + btn: [__('Continue install'), __('Cancel')], + end: function () { + + }, + yes: function (index) { + up.removeFile(file); + file.force = true; + up.uploadFile(file); + Layer.close(index); + } + }); + + } else { + Layer.alert(ret.msg, {title: __('Warning'), icon: 0}); } }); diff --git a/public/assets/js/backend/auth/rule.js b/public/assets/js/backend/auth/rule.js index f88928c5..77477b1d 100755 --- a/public/assets/js/backend/auth/rule.js +++ b/public/assets/js/backend/auth/rule.js @@ -180,7 +180,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function var iconfunc = function () { Layer.open({ type: 1, - area: ['99%', '98%'], //宽高 + area: ['80%', '80%'], //宽高 content: Template('chooseicontpl', {iconlist: iconlist}) }); }; @@ -192,8 +192,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function }); $(document).on('click', ".btn-search-icon", function () { if (iconlist.length == 0) { - $.get(Config.site.cdnurl + "/assets/libs/font-awesome/less/variables.less", function (ret) { - var exp = /fa-var-(.*):/ig; + $.get(Config.site.cdnurl + "/assets/libs/font-awesome/css/font-awesome.css", function (ret) { + var exp = /fa-(.*):before/ig; var result; while ((result = exp.exec(ret)) != null) { iconlist.push(result[1]); diff --git a/public/assets/js/backend/general/attachment.js b/public/assets/js/backend/general/attachment.js index 23202114..53c8680a 100644 --- a/public/assets/js/backend/general/attachment.js +++ b/public/assets/js/backend/general/attachment.js @@ -167,7 +167,7 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin { field: 'operate', title: __('Operate'), width: 85, events: { 'click .btn-chooseone': function (e, value, row, index) { - Fast.api.close({url: row.url, multiple: multiple}); + Fast.api.close($.extend({multiple: multiple}, row)); }, }, formatter: function () { return ' ' + __('Choose') + ''; diff --git a/public/assets/js/bootstrap-table-commonsearch.js b/public/assets/js/bootstrap-table-commonsearch.js index bb1f9ebb..a6c20457 100644 --- a/public/assets/js/bootstrap-table-commonsearch.js +++ b/public/assets/js/bootstrap-table-commonsearch.js @@ -208,7 +208,7 @@ } else { value = process ? process(obj.val()) : obj.val(); } - if (removeempty && (value == '' || value == null || ($.isArray(value) && value.length == 0)) && !sym.match(/null/i)) { + if (removeempty && (value === '' || value == null || ($.isArray(value) && value.length === 0)) && !sym.match(/null/i)) { return true; } @@ -268,7 +268,7 @@ return "Common search"; }, formatCommonSubmitButton: function () { - return "Submit"; + return "Search"; }, formatCommonResetButton: function () { return "Reset"; diff --git a/public/assets/js/require-form.js b/public/assets/js/require-form.js index fcdcc6f3..f327febc 100755 --- a/public/assets/js/require-form.js +++ b/public/assets/js/require-form.js @@ -102,6 +102,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio //绑定select元素事件 if ($(".selectpicker", form).length > 0) { require(['bootstrap-select', 'bootstrap-select-lang'], function () { + $.fn.selectpicker.Constructor.BootstrapVersion = '3'; $('.selectpicker', form).selectpicker(); $(form).on("reset", function () { setTimeout(function () { @@ -294,6 +295,9 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio var url = Config.upload.fullmode ? Fast.api.cdnurl(data.url) : data.url; $("#" + input_id).val(url).trigger("change").trigger("validate"); } + + // 触发选择文件自定义事件 + button.trigger("fa.event.selectedfile", data); } }); return false; @@ -567,7 +571,9 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio } }; // @formatter:on + var $disabledElements = form.find(':disabled').removeAttr('disabled'); var dataArr = form.serializeArray(), dataObj = {}, fieldName, fieldValue; + $disabledElements.attr('disabled', 'disabled'); $(dataArr).each(function (i, field) { fieldName = field.name; fieldValue = field.value;