diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 000000000..a3a6c1335 --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,120 @@ +setRiskyAllowed(true)->setParallelConfig(new ParallelConfig(8, 24)); +$finder = Finder::create()->in(__DIR__)->exclude(['vendor', 'public', 'runtime']); +return $config->setFinder($finder)->setUsingCache(false)->setRules([ + '@PSR2' => true, + '@Symfony' => true, + '@DoctrineAnnotation' => true, + '@PhpCsFixer' => true, + 'header_comment' => [ + 'comment_type' => 'PHPDoc', + 'header' => $header, + 'separate' => 'none', + 'location' => 'after_declare_strict', + ], + 'array_syntax' => [ + 'syntax' => 'short', + ], + 'list_syntax' => [ + 'syntax' => 'short', + ], + 'blank_line_before_statement' => [ + 'statements' => [ + 'declare', + ], + ], + 'general_phpdoc_annotation_remove' => [ + 'annotations' => [ + 'author', + ], + ], + 'ordered_imports' => [ + 'imports_order' => [ + 'class', 'function', 'const', + ], + 'sort_algorithm' => 'alpha', + ], + 'single_line_comment_style' => [ + 'comment_types' => [ + ], + ], + 'yoda_style' => [ + 'always_move_variable' => false, + 'equal' => false, + 'identical' => false, + ], + 'phpdoc_align' => [ + 'align' => 'left', + ], + 'multiline_whitespace_before_semicolons' => [ + 'strategy' => 'no_multi_line', + ], + 'constant_case' => [ + 'case' => 'lower', + ], + 'encoding' => true, // PHP代码必须只使用没有BOM的UTF-8 + 'line_ending' => true, // 所有的PHP文件编码必须一致 + 'single_quote' => true, // 简单字符串应该使用单引号代替双引号 + 'no_empty_statement' => true, // 不应该存在空的结构体 + 'standardize_not_equals' => true, // 使用 <> 代替 != + 'blank_line_after_namespace' => true, // 命名空间之后空一行 + 'no_empty_phpdoc' => true, // 不应该存在空的 phpdoc + 'no_empty_comment' => true, // 不应该存在空注释 + 'no_singleline_whitespace_before_semicolons' => true, // 禁止在关闭分号前使用单行空格 + 'concat_space' => ['spacing' => 'one'], // 连接字符是否需要空格,可选配置项 none:不需要 one:一个空格 + 'no_leading_import_slash' => true, // use 语句中取消前置斜杠 + 'cast_spaces' => ['space' => 'none'], + 'class_attributes_separation' => true, + 'combine_consecutive_unsets' => true, + 'declare_strict_types' => true, + 'lowercase_static_reference' => true, + 'linebreak_after_opening_tag' => true, + 'multiline_comment_opening_closing' => true, + 'no_useless_else' => true, + 'no_unused_imports' => true, + 'not_operator_with_successor_space' => false, + 'not_operator_with_space' => false, + 'ordered_class_elements' => true, + 'php_unit_strict' => false, + 'phpdoc_separation' => false, +]); diff --git a/app/index/controller/Index.php b/app/index/controller/Index.php index 2f5fbf79c..ab6fdaffd 100644 --- a/app/index/controller/Index.php +++ b/app/index/controller/Index.php @@ -1,18 +1,22 @@ env('CACHE_TYPE', 'file'), // 缓存连接配置 - 'stores' => [ - 'file' => [ + 'stores' => [ + 'file' => [ // 驱动方式 - 'type' => 'File', + 'type' => 'File', // 缓存保存目录 - 'path' => '', + 'path' => '', // 缓存名称前缀 - 'prefix' => '', + 'prefix' => '', // 缓存有效期 0 表示永久缓存 - 'expire' => 0, + 'expire' => 0, // 缓存标签前缀 'tag_prefix' => 'tag:', // 序列化机制 - 'serialize' => [], + 'serialize' => [], ], - 'safe' => [ + 'safe' => [ // 驱动方式 - 'type' => 'File', + 'type' => 'File', // 缓存保存目录 - 'path' => syspath('safefile/cache/'), + 'path' => syspath('safefile/cache/'), // 缓存名称前缀 - 'prefix' => '', + 'prefix' => '', // 缓存有效期 0 表示永久缓存 - 'expire' => 0, + 'expire' => 0, // 缓存标签前缀 'tag_prefix' => 'tag:', // 序列化机制 - 'serialize' => [], + 'serialize' => [], ], 'redis' => [ // 驱动方式 - 'type' => 'redis', - 'host' => env('CACHE_REDIS_HOST', '127.0.0.1'), - 'port' => env('CACHE_REDIS_PORT', 6379), - 'select' => env('CACHE_REDIS_SELECT', 0), + 'type' => 'redis', + 'host' => env('CACHE_REDIS_HOST', '127.0.0.1'), + 'port' => env('CACHE_REDIS_PORT', 6379), + 'select' => env('CACHE_REDIS_SELECT', 0), 'password' => env('CACHE_REDIS_PASSWORD', ''), - ] + ], ], -]; \ No newline at end of file +]; diff --git a/config/database.php b/config/database.php index ea58c067d..280a49dec 100644 --- a/config/database.php +++ b/config/database.php @@ -1,83 +1,86 @@ env('DB_TYPE', 'sqlite'), + 'default' => env('DB_TYPE', 'sqlite'), // 自定义时间查询规则 'time_query_rule' => [], // 自动写入时间戳字段 - 'auto_timestamp' => true, + 'auto_timestamp' => true, // 时间字段取出后的默认时间格式 'datetime_format' => 'Y-m-d H:i:s', // 数据库连接配置信息 - 'connections' => [ - 'mysql' => [ + 'connections' => [ + 'mysql' => [ // 数据库类型 - 'type' => 'mysql', + 'type' => 'mysql', // 服务器地址 - 'hostname' => env('DB_MYSQL_HOST', '127.0.0.1'), + 'hostname' => env('DB_MYSQL_HOST', '127.0.0.1'), // 服务器端口 - 'hostport' => env('DB_MYSQL_PORT', '3306'), + 'hostport' => env('DB_MYSQL_PORT', '3306'), // 数据库名 - 'database' => env('DB_MYSQL_DATABASE', 'thinkadmin'), + 'database' => env('DB_MYSQL_DATABASE', 'thinkadmin'), // 用户名 - 'username' => env('DB_MYSQL_USERNAME', 'root'), + 'username' => env('DB_MYSQL_USERNAME', 'root'), // 密码 - 'password' => env('DB_MYSQL_PASSWORD', ''), + 'password' => env('DB_MYSQL_PASSWORD', ''), // 数据库连接参数 - 'params' => [], + 'params' => [], // 数据库表前缀 - 'prefix' => env('DB_MYSQL_PREFIX', ''), + 'prefix' => env('DB_MYSQL_PREFIX', ''), // 数据库编码默认采用 utf8mb4 - 'charset' => env('DB_MYSQL_CHARSET', 'utf8mb4'), + 'charset' => env('DB_MYSQL_CHARSET', 'utf8mb4'), // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) - 'deploy' => 0, + 'deploy' => 0, // 数据库读写是否分离 主从式有效 - 'rw_separate' => false, + 'rw_separate' => false, // 读写分离后 主服务器数量 - 'master_num' => 1, + 'master_num' => 1, // 指定从服务器序号 - 'slave_no' => '', + 'slave_no' => '', // 检查字段是否存在 - 'fields_strict' => true, + 'fields_strict' => true, // 是否需要断线重连 'break_reconnect' => false, // 监听SQL执行日志 - 'trigger_sql' => true, + 'trigger_sql' => true, // 开启字段类型缓存 - 'fields_cache' => isOnline(), + 'fields_cache' => isOnline(), ], 'sqlite' => [ // 数据库类型 - 'type' => 'sqlite', + 'type' => 'sqlite', // 数据库文件 - 'database' => syspath('database/sqlite.db'), + 'database' => syspath('database/sqlite.db'), // 数据库编码默认采用 utf8 - 'charset' => 'utf8', + 'charset' => 'utf8', // 监听执行日志 'trigger_sql' => true, // 其他参数字段 - 'deploy' => 0, - 'suffix' => '', - 'prefix' => '', - 'hostname' => '', - 'hostport' => '', - 'username' => '', - 'password' => '', + 'deploy' => 0, + 'suffix' => '', + 'prefix' => '', + 'hostname' => '', + 'hostport' => '', + 'username' => '', + 'password' => '', ], ], ]; diff --git a/config/phinx.php b/config/phinx.php index a9ee86682..d6b34b457 100644 --- a/config/phinx.php +++ b/config/phinx.php @@ -1,19 +1,22 @@ [], @@ -21,4 +24,4 @@ return [ 'tables' => [], // 备份数据表,填写表名 'backup' => [], -]; \ No newline at end of file +]; diff --git a/config/worker.php b/config/worker.php index 974fe2415..a99b6457f 100644 --- a/config/worker.php +++ b/config/worker.php @@ -1,52 +1,52 @@ '127.0.0.1', + 'host' => '127.0.0.1', // 服务监听端口 - 'port' => 2346, + 'port' => 2346, // 套接字上下文选项 - 'context' => [], + 'context' => [], // 高级自定义服务类 - 'classes' => '', + 'classes' => '', // 消息请求回调处理 'callable' => null, // 服务进程参数配置 - 'worker' => [ - 'name' => 'ThinkAdmin', + 'worker' => [ + 'name' => 'ThinkAdmin', 'count' => 4, ], // 监控文件变更重载,仅 Debug 模式有效 - 'files' => [ + 'files' => [ // 监控检测间隔(单位秒,零不监控) 'time' => 3, // 文件监控目录(默认监控 app+config 目录) 'path' => [], // 文件监控后缀(默认监控 所有 文件) - 'exts' => ['*'] + 'exts' => ['*'], ], // 监控内存超限重载,仅 Debug 模式有效 - 'memory' => [ + 'memory' => [ // 监控检测间隔(单位秒,零不监控) - 'time' => 60, + 'time' => 60, // 限制内存大小(可选单位有 G M K ) - 'limit' => '1G' + 'limit' => '1G', ], -]; \ No newline at end of file +]; diff --git a/plugin/think-library/src/Builder.php b/plugin/think-library/src/Builder.php index d9fa17023..3a9b28fe7 100644 --- a/plugin/think-library/src/Builder.php +++ b/plugin/think-library/src/Builder.php @@ -1,20 +1,22 @@ '; + $html .= "\n\t\t\t" . sprintf('%s%s', empty($attrs['required']) ? '' : 'label-required-prev', $title, $substr); + $html .= "\n\t\t\t" . sprintf('', $name, $this->_attrs($attrs), $title, $this->variable, $name); + if ($remark) { + $html .= "\n\t\t\t" . sprintf('%s', $remark); + } + $this->fields[] = "{$html}\n\t\t"; + return $this; + } + + /** + * 创建 Text 输入. + * @param string $name 字段名称 + * @param string $title 字段标题 + * @param string $substr 字段子标题 + * @param string $remark 字段备注 + * @param bool $required 是否必填 + * @param ?string $pattern 验证规则 + * @param array $attrs 附加属性 + * @return $this + */ + public function addTextInput(string $name, string $title, string $substr = '', bool $required = false, string $remark = '', ?string $pattern = null, array $attrs = []): Builder + { + $attrs['vali-name'] = $title; + if ($required) { + $attrs['required'] = 'required'; + } + if (is_string($pattern)) { + $attrs['pattern'] = $pattern; + } + return $this->addInput($name, $title, $substr, $remark, $attrs); + } + + /** + * 创建密钥输入框. + * @param string $name 字段名称 + * @param string $title 字段标题 + * @param string $substr 字段子标题 + * @param string $remark 字段备注 + * @param bool $required 是否必填 + * @param ?string $pattern 验证规则 + * @param array $attrs 附加属性 + * @return $this + */ + public function addPassInput(string $name, string $title, string $substr = '', bool $required = false, string $remark = '', ?string $pattern = null, array $attrs = []): Builder + { + $attrs['type'] = 'password'; + return $this->addTextInput($name, $title, $substr, $required, $remark, $pattern, $attrs); + } + + /** + * 添加取消按钮. + * @param string $name 按钮名称 + * @param string $confirm 确认提示 + * @return $this + */ + public function addCancelButton(string $name = '取消编辑', string $confirm = '确定要取消编辑吗?'): Builder + { + return $this->addButton($name, $confirm, 'button', 'layui-btn-danger', ['data-close' => null]); + } + + /** + * 添加提交按钮. + * @param string $name 按钮名称 + * @param string $confirm 确认提示 + * @return $this + */ + public function addSubmitButton(string $name = '保存数据', string $confirm = ''): Builder + { + return $this->addButton($name, $confirm, 'submit'); + } + + /** + * 添加上传单图字段. + * @param string $name 字段名称 + * @param string $title 字段标题 + * @param string $substr 字段子标题 + * @param bool $required 必填字段 + * @param array $attrs 附加属性 + * @return $this + */ + public function addUploadOneImage(string $name, string $title, string $substr = '', bool $required = false, array $attrs = []): Builder + { + if ($required) { + $attrs['required'] = 'required'; + } + return $this->_addUploadOneView($name, $title, $substr, $attrs); + } + + /** + * 添加上传视频字段. + * @param string $name 字段名称 + * @param string $title 字段标题 + * @param string $substr 字段子标题 + * @param bool $required 必填字段 + * @param array $attrs 附加属性 + * @return $this + */ + public function addUploadOneVideo(string $name, string $title, string $substr = '', bool $required = false, array $attrs = []): Builder + { + if ($required) { + $attrs['required'] = 'required'; + } + return $this->_addUploadOneView($name, $title, $substr, $attrs, 'video'); + } + + /** + * 创建上传多图字段. + * @param string $name 字段名称 + * @param string $title 字段标题 + * @param string $substr 字段子标题 + * @param bool $required 必填字段 + * @param array $attrs 附加属性 + * @return $this + */ + public function addUploadMulImage(string $name, string $title, string $substr = '', bool $required = false, array $attrs = []): Builder + { + if ($required) { + $attrs['required'] = 'required'; + } + $attrs = array_merge($attrs, ['type' => 'hidden', 'placeholder' => "请上传{$title} ( 多图 )"]); + $html = "\n\t\t" . '
'; + $html .= "\n\t\t\t" . sprintf('%s%s', empty($attrs['required']) ? '' : 'label-required-prev ', $title, $substr); + $html .= "\n\t\t\t" . '
'; + $html .= "\n\t\t\t\t" . sprintf('', $name, $this->_attrs($attrs), $this->variable, $name); + $html .= "\n\t\t\t" . '
' . "\n\t\t" . '
'; + $html .= "\n\t\t" . sprintf('', $name); + $this->fields[] = $html; + return $this; + } + + /** + * 创建复选框字段. + * @param string $name 字段名称 + * @param string $title 字段标题 + * @param string $substr 字段子标题 + * @param string $vname 变量名称 + * @param bool $required 是否必选 + * @param array $attrs 附加属性 + * @return $this + */ + public function addCheckInput(string $name, string $title, string $substr, string $vname, bool $required = false, array $attrs = [], string $type = 'checkbox'): Builder + { + if ($required) { + $attrs['required'] = 'required'; + } + $attrs = array_merge($attrs, ['type' => $type, 'lay-ignore' => null, 'name' => $name . ($type === 'checkbox' ? '[]' : '')]); + $html = "\n\t\t" . '
'; + $html .= "\n\t\t\t" . sprintf('%s%s', empty($attrs['required']) ? '' : ' label-required-prev', $title, $substr); + $html .= "\n\t\t\t" . '
'; + $html .= "\n\t\t\t\t" . sprintf('', $vname); + $html .= "\n\t\t\t\t" . sprintf(''; + $html .= "\n\t\t\t\t" . ''; + $this->fields[] = $html . "\n\t\t\t
\n\t\t
"; + return $this; + } + + /** + * 添加单选框架字段. + * @param string $name 字段名称 + * @param string $title 字段标题 + * @param string $substr 字段子标题 + * @param string $vname 变量名称 + * @param bool $required 是否必选 + * @param array $attrs 附加属性 + * @return $this + */ + public function addRadioInput(string $name, string $title, string $substr, string $vname, bool $required = false, array $attrs = []): Builder + { + return $this->addCheckInput($name, $title, $substr, $vname, $required, $attrs, 'radio'); + } + + /** + * 显示模板内容. + * @return mixed + */ + public function fetch(array $vars = []) + { + $html = ''; + $type = "{$this->type}.{$this->mode}"; + if ($type === 'form.page') { + $html = $this->_buildFormPage(); + } elseif ($type === 'form.modal') { + $html = $this->_buildFormModal(); + } + foreach ($this->class as $k => $v) { + $vars[$k] = $v; + } + throw new HttpResponseException(display($html, $vars)); + } + + /** + * 增加输入表单元素. * @param string $name 字段名称 * @param string $title 字段标题 * @param string $subtitle 字段子标题 @@ -126,80 +335,26 @@ class Builder $html = "\n\t\t" . '"; return $this; } /** - * 创建文本输入框架 - * @param string $name 字段名称 - * @param string $title 字段标题 - * @param string $substr 字段子标题 - * @param array $attrs 附加属性 - * @return $this - */ - public function addTextArea(string $name, string $title, string $substr = '', bool $required = false, $remark = '', array $attrs = []): Builder - { - if ($required) $attrs['required'] = 'required'; - $html = "\n\t\t" . '