mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-07-01 23:42:48 +08:00
197 lines
7.2 KiB
PHP
197 lines
7.2 KiB
PHP
<?php
|
||
|
||
namespace base\common\command;
|
||
|
||
use app\admin\service\curd\BuildCurdService;
|
||
use app\common\console\Command;
|
||
use app\common\tools\PathTools;
|
||
use think\console\Input;
|
||
use think\console\input\Option;
|
||
use think\console\Output;
|
||
use think\Exception;
|
||
use think\facade\App;
|
||
|
||
class CurdBase extends Command
|
||
{
|
||
protected function configure()
|
||
{
|
||
parent::configure();
|
||
|
||
$this->setName('curd')
|
||
->addOption('table', 't', Option::VALUE_REQUIRED, '主表名', null)
|
||
->addOption('controllerFilename', 'c', Option::VALUE_REQUIRED, '控制器文件名', null)
|
||
->addOption('modelFilename', 'm', Option::VALUE_REQUIRED, '主表模型文件名', null)
|
||
//
|
||
->addOption('force', 'f', Option::VALUE_NONE, '强制覆盖模式')
|
||
->addOption('delete', 'd', Option::VALUE_NONE, '删除模式')
|
||
->addOption('runtime', 'r', Option::VALUE_NONE, '临时生成(生成到 runtime 目录)')
|
||
->addOption('examples', null, Option::VALUE_NONE, '显示使用示例')
|
||
->setDescription('一键生成 CURD 代码(控制器、模型、视图、JS)');
|
||
}
|
||
|
||
protected function getExamplesText(): string
|
||
{
|
||
return <<<'EXAMPLES'
|
||
<info>CURD 命令使用示例</info>
|
||
|
||
<comment>示例 1:首次生成(基本用法)</comment>
|
||
<info>php think curd -t daka_record</info>
|
||
说明:直接生成到项目目录,如文件已存在会跳过
|
||
|
||
<comment>示例 2:增量更新(已有业务代码)</comment>
|
||
<info>php think curd -t daka_record -r</info>
|
||
说明:生成到 runtime 临时目录,用于手动对比并合并新增字段代码(避免覆盖业务逻辑)
|
||
|
||
<comment>示例 3:带前缀的表名</comment>
|
||
<info>php think curd -t ul_daka_record</info>
|
||
说明:自动识别并去除前缀
|
||
|
||
<comment>示例 4:强制覆盖(谨慎使用)</comment>
|
||
<info>php think curd -t daka_record -f</info>
|
||
说明:覆盖已存在的文件,<error>会丢失手动修改的内容</error>
|
||
|
||
<comment>示例 5:删除已生成的文件</comment>
|
||
<info>php think curd -t daka_record -d</info>
|
||
说明:删除之前生成的所有文件(会要求确认)
|
||
注意:<error>这是删除文件,不是删除数据库记录</error>
|
||
|
||
<comment>常见错误及解决:</comment>
|
||
错误:表不存在
|
||
→ 先创建表:php think scheme:sync
|
||
→ 或使用迁移:php think migrate:run
|
||
|
||
错误:Scheme 与数据库不一致
|
||
→ 同步 Scheme:php think scheme:sync
|
||
EXAMPLES;
|
||
}
|
||
|
||
protected function execute(Input $input, Output $output)
|
||
{
|
||
// 显示使用示例
|
||
if ($input->hasOption('examples')) {
|
||
$output->writeln($this->getExamplesText());
|
||
return true;
|
||
}
|
||
|
||
$table = $input->getOption('table');
|
||
$controllerFilename = $input->getOption('controllerFilename');
|
||
$modelFilename = $input->getOption('modelFilename');
|
||
|
||
$force = 0;
|
||
$delete = 0;
|
||
|
||
if ($input->hasOption('force')) {
|
||
$force = 1;
|
||
}
|
||
|
||
if ($input->hasOption('delete')) {
|
||
$delete = 1;
|
||
}
|
||
|
||
if (empty($table)) {
|
||
$output->error('请设置主表');
|
||
|
||
return false;
|
||
}
|
||
|
||
// 收集警告信息
|
||
$warnings = [];
|
||
|
||
try {
|
||
$build = (new BuildCurdService())
|
||
->setTable($table)
|
||
->setForce($force);
|
||
|
||
$runtime_path = '';
|
||
if ($input->hasOption('runtime')) {
|
||
$runtime_path = App::getRuntimePath() . 'source' . DS . 'build' . DS . date('YmdHis') . DS;
|
||
PathTools::intiDir($runtime_path . 'a.temp');
|
||
|
||
$build->setRootDir($runtime_path);
|
||
}
|
||
|
||
$columns = $build->getTableColumns();
|
||
|
||
$relations = [];
|
||
|
||
foreach ($columns as $field => $column) {
|
||
if (isset($column['formType']) && $column['formType'] == 'relation') {
|
||
$define = $column['define'];
|
||
|
||
if (!isset($define['table'])) {
|
||
$error = "关联字段{$field}没有设置关联表名称";
|
||
$output->error($error);
|
||
$warnings[] = ['message' => $error];
|
||
return false;
|
||
}
|
||
|
||
$relations[] = [
|
||
'table' => $define['table'],
|
||
'foreignKey' => $field,
|
||
'primaryKey' => $define['primaryKey'] ?? null,
|
||
'modelFilename' => $define['modelFilename'] ?? null,
|
||
'onlyFileds' => isset($define['onlyFileds']) ? explode('|', $define['onlyFileds']) : [],
|
||
'relationBindSelect' => $define['relationBindSelect'] ?? null,
|
||
];
|
||
}
|
||
}
|
||
|
||
!empty($controllerFilename) && $build = $build->setControllerFilename($controllerFilename);
|
||
!empty($modelFilename) && $build = $build->setModelFilename($modelFilename);
|
||
|
||
foreach ($relations as $relation) {
|
||
$build = $build->setRelation($relation['table'], $relation['foreignKey'], $relation['primaryKey'], $relation['modelFilename'], $relation['onlyFileds'], $relation['relationBindSelect']);
|
||
}
|
||
|
||
$build = $build->render();
|
||
$fileList = $build->getFileList();
|
||
|
||
$result = [];
|
||
if (!$delete) {
|
||
if ($force) {
|
||
$output->writeln('>>>>>>>>>>>>>>>');
|
||
foreach ($fileList as $key => $val) {
|
||
$output->writeln($key);
|
||
}
|
||
$output->writeln('>>>>>>>>>>>>>>>');
|
||
|
||
if (!$output->confirm($input, '确定强制生成上方所有文件? 如果文件存在会直接覆盖。', true)) {
|
||
$output->comment('已取消。');
|
||
return false;
|
||
}
|
||
}
|
||
$result = $build->create();
|
||
$output->info('自动生成CURD成功');
|
||
} else {
|
||
$output->writeln('>>>>>>>>>>>>>>>');
|
||
foreach ($fileList as $key => $val) {
|
||
$output->writeln($key);
|
||
}
|
||
$output->writeln('>>>>>>>>>>>>>>>');
|
||
|
||
if (!$output->confirm($input, '确定删除上方所有文件? ', true)) {
|
||
$output->comment('已取消。');
|
||
return false;
|
||
}
|
||
$result = $build->delete();
|
||
$output->info('>>>>>>>>>>>>>>>');
|
||
$output->info('删除自动生成CURD文件成功');
|
||
}
|
||
$output->info('>>>>>>>>>>>>>>>');
|
||
foreach ($result as $vo) {
|
||
$output_endfix = '';
|
||
if ($input->hasOption('runtime')) {
|
||
$base_path = str_replace($runtime_path, '', $vo);
|
||
$root_path = App::getRootPath();
|
||
$output_endfix = PHP_EOL . 'ORIGIN:>>' . str_repeat(' ', 26) . ' ' . $root_path . $base_path . ' ';
|
||
}
|
||
$output->info($vo . $output_endfix . ' ');
|
||
}
|
||
} catch (\Exception $e) {
|
||
$output->error($e->getMessage());
|
||
|
||
return false;
|
||
}
|
||
}
|
||
}
|