初始化本地仓库

This commit is contained in:
2026-08-31 11:33:59 +08:00
commit 663f74b633
2390 changed files with 402918 additions and 0 deletions
@@ -0,0 +1,69 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* API 生成器
* 负责生成前端 API 文件内容
*/
class ApiGenerator implements FileGeneratorInterface
{
/**
* @var array 配置信息
*/
private array $config;
/**
* @var TemplateRenderer 模板渲染器
*/
private TemplateRenderer $templateRenderer;
/**
* 构造函数
* @param array $config 配置信息
*/
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
/**
* 生成文件内容
* @return string 文件内容
*/
public function generateContent(): string
{
$className = $this->config['class_name'] ?? 'DefaultModel';
$moduleName = $this->config['package_name'] ?? 'default';
// 生成带类名的接口类型名称
$rowTypeName = $className . 'Row';
// 生成baseUrl,使用连字符(-)而不是下划线(_)
$basePath = strtolower(str_replace('_', '-', $moduleName));
$classPath = strtolower(str_replace('_', '-', $className));
$baseUrl = $this->config['base_url'] ?? '/' . $basePath . '/' . $classPath;
$content = $this->templateRenderer->render('admin/api/index.stub', [
'class_name' => $className,
'module_name' => $moduleName,
'base_url' => $baseUrl,
'row_type_name' => $rowTypeName,
]);
return $content;
}
/**
* 获取文件扩展名
* @return string 文件扩展名
*/
public function getFileExtension(): string
{
return 'ts';
}
}
@@ -0,0 +1,129 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* API 模型生成器
* 负责生成前端 API 模型文件内容
*/
class ApiModelGenerator implements FileGeneratorInterface
{
/**
* @var array 配置信息
*/
private array $config;
/**
* @var TemplateRenderer 模板渲染器
*/
private TemplateRenderer $templateRenderer;
/**
* 构造函数
* @param array $config 配置信息
*/
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
/**
* 生成文件内容
* @return string 文件内容
*/
public function generateContent(): string
{
$className = $this->config['class_name'] ?? 'DefaultModel';
$moduleName = $this->config['package_name'] ?? 'default';
// 生成带类名的接口类型名称
$rowTypeName = $className . 'Row';
// 生成字段类型映射
$fields = '';
if (isset($this->config['columns']) && is_array($this->config['columns'])) {
foreach ($this->config['columns'] as $column) {
if (isset($column['column_name']) && isset($column['column_type'])) {
$fieldName = $column['column_name'];
$fieldType = $this->getColumnType($column['column_type']);
$fieldComment = isset($column['column_comment']) ? $column['column_comment'] : '';
// 如果有注释,添加注释行
if (!empty($fieldComment)) {
$fields .= " /** {$fieldComment} */\n";
}
$fields .= " {$fieldName}: {$fieldType};\n";
}
}
}
$content = $this->templateRenderer->render('admin/api/types.stub', [
'class_name' => $className,
'module_name' => $moduleName,
'row_type_name' => $rowTypeName,
'fields' => $fields,
]);
return $content;
}
/**
* 根据数据库字段类型获取 TypeScript 类型
* @param string $columnType 数据库字段类型
* @return string TypeScript 类型
*/
private function getColumnType(string $columnType): string
{
$typeMap = [
'int' => 'number',
'integer' => 'number',
'tinyint' => 'number',
'smallint' => 'number',
'mediumint' => 'number',
'bigint' => 'number',
'float' => 'number',
'double' => 'number',
'decimal' => 'number',
'string' => 'string',
'varchar' => 'string',
'char' => 'string',
'text' => 'string',
'mediumtext' => 'string',
'longtext' => 'string',
'date' => 'string',
'datetime' => 'string',
'timestamp' => 'string',
'time' => 'string',
'year' => 'number',
'boolean' => 'boolean',
'bool' => 'boolean',
'json' => 'any',
'array' => 'any[]',
];
// 转换为小写并获取基础类型
$columnType = strtolower($columnType);
foreach ($typeMap as $key => $value) {
if (strpos($columnType, $key) === 0) {
return $value;
}
}
// 默认类型
return 'any';
}
/**
* 获取文件扩展名
* @return string 文件扩展名
*/
public function getFileExtension(): string
{
return 'ts';
}
}
@@ -0,0 +1,101 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* 控制器生成器
* 负责生成控制器文件内容
*/
class ControllerGenerator implements FileGeneratorInterface
{
/**
* @var array 配置信息
*/
private array $config;
/**
* @var TemplateRenderer 模板渲染器
*/
private TemplateRenderer $templateRenderer;
/**
* 构造函数
*
* @param array $config 配置信息
*/
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
/**
* 生成文件内容
*
* @return string 文件内容
*/
public function generateContent(): string
{
$template = $this->config['template'] ?? 'app';
$isPlugin = $template !== 'app';
$pluginName = $this->config['namespace'] ?? '';
$className = $this->config['class_name'] ?? 'DefaultModel';
$packageName = $this->config['package_name'] ?? 'default';
// 生成连字符格式的名称(用于路由path)
$packageNameDash = str_replace('_', '-', $packageName);
$classNameDash = str_replace('_', '-', strtolower($className));
// 生成小写下划线格式的名称(用于权限码)
$packageNameLower = strtolower($packageName);
$classNameLower = strtolower(str_replace('_', '', $className));
// 生成命名空间
if ($isPlugin) {
// 插件模式:plugin\{plugin_name}\app\controller\{package_name}
$namespace = "plugin\\{$pluginName}\\app\\controller\\{$packageName}";
$schemaRequestNamespace = "plugin\\{$pluginName}\\app\\schema\\request\\{$packageName}";
$validateNamespace = "plugin\\{$pluginName}\\app\\validate\\{$packageName}";
$schemaResponseNamespace = "plugin\\{$pluginName}\\app\\schema\\response\\{$packageName}";
$serviceNamespace = "plugin\\{$pluginName}\\app\\service\\{$packageName}";
} else {
// App 模式
$namespace = "app\\adminapi\\controller\\{$packageName}";
$schemaRequestNamespace = "app\\adminapi\\schema\\request\\{$packageName}";
$validateNamespace = "app\\adminapi\\validate\\{$packageName}";
$schemaResponseNamespace = "app\\adminapi\\schema\\response\\{$packageName}";
$serviceNamespace = "app\\service\\admin\\{$packageName}";
}
$data = [
'class_name' => $className,
'package_name' => $packageName,
'package_name_dash' => $packageNameDash,
'class_name_dash' => $classNameDash,
'package_name_lower' => $packageNameLower,
'class_name_lower' => $classNameLower,
'table_content' => $this->config['table_content'] ?? '默认模型',
'camel_class_name' => lcfirst($className),
'namespace' => $namespace,
'schema_request_namespace' => $schemaRequestNamespace,
'validate_namespace' => $validateNamespace,
'schema_response_namespace' => $schemaResponseNamespace,
'service_namespace' => $serviceNamespace,
];
return $this->templateRenderer->render('server/controller/controller.stub', $data);
}
/**
* 获取文件扩展名
*
* @return string 文件扩展名
*/
public function getFileExtension(): string
{
return 'php';
}
}
@@ -0,0 +1,76 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* DAO 生成器
* 负责生成 DAO 文件内容
*/
class DaoGenerator implements FileGeneratorInterface
{
/**
* @var array 配置信息
*/
private array $config;
/**
* @var TemplateRenderer 模板渲染器
*/
private TemplateRenderer $templateRenderer;
/**
* 构造函数
* @param array $config 配置信息
*/
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
/**
* 生成文件内容
* @return string 文件内容
*/
public function generateContent(): string
{
$template = $this->config['template'] ?? 'app';
$isPlugin = $template !== 'app';
$pluginName = $this->config['namespace'] ?? '';
// 生成命名空间
$packageName = $this->config['package_name'] ?? 'default';
if ($isPlugin) {
// 插件模式:plugin\{plugin_name}\app\dao\{package_name}
$namespace = "plugin\\{$pluginName}\\app\\dao\\{$packageName}";
$modelNamespace = "plugin\\{$pluginName}\\app\\model\\{$packageName}";
} else {
// App 模式:app\dao\{package_name}
$namespace = "app\\dao\\{$packageName}";
$modelNamespace = "app\\model\\{$packageName}";
}
$data = [
'class_name' => $this->config['class_name'] ?? 'DefaultModel',
'package_name' => $this->config['package_name'] ?? 'default',
'table_name' => $this->config['table_name'] ?? 'default_table',
'camel_class_name' => lcfirst($this->config['class_name'] ?? 'DefaultModel'),
'namespace' => $namespace,
'model_namespace' => $modelNamespace,
];
return $this->templateRenderer->render('server/dao/dao.stub', $data);
}
/**
* 获取文件扩展名
* @return string 文件扩展名
*/
public function getFileExtension(): string
{
return 'php';
}
}
@@ -0,0 +1,100 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* 语言包生成器
* 负责生成前端语言包文件内容
*/
class LangGenerator implements FileGeneratorInterface
{
private array $config;
private TemplateRenderer $templateRenderer;
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
public function generateContent(): string
{
$className = $this->config['class_name'] ?? 'DefaultModel';
$moduleName = $this->config['package_name'] ?? 'default';
$columns = $this->config['columns'] ?? [];
$langKey = $this->generateLangKey($moduleName, $className);
$fields = $this->generateFieldsTranslations($columns, $langKey);
$classComment = $this->getClassComment($columns);
$content = $this->templateRenderer->render('admin/lang/zh-cn/index.stub', [
'module_name' => $moduleName,
'class_name' => $className,
'lang_key' => $langKey,
'class_name_comment' => $classComment,
'fields' => $fields,
]);
return $content;
}
private function generateLangKey(string $moduleName, string $className): string
{
$classKey = strtolower(preg_replace('/([a-z0-9])([A-Z])/', '$1_$2', $className));
return "{$classKey}";
}
private function generateFieldsTranslations(array $columns, string $langKey): string
{
$listFields = [];
$formFields = [];
$searchFields = [];
foreach ($columns as $column) {
$fieldName = $column['column_name'];
$comment = $column['column_comment'] ?? $fieldName;
if (isset($column['is_lists']) && $column['is_lists'] == 1) {
$listFields[] = " \"{$fieldName}\": \"{$comment}\"";
}
if ((isset($column['is_insert']) && $column['is_insert'] == 1) ||
(isset($column['is_update']) && $column['is_update'] == 1)) {
$formFields[] = " \"{$fieldName}\": \"{$comment}\"";
}
if (isset($column['is_search']) && $column['is_search'] == 1) {
$searchFields[] = " \"{$fieldName}\": \"{$comment}\"";
}
}
$result = '';
if (!empty($listFields)) {
$result .= " \"list\": {\n" . implode(",\n", $listFields) . "\n },\n";
}
if (!empty($formFields)) {
$result .= " \"form\": {\n" . implode(",\n", $formFields) . "\n },\n";
}
if (!empty($searchFields)) {
$result .= " \"search\": {\n" . implode(",\n", $searchFields) . "\n }";
}
return rtrim($result, ",\n");
}
private function getClassComment(array $columns): string
{
return $this->config['class_name_comment'] ?? $this->config['table_comment'] ?? $this->config['class_name'];
}
public function getFileExtension(): string
{
return 'json';
}
}
@@ -0,0 +1,235 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* 模型生成器
* 负责生成模型文件内容
*/
class ModelGenerator implements FileGeneratorInterface
{
/**
* @var array 配置信息
*/
private array $config;
/**
* @var TemplateRenderer 模板渲染器
*/
private TemplateRenderer $templateRenderer;
/**
* 构造函数
* @param array $config 配置信息
*/
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
/**
* 生成文件内容
*
* @return string 文件内容
* @throws \Exception
*/
public function generateContent(): string
{
$template = $this->config['template'] ?? 'app';
$isPlugin = $template !== 'app';
$pluginName = $this->config['namespace'] ?? '';
// 生成命名空间
$packageName = $this->config['package_name'] ?? 'default';
if ($isPlugin) {
// 插件模式:plugin\{plugin_name}\app\model\{package_name}
$namespace = "plugin\\{$pluginName}\\app\\model\\{$packageName}";
} else {
// App 模式:app\model\{package_name}
$namespace = "app\\model\\{$packageName}";
}
$data = [
'class_name' => $this->config['class_name'] ?? 'DefaultModel',
'package_name' => $this->config['package_name'] ?? 'default',
'table_name' => $this->config['table_name'] ?? 'default_table',
'table_content' => $this->config['table_content'] ?? '默认模型',
'camel_class_name' => lcfirst($this->config['class_name'] ?? 'DefaultModel'),
'namespace' => $namespace,
];
// 查找主键字段
$primaryKey = 'id';
if (isset($this->config['columns']) && is_array($this->config['columns'])) {
foreach ($this->config['columns'] as $column) {
if (isset($column['column_name']) && isset($column['is_pk']) && $column['is_pk']) {
$primaryKey = $column['column_name'];
break;
}
}
}
// 添加主键字段到数据中
$data['primary_key'] = $primaryKey;
// 生成首字母大写的主键字段名,处理下划线的情况
$ucfirstPrimaryKey = ucfirst($primaryKey);
$ucfirstPrimaryKey = str_replace('_', '', ucwords($ucfirstPrimaryKey, '_'));
$data['ucfirst_primary_key'] = $ucfirstPrimaryKey;
// 生成可填充字段
$fillableFields = '';
if (isset($this->config['columns']) && is_array($this->config['columns'])) {
foreach ($this->config['columns'] as $column) {
if (isset($column['column_name'])) {
$fillableFields .= " '{$column['column_name']}',\n";
}
}
}
// 添加到数据中
$data['fillable_fields'] = $fillableFields;
// 生成基于is_search字段的搜索器
$searchers = '';
if (isset($this->config['columns']) && is_array($this->config['columns'])) {
foreach ($this->config['columns'] as $column) {
if (isset($column['column_name']) && isset($column['is_search']) && $column['is_search']) {
$columnName = $column['column_name'];
// 生成首字母大写的字段名,处理下划线的情况
$ucfirstColumnName = ucfirst($columnName);
$ucfirstColumnName = str_replace('_', '', ucwords($ucfirstColumnName, '_'));
// 确定搜索运算符
$operator = 'like';
if (isset($column['query_type']) && !empty($column['query_type'])) {
$operator = strtoupper($column['query_type']);
}
// 生成搜索器方法
$searchers .= " /**\n";
$searchers .= " * 搜索器:{$columnName}\n";
$searchers .= " */\n";
$searchers .= " public function scope{$ucfirstColumnName}(\$query, \$value)\n";
$searchers .= " {\n";
$searchers .= " if (\$value) {\n";
// 根据不同的运算符生成不同的搜索逻辑
switch ($operator) {
case '=':
case '!=':
case '>':
case '>=':
case '<':
case '<=':
$searchers .= " \$query->where('{$columnName}', '{$operator}', \$value);\n";
break;
case 'LIKE':
case 'NOT LIKE':
$searchers .= " \$query->where('{$columnName}', '{$operator}', '%' . \$value . '%');\n";
break;
case 'IN':
$searchers .= " if (is_array(\$value)) {\n";
$searchers .= " \$query->whereIn('{$columnName}', \$value);\n";
$searchers .= " }\n";
break;
case 'NOT IN':
$searchers .= " if (is_array(\$value)) {\n";
$searchers .= " \$query->whereNotIn('{$columnName}', \$value);\n";
$searchers .= " }\n";
break;
case 'BETWEEN':
$searchers .= " if (is_array(\$value) && count(\$value) == 2) {\n";
$searchers .= " \$query->whereBetween('{$columnName}', \$value);\n";
$searchers .= " }\n";
break;
case 'NOT BETWEEN':
$searchers .= " if (is_array(\$value) && count(\$value) == 2) {\n";
$searchers .= " \$query->whereNotBetween('{$columnName}', \$value);\n";
$searchers .= " }\n";
break;
default:
$searchers .= " \$query->where('{$columnName}', 'LIKE', '%' . \$value . '%');\n";
break;
}
$searchers .= " }\n";
$searchers .= " return \$query;\n";
$searchers .= " }\n\n";
}
}
}
// 添加到数据中
$data['searchers'] = $searchers;
// 生成关联方法
$relations = '';
if (isset($this->config['relations']) && !empty($this->config['relations'])) {
foreach ($this->config['relations'] as $relation) {
if (isset($relation['type']) && isset($relation['model']) && isset($relation['foreign_key']) && isset($relation['local_key'])) {
$relationType = $relation['type'];
$relationModel = $relation['model'];
$foreignKey = $relation['foreign_key'];
$localKey = $relation['local_key'];
// 优化关联方法名称,只使用模型类名的小写形式
$modelParts = explode('\\', $relationModel);
$methodName = lcfirst(end($modelParts));
// 如果是hasMany关系,添加s后缀
if ($relationType === 'hasMany') {
$methodName .= 's';
}
// 生成关联方法
$relations .= " /**\n";
$relations .= " * 关联 {$relationModel}\n";
$relations .= " */\n";
$relations .= " public function {$methodName}()\n";
$relations .= " {\n";
$relations .= " return \$this->{$relationType}('{$relationModel}', '{$foreignKey}', '{$localKey}');\n";
$relations .= " }\n\n";
}
}
}
// 生成软删除功能
$softDelete = '';
$softDeleteUse = '';
$softDeleteTrait = '';
$config = $this->config['config'] ?? [];
if (isset($config['is_delete']) && $config['is_delete'] == 1) {
$deleteColumn = $config['delete_column_name'] ?? 'deleted_at';
$softDeleteUse = "use Illuminate\\Database\\Eloquent\\SoftDeletes;\n";
$softDeleteTrait = " /**\n";
$softDeleteTrait .= " * 启用软删除\n";
$softDeleteTrait .= " */\n";
$softDeleteTrait .= " use SoftDeletes;\n\n";
$softDelete .= " /**\n";
$softDelete .= " * 软删除字段\n";
$softDelete .= " */\n";
$softDelete .= " const DELETED_AT = '{$deleteColumn}';\n\n";
}
// 添加到数据中
$data['soft_delete_use'] = $softDeleteUse;
$data['soft_delete_trait'] = $softDeleteTrait;
$data['soft_delete'] = $softDelete;
$data['relations'] = $relations;
return $this->templateRenderer->render('server/model/model.stub', $data);
}
/**
* 获取文件扩展名
* @return string 文件扩展名
*/
public function getFileExtension(): string
{
return 'php';
}
}
@@ -0,0 +1,243 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* DTO 生成器
* 负责生成 DTO 文件内容
*/
class RequestFormGenerator implements FileGeneratorInterface
{
/**
* @var array 配置信息
*/
private array $config;
/**
* @var TemplateRenderer 模板渲染器
*/
private TemplateRenderer $templateRenderer;
/**
* 构造函数
* @param array $config 配置信息
*/
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
/**
* 生成文件内容
*
* @return string 文件内容
* @throws \Exception
*/
public function generateContent(): string
{
$template = $this->config['template'] ?? 'app';
$isPlugin = $template !== 'app';
$pluginName = $this->config['namespace'] ?? '';
// 生成命名空间
$packageName = $this->config['package_name'] ?? 'default';
if ($isPlugin) {
// 插件模式:plugin\{plugin_name}\app\schema\request\{package_name}
$namespace = "plugin\\{$pluginName}\\app\\schema\\request\\{$packageName}";
} else {
// App 模式:app\adminapi\schema\\request\{package_name}
$namespace = "app\\adminapi\\schema\\request\\{$packageName}";
}
$data = [
'class_name' => $this->config['class_name'] ?? 'DefaultModel',
'package_name' => $this->config['package_name'] ?? 'default',
'columns' => $this->config['columns'] ?? [],
'namespace' => $namespace,
];
// 生成字段注解
$fields = '';
if (isset($data['columns']) && is_array($data['columns'])) {
foreach ($data['columns'] as $column) {
// 跳过主键字段
if (isset($column['is_pk']) && $column['is_pk']) {
continue;
}
// 生成字段注解
$fields .= $this->generateFieldAnnotation($column);
}
}
// 添加到数据中
$data['fields'] = $fields;
return $this->templateRenderer->render('server/schema/request/form.stub', $data);
}
/**
* 生成字段注解
* @param array $column 字段信息
* @return string 字段注解代码
*/
private function generateFieldAnnotation(array $column): string
{
$columnName = $column['column_name'];
$columnComment = $column['column_comment'];
$isRequired = isset($column['is_required']) && $column['is_required'];
$columnType = $column['column_type'] ?? 'string';
// 确定字段类型
$phpType = $this->getPhpType($columnType);
$nullableType = !$isRequired ? '?' . $phpType : $phpType;
$defaultValue = !$isRequired ? ' = null' : '';
// 生成 OA\Property 注解
$annotation = " #[OA\\Property(\n";
$annotation .= " description: '{$columnComment}',\n";
$annotation .= " type: '{$this->getOpenApiType($columnType)}',\n";
$annotation .= " example: '{$this->getExampleValue($columnType)}',\n";
$annotation .= " nullable: " . ($isRequired ? 'false' : 'true') . "\n";
$annotation .= " )]\n";
// 生成 ValidationRules 注解
$rules = $this->generateValidationRules($column);
$annotation .= " #[ValidationRules(rules: '{$rules}')]\n";
// 生成字段声明
$annotation .= " public {$nullableType} $" . "{$columnName}{$defaultValue};\n\n";
return $annotation;
}
/**
* 获取 PHP 类型
* @param string $columnType 数据库字段类型
* @return string PHP 类型
*/
private function getPhpType(string $columnType): string
{
$typeMap = [
'int' => 'int',
'integer' => 'int',
'string' => 'string',
'varchar' => 'string',
'text' => 'string',
'boolean' => 'bool',
'bool' => 'bool',
'float' => 'float',
'double' => 'float',
'array' => 'array',
'json' => 'array',
];
return $typeMap[strtolower($columnType)] ?? 'string';
}
/**
* 获取 OpenAPI 类型
* @param string $columnType 数据库字段类型
* @return string OpenAPI 类型
*/
private function getOpenApiType(string $columnType): string
{
$typeMap = [
'int' => 'integer',
'integer' => 'integer',
'string' => 'string',
'varchar' => 'string',
'text' => 'string',
'boolean' => 'boolean',
'bool' => 'boolean',
'float' => 'number',
'double' => 'number',
'array' => 'array',
'json' => 'object',
];
return $typeMap[strtolower($columnType)] ?? 'string';
}
/**
* 获取示例值
* @param string $columnType 数据库字段类型
* @return string 示例值
*/
private function getExampleValue(string $columnType): string
{
$exampleMap = [
'int' => '1',
'integer' => '1',
'string' => '示例值',
'varchar' => '示例值',
'text' => '示例文本',
'boolean' => 'true',
'bool' => 'true',
'float' => '1.0',
'double' => '1.0',
'array' => '[]',
'json' => '{"key": "value"}',
];
return $exampleMap[strtolower($columnType)] ?? '示例值';
}
/**
* 生成验证规则
* @param array $column 字段信息
* @return string 验证规则
*/
private function generateValidationRules(array $column): string
{
$columnName = $column['column_name'];
$isRequired = isset($column['is_required']) && $column['is_required'];
$columnType = $column['column_type'] ?? 'string';
$rules = [];
// 必填规则
if ($isRequired) {
$rules[] = 'required';
} else {
$rules[] = 'nullable';
}
// 类型规则
switch (strtolower($columnType)) {
case 'int':
case 'integer':
$rules[] = 'integer';
break;
case 'float':
case 'double':
$rules[] = 'numeric';
break;
case 'boolean':
case 'bool':
$rules[] = 'boolean';
break;
case 'array':
$rules[] = 'array';
break;
default:
$rules[] = 'string';
break;
}
return implode('|', $rules);
}
/**
* 获取文件扩展名
* @return string 文件扩展名
*/
public function getFileExtension(): string
{
return 'php';
}
}
@@ -0,0 +1,255 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* DTO 生成器
* 负责生成 DTO 文件内容
*/
class RequestQueryGenerator implements FileGeneratorInterface
{
/**
* @var array 配置信息
*/
private array $config;
/**
* @var TemplateRenderer 模板渲染器
*/
private TemplateRenderer $templateRenderer;
/**
* 构造函数
*
* @param array $config 配置信息
*/
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
/**
* 生成文件内容
*
* @return string 文件内容
* @throws \Exception
*/
public function generateContent(): string
{
$template = $this->config['template'] ?? 'app';
$isPlugin = $template !== 'app';
$pluginName = $this->config['namespace'] ?? '';
// 生成命名空间
$packageName = $this->config['package_name'] ?? 'default';
if ($isPlugin) {
// 插件模式:plugin\{plugin_name}\app\schema\request\{package_name}
$namespace = "plugin\\{$pluginName}\\app\\schema\\request\\{$packageName}";
} else {
// App 模式:app\adminapi\schema\request\{package_name}
$namespace = "app\\adminapi\\schema\\request\\{$packageName}";
}
$data = [
'class_name' => $this->config['class_name'] ?? 'DefaultModel',
'package_name' => $this->config['package_name'] ?? 'default',
'columns' => $this->config['columns'] ?? [],
'namespace' => $namespace,
];
// 生成字段注解
$fields = '';
if (isset($data['columns']) && is_array($data['columns'])) {
foreach ($data['columns'] as $column) {
// 跳过主键字段
if (isset($column['is_pk']) && $column['is_pk']) {
continue;
}
// 生成字段注解
$fields .= $this->generateFieldAnnotation($column);
}
}
// 添加到数据中
$data['fields'] = $fields;
return $this->templateRenderer->render('server/schema/request/query.stub', $data);
}
/**
* 生成字段注解
*
* @param array $column 字段信息
*
* @return string 字段注解代码
*/
private function generateFieldAnnotation(array $column): string
{
$columnName = $column['column_name'];
$columnComment = $column['column_comment'];
$isRequired = isset($column['is_required']) && $column['is_required'];
$columnType = $column['column_type'] ?? 'string';
// 确定字段类型
$phpType = $this->getPhpType($columnType);
$nullableType = !$isRequired ? '?' . $phpType : $phpType;
$defaultValue = !$isRequired ? ' = null' : '';
// 生成 OA\Property 注解
$annotation = " #[OA\\Property(\n";
$annotation .= " description: '{$columnComment}',\n";
$annotation .= " type: '{$this->getOpenApiType($columnType)}',\n";
$annotation .= " example: '{$this->getExampleValue($columnType)}',\n";
$annotation .= " nullable: " . ($isRequired ? 'false' : 'true') . "\n";
$annotation .= " )]\n";
// 生成 ValidationRules 注解
$rules = $this->generateValidationRules($column);
$annotation .= " #[ValidationRules(rules: '{$rules}')]\n";
// 生成字段声明
$annotation .= " public {$nullableType} $" . "{$columnName}{$defaultValue};\n\n";
return $annotation;
}
/**
* 获取 PHP 类型
*
* @param string $columnType 数据库字段类型
*
* @return string PHP 类型
*/
private function getPhpType(string $columnType): string
{
$typeMap = [
'int' => 'int',
'integer' => 'int',
'string' => 'string',
'varchar' => 'string',
'text' => 'string',
'boolean' => 'bool',
'bool' => 'bool',
'float' => 'float',
'double' => 'float',
'array' => 'array',
'json' => 'array',
];
return $typeMap[strtolower($columnType)] ?? 'string';
}
/**
* 获取 OpenAPI 类型
*
* @param string $columnType 数据库字段类型
*
* @return string OpenAPI 类型
*/
private function getOpenApiType(string $columnType): string
{
$typeMap = [
'int' => 'integer',
'integer' => 'integer',
'string' => 'string',
'varchar' => 'string',
'text' => 'string',
'boolean' => 'boolean',
'bool' => 'boolean',
'float' => 'number',
'double' => 'number',
'array' => 'array',
'json' => 'object',
];
return $typeMap[strtolower($columnType)] ?? 'string';
}
/**
* 获取示例值
*
* @param string $columnType 数据库字段类型
*
* @return string 示例值
*/
private function getExampleValue(string $columnType): string
{
$exampleMap = [
'int' => '1',
'integer' => '1',
'string' => '示例值',
'varchar' => '示例值',
'text' => '示例文本',
'boolean' => 'true',
'bool' => 'true',
'float' => '1.0',
'double' => '1.0',
'array' => '[]',
'json' => '{"key": "value"}',
];
return $exampleMap[strtolower($columnType)] ?? '示例值';
}
/**
* 生成验证规则
*
* @param array $column 字段信息
*
* @return string 验证规则
*/
private function generateValidationRules(array $column): string
{
$columnName = $column['column_name'];
$isRequired = isset($column['is_required']) && $column['is_required'];
$columnType = $column['column_type'] ?? 'string';
$rules = [];
// 必填规则
if ($isRequired) {
$rules[] = 'required';
} else {
$rules[] = 'nullable';
}
// 类型规则
switch (strtolower($columnType)) {
case 'int':
case 'integer':
$rules[] = 'integer';
break;
case 'float':
case 'double':
$rules[] = 'numeric';
break;
case 'boolean':
case 'bool':
$rules[] = 'boolean';
break;
case 'array':
$rules[] = 'array';
break;
default:
$rules[] = 'string';
break;
}
return implode('|', $rules);
}
/**
* 获取文件扩展名
*
* @return string 文件扩展名
*/
public function getFileExtension(): string
{
return 'php';
}
}
@@ -0,0 +1,237 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* Schema 生成器
* 负责生成 Schema 文件内容
*/
class ResponseGenerator implements FileGeneratorInterface
{
/**
* @var array 配置信息
*/
private array $config;
/**
* @var TemplateRenderer 模板渲染器
*/
private TemplateRenderer $templateRenderer;
/**
* 构造函数
* @param array $config 配置信息
*/
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
/**
* 生成文件内容
* @return string 文件内容
*/
public function generateContent(): string
{
$template = $this->config['template'] ?? 'app';
$isPlugin = $template !== 'app';
$pluginName = $this->config['namespace'] ?? '';
// 生成命名空间
$packageName = $this->config['package_name'] ?? 'default';
if ($isPlugin) {
// 插件模式:plugin\{plugin_name}\app\schema\response\{package_name}
$namespace = "plugin\\{$pluginName}\\app\\schema\\response\\{$packageName}";
} else {
// App 模式:app\adminapi\\schema\{package_name}
$namespace = "app\\adminapi\\schema\\response\\{$packageName}";
}
$data = [
'class_name' => $this->config['class_name'] ?? 'DefaultModel',
'package_name' => $this->config['package_name'] ?? 'default',
'columns' => $this->config['columns'] ?? [],
'namespace' => $namespace,
];
// 生成字段注解
$fields = '';
if (isset($data['columns']) && is_array($data['columns'])) {
foreach ($data['columns'] as $column) {
// 跳过主键字段
if (isset($column['is_pk']) && $column['is_pk']) {
continue;
}
// 生成字段注解
$fields .= $this->generateFieldAnnotation($column);
}
}
// 添加到数据中
$data['fields'] = $fields;
return $this->templateRenderer->render('server/schema/response/schema.stub', $data);
}
/**
* 生成字段注解
* @param array $column 字段信息
* @return string 字段注解代码
*/
private function generateFieldAnnotation(array $column): string
{
$columnName = $column['column_name'];
$columnComment = $column['column_comment'];
$isRequired = isset($column['is_required']) && $column['is_required'];
$columnType = $column['column_type'] ?? 'string';
// 确定字段类型
$phpType = $this->getPhpType($columnType);
$nullableType = !$isRequired ? '?' . $phpType : $phpType;
$defaultValue = !$isRequired ? ' = null' : '';
// 生成 OA\Property 注解
$annotation = " #[OA\Property(\n";
$annotation .= " description: '{$columnComment}',\n";
$annotation .= " type: '{$this->getOpenApiType($columnType)}',\n";
$annotation .= " example: '{$this->getExampleValue($columnType)}',\n";
$annotation .= " nullable: " . ($isRequired ? 'false' : 'true') . "\n";
$annotation .= " )]\n";
// 生成字段声明(Schema定义不需要验证规则)
$annotation .= " public {$nullableType} $" . "{$columnName}{$defaultValue};\n\n";
return $annotation;
}
/**
* 获取 PHP 类型
* @param string $columnType 数据库字段类型
* @return string PHP 类型
*/
private function getPhpType(string $columnType): string
{
$typeMap = [
'int' => 'int',
'integer' => 'int',
'string' => 'string',
'varchar' => 'string',
'text' => 'string',
'boolean' => 'bool',
'bool' => 'bool',
'float' => 'float',
'double' => 'float',
'array' => 'array',
'json' => 'array',
];
return $typeMap[strtolower($columnType)] ?? 'string';
}
/**
* 获取 OpenAPI 类型
* @param string $columnType 数据库字段类型
* @return string OpenAPI 类型
*/
private function getOpenApiType(string $columnType): string
{
$typeMap = [
'int' => 'integer',
'integer' => 'integer',
'string' => 'string',
'varchar' => 'string',
'text' => 'string',
'boolean' => 'boolean',
'bool' => 'boolean',
'float' => 'number',
'double' => 'number',
'array' => 'array',
'json' => 'object',
];
return $typeMap[strtolower($columnType)] ?? 'string';
}
/**
* 获取示例值
* @param string $columnType 数据库字段类型
* @return string 示例值
*/
private function getExampleValue(string $columnType): string
{
$exampleMap = [
'int' => '1',
'integer' => '1',
'string' => '示例值',
'varchar' => '示例值',
'text' => '示例文本',
'boolean' => 'true',
'bool' => 'true',
'float' => '1.0',
'double' => '1.0',
'array' => '[]',
'json' => '{"key": "value"}',
];
return $exampleMap[strtolower($columnType)] ?? '示例值';
}
/**
* 生成验证规则
* @param array $column 字段信息
* @return string 验证规则
*/
private function generateValidationRules(array $column): string
{
$columnName = $column['column_name'];
$isRequired = isset($column['is_required']) && $column['is_required'];
$columnType = $column['column_type'] ?? 'string';
$rules = [];
// 必填规则
if ($isRequired) {
$rules[] = 'required';
} else {
$rules[] = 'nullable';
}
// 类型规则
switch (strtolower($columnType)) {
case 'int':
case 'integer':
$rules[] = 'integer';
break;
case 'float':
case 'double':
$rules[] = 'numeric';
break;
case 'boolean':
case 'bool':
$rules[] = 'boolean';
break;
case 'array':
$rules[] = 'array';
break;
default:
$rules[] = 'string';
break;
}
return implode('|', $rules);
}
/**
* 获取文件扩展名
* @return string 文件扩展名
*/
public function getFileExtension(): string
{
return 'php';
}
}
@@ -0,0 +1,81 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* 服务生成器
* 负责生成服务文件内容
*/
class ServiceGenerator implements FileGeneratorInterface
{
/**
* @var array 配置信息
*/
private array $config;
/**
* @var TemplateRenderer 模板渲染器
*/
private TemplateRenderer $templateRenderer;
/**
* 构造函数
* @param array $config 配置信息
*/
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
/**
* 生成文件内容
* @return string 文件内容
*/
public function generateContent(): string
{
$template = $this->config['template'] ?? 'app';
$isPlugin = $template !== 'app';
$pluginName = $this->config['namespace'] ?? '';
// 生成命名空间
$packageName = $this->config['package_name'] ?? 'default';
if ($isPlugin) {
// 插件模式:plugin\{plugin_name}\app\service\{package_name}
$namespace = "plugin\\{$pluginName}\\app\\service\\{$packageName}";
} else {
// App 模式:app\service\admin\{package_name}
$namespace = "app\\service\\admin\\{$packageName}";
}
// 生成 DAO 命名空间
if ($isPlugin) {
$daoNamespace = "plugin\\{$pluginName}\\app\\dao\\{$packageName}";
} else {
$daoNamespace = "app\\dao\\{$packageName}";
}
$data = [
'class_name' => $this->config['class_name'] ?? 'DefaultModel',
'package_name' => $this->config['package_name'] ?? 'default',
'table_content' => $this->config['table_content'] ?? '默认模型',
'camel_class_name' => lcfirst($this->config['class_name'] ?? 'DefaultModel'),
'namespace' => $namespace,
'dao_namespace' => $daoNamespace,
];
return $this->templateRenderer->render('server/service/service.stub', $data);
}
/**
* 获取文件扩展名
* @return string 文件扩展名
*/
public function getFileExtension(): string
{
return 'php';
}
}
@@ -0,0 +1,222 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* 验证器生成器
* 负责生成验证器文件内容
*/
class ValidateGenerator implements FileGeneratorInterface
{
/**
* @var array 配置信息
*/
private array $config;
/**
* @var TemplateRenderer 模板渲染器
*/
private TemplateRenderer $templateRenderer;
/**
* 构造函数
* @param array $config 配置信息
*/
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
/**
* 生成文件内容
* @return string 文件内容
*/
public function generateContent(): string
{
$template = $this->config['template'] ?? 'app';
$isPlugin = $template !== 'app';
$pluginName = $this->config['namespace'] ?? '';
// 生成命名空间
$packageName = $this->config['package_name'] ?? 'default';
if ($isPlugin) {
// 插件模式:plugin\{plugin_name}\app\validate\{package_name}
$namespace = "plugin\\{$pluginName}\\app\\validate\\{$packageName}";
} else {
// App 模式:app\adminapi\validate\{package_name}
$namespace = "app\\adminapi\\validate\\{$packageName}";
}
$data = [
'class_name' => $this->config['class_name'] ?? 'DefaultModel',
'package_name' => $this->config['package_name'] ?? 'default',
'columns' => $this->config['columns'] ?? [],
'namespace' => $namespace,
];
// 生成场景字段
$storeFields = [];
$updateFields = [];
$rules = [];
$messages = [];
if (isset($data['columns']) && is_array($data['columns'])) {
foreach ($data['columns'] as $column) {
$columnName = $column['column_name'];
$columnComment = $column['column_comment'];
$isRequired = isset($column['is_required']) && $column['is_required'];
$isInsert = isset($column['is_insert']) && $column['is_insert'];
$isUpdate = isset($column['is_update']) && $column['is_update'];
$columnType = $column['column_type'] ?? 'string';
// 生成验证规则
$validationRule = $this->generateValidationRule($column);
if (!empty($validationRule)) {
$rules[] = "'{$columnName}' => '{$validationRule}'";
// 生成错误信息
$errorMessages = $this->generateErrorMessage($column);
foreach ($errorMessages as $rule => $message) {
$messages[] = "'{$columnName}.{$rule}' => '{$message}'";
}
// 添加到场景
$isPk = isset($column['is_pk']) && $column['is_pk'];
if ($isInsert && !$isPk) {
$storeFields[] = "'{$columnName}'";
}
if ($isUpdate) {
$updateFields[] = "'{$columnName}'";
}
}
}
}
// 添加到数据中
$data['store_fields'] = implode(",\n ", $storeFields);
$data['update_fields'] = implode(",\n ", $updateFields);
$data['rules'] = implode(",\n ", $rules);
$data['messages'] = implode(",\n ", $messages);
return $this->templateRenderer->render('server/validate/validation.stub', $data);
}
/**
* 生成验证规则
* @param array $column 字段信息
* @return string 验证规则
*/
private function generateValidationRule(array $column): string
{
$isRequired = isset($column['is_required']) && $column['is_required'];
$columnType = $column['column_type'] ?? 'string';
$isPk = isset($column['is_pk']) && $column['is_pk'];
$rules = [];
// 必填规则
if ($isRequired) {
$rules[] = 'required';
}
// 类型规则
switch (strtolower($columnType)) {
case 'int':
case 'integer':
// 主键字段支持int和string两种类型(如雪花ID)
if ($isPk) {
$rules[] = 'integer|string';
} else {
$rules[] = 'integer';
}
break;
case 'float':
case 'double':
$rules[] = 'numeric';
break;
case 'boolean':
case 'bool':
$rules[] = 'boolean';
break;
case 'array':
$rules[] = 'array';
break;
case 'email':
$rules[] = 'email';
break;
default:
$rules[] = 'string';
break;
}
return implode('|', $rules);
}
/**
* 生成错误信息
* @param array $column 字段信息
* @return array 错误信息
*/
private function generateErrorMessage(array $column): array
{
$columnName = $column['column_name'];
$columnComment = $column['column_comment'];
$isRequired = isset($column['is_required']) && $column['is_required'];
$columnType = $column['column_type'] ?? 'string';
$messages = [];
// 必填错误信息
if ($isRequired) {
$messages['required'] = "{$columnComment}必须填写";
}
$isPk = isset($column['is_pk']) && $column['is_pk'];
// 类型错误信息
switch (strtolower($columnType)) {
case 'int':
case 'integer':
// 主键字段支持int和string两种类型(如雪花ID)
if ($isPk) {
$messages['integer'] = "{$columnComment}必须是整数或字符串";
$messages['string'] = "{$columnComment}必须是整数或字符串";
} else {
$messages['integer'] = "{$columnComment}必须是整数";
}
break;
case 'float':
case 'double':
$messages['numeric'] = "{$columnComment}必须是数字";
break;
case 'boolean':
case 'bool':
$messages['boolean'] = "{$columnComment}必须是布尔值";
break;
case 'array':
$messages['array'] = "{$columnComment}必须是数组";
break;
case 'email':
$messages['email'] = "{$columnComment}格式不正确";
break;
default:
$messages['string'] = "{$columnComment}必须是字符串";
break;
}
return $messages;
}
/**
* 获取文件扩展名
* @return string 文件扩展名
*/
public function getFileExtension(): string
{
return 'php';
}
}
@@ -0,0 +1,78 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* 视图生成器
* 负责生成前端视图文件内容
*/
class ViewGenerator implements FileGeneratorInterface
{
private array $config;
private TemplateRenderer $templateRenderer;
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
public function generateContent(): string
{
$className = $this->config['class_name'] ?? 'DefaultModel';
$moduleName = $this->config['package_name'] ?? 'default';
$dummyClassName = strtolower(preg_replace('/([a-z0-9])([A-Z])/', '$1_$2', $className));
$serviceName = $className . 'Service';
$kebabModuleName = str_replace('_', '-', $moduleName);
$kebabClassName = strtolower(preg_replace('/([a-z0-9])([A-Z])/', '$1-$2', $className));
$template = $this->config['template'] ?? 'app';
$isPlugin = $template !== 'app';
$pluginName = $this->config['namespace'] ?? '';
// 生成 API import 路径
if ($isPlugin) {
// 插件模式: @/apps/{plugin}/api/{kebab_module_name}
$apiImportPath = '@/apps/' . $pluginName . '/api/' . $kebabModuleName;
} else {
// 应用模式: @/api/{kebab_module_name}
$apiImportPath = '@/api/' . $kebabModuleName;
}
$langKey = $this->generateLangKey($moduleName, $className);
$langImportPath = $this->generateLangImportPath($moduleName);
$content = $this->templateRenderer->render('admin/views/index.stub', [
'module_name' => $moduleName,
'class_name' => $className,
'dummy_class_name' => $dummyClassName,
'service_name' => $serviceName,
'kebab_module_name' => $kebabModuleName,
'kebab_class_name' => $kebabClassName,
'api_import_path' => $apiImportPath,
'lang_key' => $langKey,
'lang_import_path' => $langImportPath,
]);
return $content;
}
private function generateLangKey(string $moduleName, string $className): string
{
$moduleKey = strtolower(str_replace('-', '_', $moduleName));
$classKey = strtolower(preg_replace('/([a-z0-9])([A-Z])/', '$1_$2', $className));
return "{$moduleKey}_{$classKey}";
}
private function generateLangImportPath(string $moduleName): string
{
return "@/lang/{$moduleName}";
}
public function getFileExtension(): string
{
return 'vue';
}
}
@@ -0,0 +1,280 @@
<?php
namespace core\generator\file;
use core\generator\interfaces\FileGeneratorInterface;
use core\generator\utils\TemplateRenderer;
/**
* 视图 Schema 生成器
* 负责生成前端视图 Schema 文件内容
*/
class ViewSchemaGenerator implements FileGeneratorInterface
{
private array $config;
private TemplateRenderer $templateRenderer;
public function __construct(array $config)
{
$this->config = $config;
$this->templateRenderer = new TemplateRenderer();
}
public function generateContent(): string
{
$className = $this->config['class_name'] ?? 'DefaultModel';
$moduleName = $this->config['package_name'] ?? 'default';
$dummyClassName = strtolower(preg_replace('/([a-z0-9])([A-Z])/', '$1_$2', $className));
$serviceName = $className . 'Service';
$kebabModuleName = str_replace('_', '-', $moduleName);
$columns = $this->config['columns'] ?? [];
$template = $this->config['template'] ?? 'app';
$isPlugin = $template !== 'app';
$pluginName = $this->config['namespace'] ?? '';
// 生成 API import 路径
if ($isPlugin) {
// 插件模式: @/apps/{plugin}/api/{kebab_module_name}
$apiImportPath = '@/apps/' . $pluginName . '/api/' . $kebabModuleName;
} else {
// 应用模式: @/api/{kebab_module_name}
$apiImportPath = '@/api/' . $kebabModuleName;
}
$langKey = $this->generateLangKey($moduleName, $className);
$langImportPath = $this->generateLangImportPath($moduleName);
$tableColumns = $this->processTableColumns($columns, $langKey);
$searchFormSchema = $this->processSearchFormSchema($columns, $langKey);
$formSchema = $this->processFormSchema($columns, $langKey);
$dialogType = '';
if (isset($this->config['config']['edit_type']) && $this->config['config']['edit_type'] == 2) {
$dialogType = 'dialogType: "drawer"';
}
$dialogWidth = $this->config['config']['dialog_width'] ?? '50%';
$content = $this->templateRenderer->render('admin/views/schemas/index.stub', [
'class_name' => $className,
'module_name' => $moduleName,
'dummy_class_name' => $dummyClassName,
'service_name' => $serviceName,
'kebab_module_name' => $kebabModuleName,
'api_import_path' => $apiImportPath,
'lang_key' => $langKey,
'lang_import_path' => $langImportPath,
'table_columns' => $tableColumns,
'search_form_schema' => $searchFormSchema,
'form_schema' => $formSchema,
'use_crud' => isset($this->config['config']['use_crud']) ? (bool)$this->config['config']['use_crud'] : true,
'has_add' => isset($this->config['config']['has_add']) ? (bool)$this->config['config']['has_add'] : true,
'has_remove' => isset($this->config['config']['has_remove']) ? (bool)$this->config['config']['has_remove'] : true,
'has_edit' => isset($this->config['config']['has_edit']) ? (bool)$this->config['config']['has_edit'] : true,
'has_view' => isset($this->config['config']['has_view']) ? (bool)$this->config['config']['has_view'] : false,
'dialog_type' => $dialogType,
'dialog_width' => $dialogWidth,
]);
return $content;
}
private function generateLangKey(string $moduleName, string $className): string
{
$classKey = strtolower(preg_replace('/([a-z0-9])([A-Z])/', '$1_$2', $className));
$kebabModuleName = strtolower(str_replace('_', '-', $moduleName));
return "{$kebabModuleName}.{$classKey}";
}
private function generateLangImportPath(string $moduleName): string
{
return "@/lang/{$moduleName}";
}
private function processTableColumns(array $columns, string $langKey): string
{
$result = [];
foreach ($columns as $column) {
if (isset($column['is_lists']) && $column['is_lists'] == 1) {
$tableItem = [
'prop' => $column['column_name'],
'label' => '$t(\'' . $langKey . '.list.' . $column['column_name'] . '\')'
];
if(isset($column['view_type']) && $column['view_type'] == 'ApiDict') {
$tableItem['component'] = 'ApiDict';
$tableItem['componentProps'] = [
'code' => $column['dict_type'],
];
}
$result[] = $this->arrayToCode($tableItem);
}
}
return implode(",\n ", $result);
}
private function arrayToCode(array $array): string
{
$items = [];
foreach ($array as $key => $value) {
if (is_array($value)) {
$items[] = $key . ': ' . $this->arrayToCode($value);
} elseif (is_bool($value)) {
$items[] = $key . ': ' . ($value ? 'true' : 'false');
} elseif (is_int($value) || is_float($value)) {
$items[] = $key . ': ' . $value;
} elseif (strpos($value, '$t(') === 0 || strpos($value, '[') === 0) {
$items[] = $key . ': ' . $value;
} else {
$items[] = $key . ': "' . $value . '"';
}
}
return '{' . implode(', ', $items) . '}';
}
private function processSearchFormSchema(array $columns, string $langKey): string
{
$result = [];
foreach ($columns as $column) {
if (isset($column['is_search']) && $column['is_search'] == 1) {
$prop = $column['column_name'];
if (strpos(strtoupper($prop), 'LIKE_') === 0) {
$prop = substr($prop, 5);
} elseif (strpos(strtoupper($prop), 'EQ_') === 0) {
$prop = substr($prop, 3);
}
$searchItem = [
'component' => $this->getComponent($column),
'prop' => $prop,
'label' => '$t(\'' . $langKey . '.search.' . $prop . '\')',
'componentProps' => [
'placeholder' => '$t(\'' . $langKey . '.search.' . $prop . '\')'
],
'colSpan' => 6
];
if (isset($column['label_key']) && $column['label_key']) {
$searchItem['labelKey'] = $column['label_key'];
}
if (isset($column['value_key']) && $column['value_key']) {
$searchItem['valueKey'] = $column['value_key'];
}
if (isset($column['api']) && $column['api']) {
$searchItem['componentProps']['api'] = $column['api'];
}
if (isset($column['dict_type']) && $column['dict_type']) {
$searchItem['componentProps']['code'] = $column['dict_type'];
}
$result[] = $this->arrayToCode($searchItem);
}
}
return implode(",\n ", $result);
}
private function processFormSchema(array $columns, string $langKey): string
{
$result = [];
foreach ($columns as $column) {
if (isset($column['is_pk']) && $column['is_pk'] == 1) {
$item = [
'label' => '$t(\'' . $langKey . '.form.' . $column['column_name'] . '\')',
'prop' => $column['column_name'],
'component' => $this->getComponent($column),
'colSpan' => 24,
'show' => false
];
$result[] = $this->arrayToCode($item);
continue;
}
if ((isset($column['is_insert']) && $column['is_insert'] == 1) || (isset($column['is_update']) && $column['is_update'] == 1)) {
$item = [
'label' => '$t(\'' . $langKey . '.form.' . $column['column_name'] . '\')',
'prop' => $column['column_name'],
'component' => $this->getComponent($column),
'colSpan' => 24
];
if (isset($column['show']) && $column['show'] == 1) {
$item['show'] = true;
}
if (isset($column['ifDetail']) && $column['ifDetail'] == 1) {
$item['ifDetail'] = true;
}
if (isset($column['validate_type']) && $column['validate_type']) {
$item['rules'] = $this->getValidationRules($column['validate_type']);
}
if (isset($column['label_key']) && $column['label_key']) {
$item['labelKey'] = $column['label_key'];
}
if (isset($column['value_key']) && $column['value_key']) {
$item['valueKey'] = $column['value_key'];
}
if (isset($column['api']) && $column['api']) {
$item['componentProps'] = [
'api' => $column['api']
];
}
if (isset($column['dict_type']) && $column['dict_type']) {
if (!isset($item['componentProps'])) {
$item['componentProps'] = [];
}
$item['componentProps']['code'] = $column['dict_type'];
}
$result[] = $this->arrayToCode($item);
}
}
return implode(",\n ", $result);
}
private function getComponent(array $column): string
{
if (isset($column['dict_type']) && $column['dict_type']) {
return 'ApiDict';
}
if (isset($column['view_type']) && $column['view_type']) {
$viewType = $column['view_type'];
return $viewType;
}
return 'Input';
}
private function getValidationRules(string $validateType): string
{
$rules = [];
$validateTypes = explode(',', $validateType);
foreach ($validateTypes as $type) {
switch (trim($type)) {
case 'required':
$rules[] = '{"required":true,"message":"此项为必填项","trigger":"blur"}';
break;
case 'email':
$rules[] = '{"type":"email","message":"请输入有效的邮箱地址","trigger":"blur"}';
break;
case 'url':
$rules[] = '{"type":"url","message":"请输入有效的URL地址","trigger":"blur"}';
break;
case 'number':
$rules[] = '{"type":"number","message":"请输入数字","trigger":"blur"}';
break;
}
}
return '[' . implode(',', $rules) . ']';
}
public function getFileExtension(): string
{
return 'tsx';
}
}