From 2f2a0750466798e158166a22dbb3fb1e86653a2d Mon Sep 17 00:00:00 2001 From: liaofei <136327134@qq.com> Date: Thu, 13 Apr 2023 17:05:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/v1/setting/SystemCrud.php | 68 ++++-- .../services/system/SystemCrudServices.php | 91 +++++--- crmeb/config/console.php | 3 +- crmeb/crmeb/command/Crud.php | 20 -- crmeb/crmeb/command/Npm.php | 46 ++++ crmeb/crmeb/command/Util.php | 13 +- crmeb/crmeb/utils/Terminal.php | 208 ++++++++++++++++++ 7 files changed, 381 insertions(+), 68 deletions(-) delete mode 100644 crmeb/crmeb/command/Crud.php create mode 100644 crmeb/crmeb/utils/Terminal.php diff --git a/crmeb/app/adminapi/controller/v1/setting/SystemCrud.php b/crmeb/app/adminapi/controller/v1/setting/SystemCrud.php index 376988034..f22e12e57 100644 --- a/crmeb/app/adminapi/controller/v1/setting/SystemCrud.php +++ b/crmeb/app/adminapi/controller/v1/setting/SystemCrud.php @@ -67,14 +67,29 @@ class SystemCrud extends AuthController ['tableComment', ''],//表备注 ['tableField', []],//表字段 ['tableIndex', []],//索引 - ['tableTime', 0],//表是否增加修改和添加时间 - ['tableDelete', 0],//表是否增加伪删除 - ['fromField', []], - ['columnField', []], ['filePath', []], ['isTable', 0], ]); + $fromField = $columnField = []; + foreach ($data['tableField'] as $item) { + if ($item['is_table']) { + $columnField[] = [ + 'field' => $item['field'], + 'name' => $item['table_name'], + ]; + } + if ($item['from_type']) { + $fromField[] = [ + 'field' => $item['field'], + 'name' => $item['table_name'], + 'required' => $item['required'], + 'option' => $item['option'] ?? [], + ]; + } + } + $data['fromField '] = $fromField; + $data['columnField '] = $columnField; if (!$data['tableName']) { return app('json')->fail('缺少表名'); } @@ -93,12 +108,9 @@ class SystemCrud extends AuthController */ public function getFilePath() { - [$menuName, $tableName, $isTable, $fromField, $columnField] = $this->request->postMore([ - ['menuName', ''], + [$tableName, $isTable] = $this->request->postMore([ ['tableName', ''], ['isTable', 0], - ['fromField', []], - ['columnField', []], ], true); if (!$tableName) { @@ -112,9 +124,9 @@ class SystemCrud extends AuthController $routeName = 'crud/' . Str::snake($tableName); $make = $this->services->makeFile($tableName, $routeName, false, [ - 'menuName' => $menuName, - 'fromField' => $fromField, - 'columnField' => $columnField, + 'menuName' => '', + 'fromField' => [], + 'columnField' => [], ]); $makePath = []; @@ -129,7 +141,17 @@ class SystemCrud extends AuthController return app('json')->fail('表不存在'); } foreach ($field as $item) { - $tableField[] = ['value' => $item['name'], 'all' => $item, 'comment' => $item['comment'], 'label' => $item['name']]; + $tableField[] = [ + 'field' => $item['name'], + 'file_type' => $item['type'], + 'default' => $item['default'], + 'limit' => $item['limit'], + 'comment' => $item['comment'], + 'required' => false, + 'is_table' => false, + 'table_name' => '', + 'from_type' => '', + ]; } } @@ -164,12 +186,28 @@ class SystemCrud extends AuthController break; } } - + $fromField = $columnField = []; + foreach ($info->tableField as $item) { + if ($item['is_table']) { + $columnField[] = [ + 'field' => $item['field'], + 'name' => $item['table_name'], + ]; + } + if ($item['from_type']) { + $fromField[] = [ + 'field' => $item['field'], + 'name' => $item['table_name'], + 'required' => $item['required'], + 'option' => $item['option'] ?? [], + ]; + } + } $make = $this->services->makeFile($info->table_name, $routeName, false, [ 'menuName' => $info->name, 'key' => $key, - 'fromField' => $info->field['fromField'] ?? [], - 'columnField' => $info->field['columnField'] ?? [], + 'fromField' => $fromField, + 'columnField' => $columnField, ]); $data = []; diff --git a/crmeb/app/services/system/SystemCrudServices.php b/crmeb/app/services/system/SystemCrudServices.php index c387b7696..1801ce8f6 100644 --- a/crmeb/app/services/system/SystemCrudServices.php +++ b/crmeb/app/services/system/SystemCrudServices.php @@ -87,33 +87,62 @@ class SystemCrudServices extends BaseServices */ public function getTabelRule() { + $rule = [ + 'varchat' => 'string', + 'int' => 'integer', + 'biginteger' => 'bigint', + ]; return [ 'types' => [ - 'string', + 'varchar', 'char', 'text', - 'integer', - 'biginteger', - 'float', - 'decimal', + 'longtext', + 'tinytext', + 'enum', + 'blob', + 'binary', + 'varbinary', + 'datetime', 'timestamp', 'time', 'date', - 'blob', - 'binary', - 'varbinary', + 'year', + 'boolean', - 'uuid', - // Geospatial data types - 'geometry', - 'point', - 'linestring', - 'polygon', - ] + 'tinyint', + 'int', + 'decimal', + 'float', + + 'json', + + 'addTimestamps', + 'addSoftDelete', + ], + 'rule' => $rule ]; } + /** + * 改变数据库类型 + * @param string $type + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function changeTabelRule(string $type) + { + + if (!in_array($type, $this->getTabelRule()['type'])) { + throw new ValidateException('类型不在支持范围'); + } + + return $this->getTabelRule()['rule'][$type] ?? $type; + } + /** * 获取表字段 * @param string $tableName @@ -140,6 +169,7 @@ class SystemCrudServices extends BaseServices 'unsigned' => (bool)stripos($item['COLUMN_TYPE'], 'unsigned'), 'autoIncrement' => stripos($item['EXTRA'], 'auto_increment') !== false, 'comment' => $item['COLUMN_COMMENT'], + 'limit' => $item['CHARACTER_MAXIMUM_LENGTH'] ?: $item['NUMERIC_PRECISION'], ]; $columns[$item['COLUMN_NAME']] = $column; } @@ -199,7 +229,7 @@ class SystemCrudServices extends BaseServices if (!$column) { throw new ValidateException('请先创建' . $tableName . '表'); } - + //获取主键 foreach ($column as $value) { if ($value['primaryKey']) { $data['key'] = $value['name']; @@ -209,7 +239,7 @@ class SystemCrudServices extends BaseServices $routeName = 'crud/' . Str::snake($tableName); $uniqueAuth = Str::snake($tableName) . '-crud-list-index'; - + //增加保存的绝对路径 foreach ($filePath as $k => $i) { if (in_array($k, ['pages', 'router', 'api'])) { $filePath[$k] = Make::adminTemplatePath() . $i; @@ -300,13 +330,12 @@ class SystemCrudServices extends BaseServices ]; } app()->make(SystemMenusServices::class)->saveAll($menuData); - + //生成文件 $make = $this->makeFile($tableName, $routeName, true, $data, $filePath); $makePath = []; foreach ($make as $key => $item) { $makePath[$key] = $item['path']; } - //记录crud生成 $res = $this->dao->save([ 'pid' => $data['pid'], @@ -334,7 +363,7 @@ class SystemCrudServices extends BaseServices */ public function makeDatebase(string $tableName, string $tableComment, array $tableField = []) { - $migrator = app()->make(Migrator::class); + $migrator = app()->make(Migrator::class, [date('YmdHis')]); //创建表 $table = $migrator->table($tableName, $tableComment); //创建字段 @@ -346,12 +375,16 @@ class SystemCrudServices extends BaseServices if (!isset($item['default'])) { $option['default'] = $item['default']; } - $option['comment'] = $item['comment']; - $table->addColumn($item['field'], $item['type'], $option); - } - //创建修改和增加时间 - if (!empty($data['tableTime'])) { - $table->addTimestamps(); + //创建伪删除 + if ($item['type'] === 'addSoftDelete') { + $table->addSoftDelete(); + } else if ($item['type'] === 'addTimestamps') { + //创建修改和增加时间 + $table->addTimestamps(); + } else { + $option['comment'] = $item['comment']; + $table->addColumn($item['field'], $this->changeTabelRule($item['type']), $option); + } } //创建索引 if (!empty($data['tableIndex'])) { @@ -359,10 +392,6 @@ class SystemCrudServices extends BaseServices $table->addIndex($item); } } - //创建伪删除 - if (!empty($data['tableDelete'])) { - $table->addSoftDelete(); - } //执行创建 $table->create(); } @@ -385,7 +414,7 @@ class SystemCrudServices extends BaseServices $options['columnField'] = is_array($options['columnField']) ? $options['columnField'] : []; //生成模型 $model = app()->make(Model::class); - [$modelContent, $modelPath, $usePath] = $model->setFilePathName($filePath['model'] ?? '')->isMake($isMake)->handle($tableName); + [$modelContent, $modelPath, $usePath] = $model->setFilePathName($filePath['model'] ?? '')->isMake($isMake)->handle($tableName, $options); //生成dao $dao = app()->make(Dao::class); [$daoContent, $daoPath, $usePath] = $dao->setFilePathName($filePath['dao'] ?? '')->isMake($isMake)->handle($tableName, [ diff --git a/crmeb/config/console.php b/crmeb/config/console.php index a837ee506..ece59e882 100644 --- a/crmeb/config/console.php +++ b/crmeb/config/console.php @@ -19,6 +19,7 @@ return [ 'commands' => [ 'workerman' => \crmeb\command\Workerman::class, 'timer' => \crmeb\command\Timer::class, - 'util' => \crmeb\command\Util::class + 'util' => \crmeb\command\Util::class, + 'npm' => \crmeb\command\Npm::class ], ]; diff --git a/crmeb/crmeb/command/Crud.php b/crmeb/crmeb/command/Crud.php deleted file mode 100644 index e323371ea..000000000 --- a/crmeb/crmeb/command/Crud.php +++ /dev/null @@ -1,20 +0,0 @@ - - * +---------------------------------------------------------------------- - */ - -namespace crmeb\command\crud; - - -class Crud -{ - -} diff --git a/crmeb/crmeb/command/Npm.php b/crmeb/crmeb/command/Npm.php index 4c4b50261..fbc29b9f6 100644 --- a/crmeb/crmeb/command/Npm.php +++ b/crmeb/crmeb/command/Npm.php @@ -14,12 +14,26 @@ namespace crmeb\command; +use crmeb\services\FileService; +use crmeb\utils\Terminal; use think\console\Command; use think\console\input\Argument; use think\console\input\Option; +/** + * Class Npm + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + * @package crmeb\command + */ class Npm extends Command { + /** + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ protected function configure() { $this->setName('npm') @@ -29,8 +43,40 @@ class Npm extends Command ->setDescription('NPM打包工具'); } + /** + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ public function handle() { + $path = $this->input->getOption('path'); + $build = $this->input->getOption('build'); + $zip = $this->input->getOption('zip'); + if (!$build) { + $build = public_path() . 'admin'; + } + $terminal = new Terminal(); + $terminal->setOutput($this->output); + + $adminPath = $terminal->adminTemplatePath(); + + $adminPath = dirname($adminPath); + $dir = $adminPath . DS . 'node_modules'; + if (!is_dir($dir)) { + $terminal->run('npm-install'); + } + + $terminal->run('npm-build'); + + if (!is_dir($adminPath . DS . 'dist')) { + $this->output->error('打包失败'); + return; + } + + FileService::copyDir($adminPath . 'dist', $build); + + $this->output->info('执行成功'); } } diff --git a/crmeb/crmeb/command/Util.php b/crmeb/crmeb/command/Util.php index 9297033c1..44b044ed9 100644 --- a/crmeb/crmeb/command/Util.php +++ b/crmeb/crmeb/command/Util.php @@ -3,6 +3,7 @@ namespace crmeb\command; +use app\services\system\SystemRouteServices; use crmeb\exceptions\AdminException; use think\console\Command; use think\console\Input; @@ -17,9 +18,10 @@ class Util extends Command protected function configure() { $this->setName('util') - ->addArgument('type', Argument::REQUIRED, '类型replace') + ->addArgument('type', Argument::REQUIRED, '类型replace/route') ->addOption('h', null, Option::VALUE_REQUIRED, '替换成当前域名') ->addOption('u', null, Option::VALUE_REQUIRED, '替换的域名') + ->addOption('a', null, Option::VALUE_REQUIRED, '应用名') ->setDescription('工具类'); } @@ -39,6 +41,13 @@ class Util extends Command } $this->replaceSiteUrl($url, $host); break; + case 'route': + $appName = $input->getOption('a'); + if (!$appName) { + return $output->error('缺少应用名称'); + } + app()->make(SystemRouteServices::class)->syncRoute($appName); + break; } $output->info('执行成功'); @@ -47,7 +56,9 @@ class Util extends Command protected function replaceSiteUrl(string $url, string $siteUrl) { $siteUrlJosn = str_replace('http://', 'http:\\\/\\\/', $siteUrl); + $siteUrlJosn = str_replace('https://', 'https:\\\/\\\/', $siteUrlJosn); $valueJosn = str_replace('http://', 'http:\\\/\\\/', $url); + $valueJosn = str_replace('https://', 'https:\\\/\\\/', $valueJosn); $prefix = Config::get('database.connections.' . Config::get('database.default') . '.prefix'); $sql = [ "UPDATE `{$prefix}system_attachment` SET `att_dir` = replace(att_dir ,'{$siteUrl}','{$url}'),`satt_dir` = replace(satt_dir ,'{$siteUrl}','{$url}')", diff --git a/crmeb/crmeb/utils/Terminal.php b/crmeb/crmeb/utils/Terminal.php new file mode 100644 index 000000000..ad1dc306f --- /dev/null +++ b/crmeb/crmeb/utils/Terminal.php @@ -0,0 +1,208 @@ + + * +---------------------------------------------------------------------- + */ + +namespace crmeb\utils; + +use think\Response; +use think\console\Output; + +/** + * 执行命令 + * Class Terminal + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + * @package crmeb\utils + */ +class Terminal +{ + /** + * 命令 + * @var \string[][] + */ + protected $command = [ + 'npm-build' => [ + 'run_root' => '', + 'command' => 'npm run build', + ], + 'npm-install' => [ + 'run_root' => '', + 'command' => 'npm run install', + ], + ]; + + /** + * 执行内容保存地址 + * @var string + */ + protected $outputFile; + + /** + * 执行状态 + * @var integer + */ + protected $procStatus; + + /** + * 响应内容 + * @var string + */ + protected $outputContent; + + /** + * @var + */ + protected $output; + + /** + * Terminal constructor. + */ + public function __construct() + { + $this->command['npm-build']['run_root'] = str_replace('DS', DS, config('app.admin_template_path')); + $this->command['npm-install']['run_root'] = str_replace('DS', DS, config('app.admin_template_path')); + + $outputDir = root_path() . 'runtime' . DIRECTORY_SEPARATOR . 'terminal'; + $this->outputFile = $outputDir . DIRECTORY_SEPARATOR . 'exec.log'; + if (!is_dir($outputDir)) { + mkdir($outputDir, 0755, true); + } + file_put_contents($this->outputFile, ''); + } + + /** + * @param Output $output + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function setOutput(Output $output) + { + $this->output = $output; + } + + /** + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function adminTemplatePath() + { + return $this->command['npm-install']['run_root']; + } + + /** + * 执行 + * @param string $name + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function run(string $name) + { + if (!function_exists('proc_open')) { + throw new \RuntimeException('缺少proc_open函数无法运行'); + } + + if (!isset($this->command[$name])) { + throw new \RuntimeException('运行的命令不存在'); + } + + $command = $this->command[$name]; + + $descriptorspec = [0 => ['pipe', 'r'], 1 => ['file', $this->outputFile, 'w'], 2 => ['file', $this->outputFile, 'w']]; + $process = proc_open($command['command'], $descriptorspec, $pipes, $command['run_root'], null, ['suppress_errors' => true]); + if (is_resource($process)) { + while ($this->getProcStatus($process)) { + $contents = file_get_contents($this->outputFile); + if (strlen($contents) && $this->outputContent != $contents) { + $newOutput = str_replace($this->outputContent, '', $contents); + if (preg_match('/\r\n|\r|\n/', $newOutput)) { + $this->echoOutputFlag($newOutput); + $this->outputContent = $contents; + } + } + usleep(500000); + } + foreach ($pipes as $pipe) { + fclose($pipe); + } + proc_close($process); + } + + return $this->output('run success'); + } + + /** + * 判断状态 + * @param $process + * @return bool + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + public function getProcStatus($process): bool + { + $status = proc_get_status($process); + if ($status['running']) { + $this->procStatus = 1; + return true; + } elseif ($this->procStatus === 1) { + $this->procStatus = 0; + $this->output('exit: ' . $status['exitcode']); + if ($status['exitcode'] === 0) { + $this->echoOutputFlag('success'); + } else { + $this->echoOutputFlag('error'); + } + return true; + } else { + return false; + } + } + + /** + * 直接输入响应 + * @param string $message + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + protected function echoOutputFlag(string $message) + { + if ($this->output && $this->output instanceof Output) { + $this->output->info($message); + } else { + echo $this->output($message); + @ob_flush(); + } + } + + /** + * 返回响应内容 + * @param string $data + * @return string + * @author 等风来 + * @email 136327134@qq.com + * @date 2023/4/13 + */ + private function output($data) + { + $data = [ + 'data' => $data, + ]; + return Response::create($data, 'json')->getContent(); + } +}