初始化-安装依赖

This commit is contained in:
2026-03-03 10:06:12 +08:00
parent 3f349a35a4
commit ec8cac4221
187 changed files with 26292 additions and 0 deletions

View File

@@ -0,0 +1,289 @@
<?php
// +----------------------------------------------------------------------
// | saiadmin [ saiadmin快速开发框架 ]
// +----------------------------------------------------------------------
// | Author: sai <1430792918@qq.com>
// +----------------------------------------------------------------------
namespace plugin\saiadmin\utils\code;
use Twig\TwigFilter;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
use plugin\saiadmin\exception\ApiException;
// 定义目录分隔符常量
defined('DS') or define('DS', DIRECTORY_SEPARATOR);
/**
* 代码生成引擎
*/
class CodeEngine
{
/**
* @var array 值栈
*/
private array $value = [];
/**
* 模板名称
* @var string
*/
private string $stub = 'saiadmin';
/**
* 获取配置文件
* @return string[]
*/
private static function _getConfig(): array
{
return [
'template_path' => base_path() . DS . 'plugin' . DS . 'saiadmin' . DS . 'utils' . DS . 'code' . DS . 'stub',
'generate_path' => runtime_path() . DS . 'code_engine' . DS . 'saiadmin',
];
}
/**
* 初始化
* @param array $data 数据
*/
public function __construct(array $data)
{
// 读取配置文件
$config = self::_getConfig();
// 判断模板是否存在
if (!is_dir($config['template_path'])) {
throw new ApiException('模板目录不存在!');
}
// 判断文件生成目录是否存在
if (!is_dir($config['generate_path'])) {
mkdir($config['generate_path'], 0770, true);
}
// 赋值
$this->value = $data;
}
/**
* 设置模板名称
* @param $stub
* @return void
*/
public function setStub($stub): void
{
$this->stub = $stub;
}
/**
* 渲染文件内容
*/
public function renderContent($path, $filename): string
{
$config = self::_getConfig();
$path = $config['template_path'] . DS . $this->stub . DS . $path;
$loader = new FilesystemLoader($path);
$twig = new Environment($loader);
$camelFilter = new TwigFilter('camel', function ($value) {
static $cache = [];
$key = $value;
if (isset($cache[$key])) {
return $cache[$key];
}
$value = ucwords(str_replace(['-', '_'], ' ', $value));
return $cache[$key] = str_replace(' ', '', $value);
});
$boolFilter = new TwigFilter('bool', function ($value) {
if ($value == 1) {
return 'true';
} else {
return 'false';
}
});
$formatFilter = new TwigFilter('formatNumber', function ($value) {
if (ctype_digit((string) $value)) {
return $value;
} else {
return '1';
}
});
$defaultFilter = new TwigFilter('parseNumber', function ($value) {
if ($value) {
return $value;
} else {
return 'null';
}
});
$containsFilter = new TwigFilter('str_contains', function ($haystack, $needle) {
return str_contains($haystack ?? '', $needle ?? '');
});
$twig->addFilter($camelFilter);
$twig->addFilter($boolFilter);
$twig->addFilter($containsFilter);
$twig->addFilter($formatFilter);
$twig->addFilter($defaultFilter);
return $twig->render($filename, $this->value);
}
/**
* 生成后端文件
*/
public function generateBackend($action, $content): void
{
$outPath = '';
if ($this->value['template'] == 'app') {
$rootPath = base_path() . DS . 'app' . DS . $this->value['namespace'];
$adminPath = '';
} else {
$rootPath = base_path() . DS . 'plugin' . DS . $this->value['namespace'] . DS . 'app';
$adminPath = DS . 'admin';
}
$subPath = DS . $this->value['package_name'];
switch ($action) {
case 'controller':
$outPath = $rootPath . $adminPath . DS . 'controller' . $subPath . DS . $this->value['class_name'] . 'Controller.php';
break;
case 'logic':
$outPath = $rootPath . $adminPath . DS . 'logic' . $subPath . DS . $this->value['class_name'] . 'Logic.php';
break;
case 'validate':
$outPath = $rootPath . $adminPath . DS . 'validate' . $subPath . DS . $this->value['class_name'] . 'Validate.php';
break;
case 'model':
$outPath = $rootPath . DS . 'model' . $subPath . DS . $this->value['class_name'] . '.php';
break;
default:
break;
}
if (empty($outPath)) {
throw new ApiException('文件类型异常,无法生成指定文件!');
}
if (!is_dir(dirname($outPath))) {
mkdir(dirname($outPath), 0777, true);
}
file_put_contents($outPath, $content);
}
/**
* 生成前端文件
*/
public function generateFrontend($action, $content): void
{
$rootPath = dirname(base_path()) . DS . $this->value['generate_path'];
if (!is_dir($rootPath)) {
throw new ApiException('前端目录查找失败,必须与后端目录为同级目录!');
}
$rootPath = $rootPath . DS . 'src' . DS . 'views' . DS . 'plugin' . DS . $this->value['namespace'];
$subPath = DS . $this->value['package_name'];
switch ($action) {
case 'index':
$outPath = $rootPath . $subPath . DS . $this->value['business_name'] . DS . 'index.vue';
break;
case 'edit-dialog':
$outPath = $rootPath . $subPath . DS . $this->value['business_name'] . DS . 'modules' . DS . 'edit-dialog.vue';
break;
case 'table-search':
$outPath = $rootPath . $subPath . DS . $this->value['business_name'] . DS . 'modules' . DS . 'table-search.vue';
break;
case 'api':
$outPath = $rootPath . DS . 'api' . $subPath . DS . $this->value['business_name'] . '.ts';
break;
default:
break;
}
if (empty($outPath)) {
throw new ApiException('文件类型异常,无法生成指定文件!');
}
if (!is_dir(dirname($outPath))) {
mkdir(dirname($outPath), 0777, true);
}
file_put_contents($outPath, $content);
}
/**
* 生成临时文件
*/
public function generateTemp(): void
{
$config = self::_getConfig();
$rootPath = $config['generate_path'];
$vuePath = $rootPath . DS . 'vue' . DS . 'src' . DS . 'views' . DS . 'plugin' . DS . $this->value['namespace'];
$phpPath = $rootPath . DS . 'php';
$sqlPath = $rootPath . DS . 'sql';
if ($this->value['template'] == 'app') {
$phpPath = $phpPath . DS . 'app' . DS . $this->value['namespace'];
$adminPath = '';
} else {
$phpPath = $phpPath . DS . 'plugin' . DS . $this->value['namespace'] . DS . 'app';
$adminPath = DS . 'admin';
}
$subPath = DS . $this->value['package_name'];
$indexOutPath = $vuePath . $subPath . DS . $this->value['business_name'] . DS . 'index.vue';
$this->checkPath($indexOutPath);
$indexContent = $this->renderContent('vue', 'index.stub');
file_put_contents($indexOutPath, $indexContent);
$editOutPath = $vuePath . $subPath . DS . $this->value['business_name'] . DS . 'modules' . DS . 'edit-dialog.vue';
$this->checkPath($editOutPath);
$editContent = $this->renderContent('vue', 'edit-dialog.stub');
file_put_contents($editOutPath, $editContent);
$searchOutPath = $vuePath . $subPath . DS . $this->value['business_name'] . DS . 'modules' . DS . 'table-search.vue';
$this->checkPath($searchOutPath);
$searchContent = $this->renderContent('vue', 'table-search.stub');
file_put_contents($searchOutPath, $searchContent);
$viewOutPath = $vuePath . DS . 'api' . $subPath . DS . $this->value['business_name'] . '.ts';
$this->checkPath($viewOutPath);
$viewContent = $this->renderContent('ts', 'api.stub');
file_put_contents($viewOutPath, $viewContent);
$controllerOutPath = $phpPath . $adminPath . DS . 'controller' . $subPath . DS . $this->value['class_name'] . 'Controller.php';
$this->checkPath($controllerOutPath);
$controllerContent = $this->renderContent('php', 'controller.stub');
file_put_contents($controllerOutPath, $controllerContent);
$logicOutPath = $phpPath . $adminPath . DS . 'logic' . $subPath . DS . $this->value['class_name'] . 'Logic.php';
$this->checkPath($logicOutPath);
$logicContent = $this->renderContent('php', 'logic.stub');
file_put_contents($logicOutPath, $logicContent);
$validateOutPath = $phpPath . $adminPath . DS . 'validate' . $subPath . DS . $this->value['class_name'] . 'Validate.php';
$this->checkPath($validateOutPath);
$validateContent = $this->renderContent('php', 'validate.stub');
file_put_contents($validateOutPath, $validateContent);
$modelOutPath = $phpPath . DS . 'model' . $subPath . DS . $this->value['class_name'] . '.php';
$this->checkPath($modelOutPath);
$modelContent = $this->renderContent('php', 'model.stub');
file_put_contents($modelOutPath, $modelContent);
$sqlOutPath = $sqlPath . DS . 'sql.sql';
$this->checkPath($sqlOutPath);
$sqlContent = $this->renderContent('sql', 'sql.stub');
file_put_contents($sqlOutPath, $sqlContent);
}
/**
* 检查并生成路径
* @param $path
* @return void
*/
protected function checkPath($path): void
{
if (!is_dir(dirname($path))) {
mkdir(dirname($path), 0777, true);
}
}
}