building-sign/app/command/Generate.php

314 lines
11 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
declare (strict_types=1);
namespace app\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
class Generate extends Command
{
protected string $controller;
protected string $name;
protected string $title;
protected string $namespace;//控制器命名空间
protected string $viewDir;//view目录
protected string $jsFullDir;//js完整路径目录
protected string $jsDir;//js相对路径目录
protected string $controllerFullPath;//控制器完整路径
protected string $className;//控制器类名
protected function configure()
{
// 指令配置
$this->setName('generate')
->setDescription('生成后台基础crud')
->addOption('title', 't', Option::VALUE_REQUIRED, '标题')
->addOption('name', null, Option::VALUE_REQUIRED, '权限标识')
->addOption('controller', null, Option::VALUE_REQUIRED, '控制器命名空间');
}
protected function setInfo(string $controller, string $name, string $title)
{
$this->name = $name;
$this->controller = $controller;
$this->title = $title;
$this->controllerFullPath = $this->getControllerPathName();
$this->viewDir = $this->getViewDirName();
$this->jsFullDir = $this->getJsFullDirName();
$this->jsDir = $this->getJsDirName();
$controllerPath = explode('/', trim($controller, '/'));
$this->className = $controllerPath[count($controllerPath) - 1];
$namespace = 'app\\controller\\'.implode('\\', array_slice($controllerPath, 0, count($controllerPath) - 1));
$this->namespace = $namespace;
}
protected function execute(Input $input, Output $output)
{
$title = $input->getOption('title') ? trim($input->getOption('title')) : '';
$name = $input->getOption('name') ? trim($input->getOption('name')) : '';
$controller = $input->getOption('controller') ? trim($input->getOption('controller')) : '';
$this->setInfo($controller, $name, $title);
try {
$output->writeln('开始创建');
$output->writeln('1.菜单表生成数据...');
$dbRes = $this->createDb([
'title' => $title, 'name' => $name, 'controller' => $controller
]);
$successList = [];
if ($dbRes) {
$output->info('菜单表数据生成成功!');
$successList[] = '菜单数据生成!';
} else {
$output->warning('菜单表数据生成失败');
}
$output->writeln('2.生成控制器...');
if (is_file($this->controllerFullPath)) {
$output->error('控制器: '.$controller.' 已存在!');
}
if (!is_dir(dirname($this->controllerFullPath))) {
mkdir(dirname($this->controllerFullPath), 0755, true);
}
// 生成控制器
file_put_contents($this->controllerFullPath, $this->buildController());
$output->info($this->controllerFullPath.' 控制器生成成功!');
$successList[] = '创建文件:'.$this->controllerFullPath;
$output->writeln('3.生成视图文件...');
if (!is_dir($this->viewDir)) {
mkdir($this->viewDir, 0755, true);
}
foreach (['index', 'add', 'edit'] as $action) {
$actionHtml = sprintf('%s/%s.html', $this->viewDir, $action);
if (is_file($actionHtml)) {
$output->error($actionHtml.' 视图文件已存在!');
}
file_put_contents($actionHtml, $this->buildView($action));
$output->info($actionHtml.' 文件创建成功');
$successList[] = '创建文件:'.$actionHtml;
}
$output->info('视图文件生成成功!');
$jsPath = sprintf('%s/%s.js', $this->jsFullDir, unCamelize($this->className, '_'));
$output->writeln('4.生成js文件...');
if (!is_dir($this->jsFullDir)) {
mkdir($this->jsFullDir, 0755, true);
}
file_put_contents($jsPath, $this->buildJs());
$output->info($jsPath.' js文件创建成功');
$successList[] = '创建文件:'.$jsPath;
$output->newLine();
$output->writeln('信息汇总');
// 汇总信息
foreach ($successList as $success) {
$output->info($success);
}
$output->newLine();
$output->info(sprintf('此时可访问路径查看是否创建成功 /%s/index', unCamelize($controller)));
$output->newLine();
$output->warning('请注意,控制器中 $noNeedRight 默认开启了所有权限,如需纳入权限控制,请删除并在角色中选择对应权限');
// 指令输出
$output->info('创建完成');
} catch (\Exception $e) {
$output->error($e->getMessage());
}
}
/**
* 构建控制器内容
*
* @return array|false|string|string[]
*/
protected function buildController()
{
$controllerStubPath = __DIR__.DIRECTORY_SEPARATOR.'stubs/controller.stub';
$stub = file_get_contents($controllerStubPath);
return str_replace(['{%className%}', '{%namespace%}'], [
$this->className,
$this->namespace,
], $stub);
}
/**
* 构建视图文件内容
*
* @param string $action
* @return array|false|string|string[]
*/
protected function buildView(string $action)
{
$actionStubPath = __DIR__.DIRECTORY_SEPARATOR.'stubs/'.$action.'.stub';
$stub = file_get_contents($actionStubPath);
return str_replace(['{%path%}', '{%jsPath%}'], [
'/'.unCamelize($this->controller),
$this->jsDir.'/'.unCamelize($this->className, '_').'.js',
], $stub);
}
/**
* 构建js文件内容
*
* @return false|string
*/
protected function buildJs()
{
$actionStubPath = __DIR__.DIRECTORY_SEPARATOR.'stubs/js.stub';
return file_get_contents($actionStubPath);
}
/**
* 获取控制器完整路径
*
* @return string
*/
protected function getControllerPathName(): string
{
return $this->app->getBasePath().'controller/'.ltrim(str_replace('\\', '/', $this->controller), '/').'.php';
}
/**
* 获取对应view完整目录
*
* @return string
*/
protected function getViewDirName(): string
{
return $this->app->getRootPath().'view/'.ltrim(unCamelize($this->controller, '_'), '/');
}
/**
* 获取对应js完整目录
*
* @return string
*/
protected function getJsFullDirName(): string
{
$dir = $this->app->getRootPath().'public/static/'.ltrim(unCamelize($this->controller, '_'), '/');
return str_replace('/manager/', '/manager/js/', $dir);
}
/**
* 获取对应js相对目录
*
* @return string
*/
protected function getJsDirName(): string
{
return explode('/manager/', $this->jsFullDir)[1] ?? '';
}
/**
* 自动添加菜单表数据
*
* @param array $data
* @return bool
* @throws \Exception
*/
public function createDb(array $data): bool
{
$menuTable = 'menu';
$now = date('Y-m-d H:i:s');
if (!isset($data['title']) || !isset($data['name']) || !isset($data['controller'])) {
throw new \Exception('参数错误 请添加:--title 标题 --name 权限标识如aaa/bbb --controller 控制器 如manager/aaa/Bbb');
}
if (empty($data['title']) || empty($data['name']) || empty($data['controller'])) {
throw new \Exception('参数错误 请添加:--title 标题 --name 权限标识如aaa/bbb --controller 控制器 如manager/aaa/Bbb');
}
// 检查权限标识是否已存在
$already = Db::name('menu')->where('name', $data['name'])->whereOr('title', $data['title'])->count();
if ($already) {
throw new \Exception('菜单名称或标识已存在');
}
$href = unCamelize($data['controller']);
$insertMaster = [
'pid' => 0,
'title' => $data['title'], //名称
'icon' => $data['icon'] ?? 'fa-align-justify', //菜单图标
'name' => $data['name'], //权限标识
'href' => $href.'/index',//链接
'type' => 'menu',
'is_show' => 1,
'status' => 1,
'remark' => 'command generate',
'created_at' => $now,
];
$masterId = Db::name($menuTable)->insertGetId($insertMaster);
$masterPath = sprintf(',0,%d,', $masterId);
Db::name($menuTable)->where('id', $masterId)->update([
'path' => $masterPath
]);
$insertName = trim($data['name'], '/');
$insertHref = '/'.trim($href, '/');
$actionArr = $this->actionList();
// 基于权限标识生成下级列表 默认index add del edit modify
$insertAll = [];
foreach (array_keys($actionArr) as $action) {
$insertAll[] = [
'pid' => $masterId,
'title' => $actionArr[$action]['title'], //名称
'icon' => '', //菜单图标
'name' => $insertName.':'.$action, //权限标识
'href' => $insertHref.'/'.$action,//链接
'type' => 'action',
'is_show' => 1,
'status' => 1,
'remark' => 'command generate',
'path' => $masterPath,//此时的path为负极path
'created_at' => $now,
];
}
// 插入自己菜单
Db::name($menuTable)->insertAll($insertAll);
// 批量更新自己菜单path
Db::execute("update bee_$menuTable set `path`=concat(`path`, `id`, ',') where pid=$masterId");
return true;
}
protected function actionList(): array
{
return [
'index' => ['title' => '查看'],
'add' => ['title' => '添加'],
'edit' => ['title' => '编辑'],
'del' => ['title' => '删除'],
'modify' => ['title' => '属性设置'],
'sort' => ['title' => '排序'],
];
}
}