mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-07-07 02:22:48 +08:00
feat: 发布智能体版
This commit is contained in:
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin;
|
||||
|
||||
use think\console\Command;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
use think\facade\App;
|
||||
@@ -13,6 +13,8 @@ class ClearBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
// 指令配置
|
||||
$this->setName('admin:clear')
|
||||
->setDescription('删除开发临时生成目录');
|
||||
@@ -20,31 +22,34 @@ class ClearBase extends Command
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
// 指令输出
|
||||
$output->writeln('删除测试目录');
|
||||
|
||||
$dir = App::getRootPath() . '/runtime/source/';
|
||||
$deleted = false;
|
||||
$message = '';
|
||||
$command_line = '';
|
||||
|
||||
$dir = App::getRootPath() . '/runtime/source/';
|
||||
|
||||
if (!is_dir($dir)) {
|
||||
$output->writeln('删除成功');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (strpos(strtolower(PHP_OS), 'win') === 0) {
|
||||
$command_line = implode(' ', ['rd', '/s', '/q', str_replace('/', '\\', $dir)]);
|
||||
$deleted = true;
|
||||
$message = '目录不存在,无需删除';
|
||||
} else {
|
||||
$command_line = implode(' ', ['rm', '-rf', $dir]);
|
||||
if (strpos(strtolower(PHP_OS), 'win') === 0) {
|
||||
$command_line = implode(' ', ['rd', '/s', '/q', str_replace('/', '\\', $dir)]);
|
||||
} else {
|
||||
$command_line = implode(' ', ['rm', '-rf', $dir]);
|
||||
}
|
||||
|
||||
exec($command_line);
|
||||
$deleted = !is_dir($dir);
|
||||
$message = $deleted ? '删除成功' : '删除失败';
|
||||
}
|
||||
|
||||
$output->info('删除目录:' . $command_line);
|
||||
// 文本模式输出
|
||||
$output->writeln('删除测试目录');
|
||||
if ($command_line) {
|
||||
$output->info('删除目录:' . $command_line);
|
||||
$output->info('run command: ' . $command_line);
|
||||
}
|
||||
$output->info($message);
|
||||
|
||||
$output->info('run command: ' . $command_line);
|
||||
|
||||
exec($command_line);
|
||||
|
||||
$output->info('删除成功');
|
||||
return $deleted ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||
namespace base\common\command\admin;
|
||||
|
||||
use app\admin\service\AdminUpdateService;
|
||||
use think\console\Command;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
@@ -17,11 +17,13 @@ class UpdateBase extends Command
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
// 指令配置
|
||||
$this->setName('admin:update')
|
||||
->addOption('reinstall', null, Option::VALUE_NONE, '重装版本')
|
||||
->addOption('update-ulthon', null, Option::VALUE_NONE, '重装版本')
|
||||
->setDescription('the admin:update command');
|
||||
->addOption('update-ulthon', null, Option::VALUE_NONE, '更新 ulthon_admin')
|
||||
->setDescription('更新系统代码');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
@@ -38,6 +40,7 @@ class UpdateBase extends Command
|
||||
$update_service = new AdminUpdateService($repo);
|
||||
$update_service->input = $input;
|
||||
$update_service->output = $output;
|
||||
|
||||
$update_service->update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin;
|
||||
|
||||
use app\common\console\Command;
|
||||
use app\common\tools\PathTools;
|
||||
use think\App as ThinkApp;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
@@ -85,6 +85,8 @@ class VersionBase extends Command
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
// 指令配置
|
||||
$this->setName('admin:version')
|
||||
->addOption('generate-comment', null, Option::VALUE_NONE, '使用git命令生成说明文件')
|
||||
@@ -96,6 +98,7 @@ class VersionBase extends Command
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
// 文本模式输出
|
||||
// 指令输出
|
||||
if (!empty(static::PRODUCT_VERSION)) {
|
||||
$output->info('当前版本号为:' . static::PRODUCT_VERSION);
|
||||
|
||||
106
extend/base/common/command/admin/menu/AdminMenuCreateBase.php
Normal file
106
extend/base/common/command/admin/menu/AdminMenuCreateBase.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\menu;
|
||||
|
||||
use app\admin\model\SystemMenu;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
/**
|
||||
* admin:menu:create command - 创建菜单
|
||||
*/
|
||||
class AdminMenuCreateBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
// 命令配置
|
||||
$this->setName('admin:menu:create')
|
||||
->addOption('title', null, Option::VALUE_REQUIRED, '菜单标题(必填)')
|
||||
->addOption('path', null, Option::VALUE_OPTIONAL, '菜单路径', '')
|
||||
->addOption('icon', null, Option::VALUE_OPTIONAL, '菜单图标', '')
|
||||
->addOption('parent-id', null, Option::VALUE_OPTIONAL, '父菜单ID(默认为0)', 0)
|
||||
->addOption('sort', null, Option::VALUE_OPTIONAL, '排序(默认为100)', 100)
|
||||
->addOption('node', null, Option::VALUE_OPTIONAL, '权限节点', '')
|
||||
->addOption('remark', null, Option::VALUE_OPTIONAL, '备注说明', '')
|
||||
->setDescription('创建菜单');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
// 获取参数
|
||||
$title = $input->getOption('title');
|
||||
$path = $input->getOption('path');
|
||||
$icon = $input->getOption('icon');
|
||||
$parentId = $input->getOption('parent-id');
|
||||
$sort = $input->getOption('sort');
|
||||
$node = $input->getOption('node');
|
||||
$remark = $input->getOption('remark');
|
||||
|
||||
// 验证必填参数
|
||||
if (empty($title)) {
|
||||
$output->error('菜单标题不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 准备菜单数据
|
||||
$menuData = [
|
||||
'title' => $title,
|
||||
'path' => $path,
|
||||
'icon' => $icon,
|
||||
'parent_id' => (int)$parentId,
|
||||
'sort' => (int)$sort,
|
||||
'node' => $node,
|
||||
'remark' => $remark,
|
||||
];
|
||||
|
||||
// 实例化菜单服务(使用 app\admin\service\MenuService,它继承自 base\common\service\MenuServiceBase)
|
||||
// 由于 MenuServiceBase 需要 adminId 参数,我们使用 0 表示命令行操作
|
||||
$menuService = new \app\common\service\MenuService(0);
|
||||
|
||||
// 创建菜单
|
||||
$menuId = $menuService->create($menuData);
|
||||
|
||||
// 获取创建的菜单详情
|
||||
$menuModel = SystemMenu::find($menuId);
|
||||
$menu = $menuModel ? $menuModel->toArray() : null;
|
||||
|
||||
if (empty($menu)) {
|
||||
throw new \Exception('菜单创建成功,但无法获取菜单详情');
|
||||
}
|
||||
|
||||
$outputData = [
|
||||
'id' => (int)$menu['id'],
|
||||
'title' => $menu['title'] ?? '',
|
||||
'path' => $menu['href'] ?? '',
|
||||
'icon' => $menu['icon'] ?? '',
|
||||
'parent_id' => (int)($menu['pid'] ?? 0),
|
||||
'sort' => (int)($menu['sort'] ?? 0),
|
||||
'node' => $menu['auth_node'] ?? '',
|
||||
];
|
||||
|
||||
// 输出结果
|
||||
$output->info('菜单创建成功');
|
||||
$output->info('菜单ID: ' . $outputData['id']);
|
||||
$output->info('菜单标题: ' . $outputData['title']);
|
||||
$output->info('菜单路径: ' . $outputData['path']);
|
||||
$output->info('菜单图标: ' . $outputData['icon']);
|
||||
$output->info('父菜单ID: ' . $outputData['parent_id']);
|
||||
$output->info('排序: ' . $outputData['sort']);
|
||||
if (!empty($outputData['node'])) {
|
||||
$output->info('权限节点: ' . $outputData['node']);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('创建菜单失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\menu;
|
||||
|
||||
use app\admin\model\SystemMenu;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
/**
|
||||
* admin:menu:delete command - 删除菜单
|
||||
*/
|
||||
class AdminMenuDeleteBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
// 指令配置
|
||||
$this->setName('admin:menu:delete')
|
||||
->addOption('id', null, Option::VALUE_REQUIRED, '菜单ID')
|
||||
->setDescription('删除菜单');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
// 获取参数
|
||||
$id = $input->getOption('id');
|
||||
|
||||
// 验证参数
|
||||
if (empty($id)) {
|
||||
$output->error('菜单ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. 验证菜单是否存在
|
||||
$menu = SystemMenu::find($id);
|
||||
if (empty($menu)) {
|
||||
$output->error('菜单ID ' . $id . ' 不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 检查是否有子菜单
|
||||
$childCount = SystemMenu::where('pid', $id)
|
||||
->where('delete_time', 0)
|
||||
->count();
|
||||
|
||||
if ($childCount > 0) {
|
||||
$output->error('菜单ID ' . $id . ' 存在 ' . $childCount . ' 个子菜单,请先删除子菜单');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 保存菜单信息用于输出
|
||||
$menuInfo = [
|
||||
'id' => (int)$menu->id,
|
||||
'title' => $menu->title,
|
||||
'path' => $menu->href ?? '',
|
||||
'icon' => $menu->icon ?? '',
|
||||
'parent_id' => (int)($menu->pid ?? 0),
|
||||
'sort' => (int)($menu->sort ?? 0),
|
||||
'node' => $menu->auth_node ?? '',
|
||||
];
|
||||
|
||||
// 4. 执行删除(软删除)
|
||||
$menu->delete();
|
||||
|
||||
// 5. 输出结果
|
||||
$output->info('菜单删除成功');
|
||||
$output->info('菜单ID: ' . $menuInfo['id']);
|
||||
$output->info('菜单名称: ' . $menuInfo['title']);
|
||||
$output->info('菜单路径: ' . $menuInfo['path']);
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('删除菜单失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
127
extend/base/common/command/admin/menu/AdminMenuExportBase.php
Normal file
127
extend/base/common/command/admin/menu/AdminMenuExportBase.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\menu;
|
||||
|
||||
use app\admin\model\SystemMenu;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
/**
|
||||
* admin:menu:export command - 导出菜单
|
||||
*/
|
||||
class AdminMenuExportBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
// 指令配置
|
||||
$this->setName('admin:menu:export')
|
||||
->setDescription('导出菜单数据')
|
||||
->addOption('format', null, Option::VALUE_OPTIONAL, '输出格式(text/json)', 'text')
|
||||
->addOption('output', null, Option::VALUE_OPTIONAL, '输出文件路径(可选)');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
// 获取参数
|
||||
$outputPath = $input->getOption('output');
|
||||
|
||||
try {
|
||||
// 1. 查询所有菜单
|
||||
$menus = SystemMenu::where('delete_time', 0)
|
||||
->order(['sort' => 'desc', 'id' => 'asc'])
|
||||
->select()
|
||||
->hidden(['create_time', 'update_time', 'delete_time']);
|
||||
|
||||
// 2. 格式化菜单数据
|
||||
$menuData = [];
|
||||
foreach ($menus as $menu) {
|
||||
$menuData[] = [
|
||||
'id' => (int)$menu->id,
|
||||
'pid' => (int)($menu->pid ?? 0),
|
||||
'title' => $menu->title ?? '',
|
||||
'href' => $menu->href ?? '',
|
||||
'icon' => $menu->icon ?? '',
|
||||
'sort' => (int)($menu->sort ?? 0),
|
||||
'auth_node' => $menu->auth_node ?? '',
|
||||
'status' => (int)($menu->status ?? 0),
|
||||
'type' => (int)($menu->type ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
// JSON 模式输出
|
||||
if ($input->getOption('format') === 'json') {
|
||||
if (!empty($outputPath)) {
|
||||
$jsonData = json_encode($menuData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
||||
if ($jsonData === false) {
|
||||
throw new \RuntimeException('JSON 编码失败');
|
||||
}
|
||||
|
||||
$result = file_put_contents($outputPath, $jsonData);
|
||||
if ($result === false) {
|
||||
throw new \RuntimeException('无法写入文件: ' . $outputPath);
|
||||
}
|
||||
}
|
||||
|
||||
$json = json_encode([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'menus' => $menuData,
|
||||
'output' => !empty($outputPath) ? $outputPath : null,
|
||||
],
|
||||
'warnings' => [],
|
||||
'metadata' => [
|
||||
'count' => count($menuData),
|
||||
'exported_at' => date('c'),
|
||||
],
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
$output->writeln($json);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. 如果指定了输出路径,写入文件
|
||||
if (!empty($outputPath)) {
|
||||
$jsonData = json_encode($menuData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
||||
$result = file_put_contents($outputPath, $jsonData);
|
||||
|
||||
if ($result === false) {
|
||||
$output->error('无法写入文件: ' . $outputPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
$output->info('成功导出 ' . count($menuData) . ' 个菜单到文件: ' . $outputPath);
|
||||
} else {
|
||||
// 4. 输出结果到控制台
|
||||
$output->info('成功导出 ' . count($menuData) . ' 个菜单');
|
||||
|
||||
// 以表格形式输出菜单数据
|
||||
$output->writeln('菜单ID | 父菜单ID | 菜单标题 | 菜单路径 | 图标 | 排序 | 权限节点 | 状态 | 类型');
|
||||
$output->writeln('--------|----------|----------|----------|------|------|----------|------|------');
|
||||
|
||||
foreach ($menuData as $menu) {
|
||||
$output->writeln($menu['id'] . ' | ' .
|
||||
$menu['pid'] . ' | ' .
|
||||
$menu['title'] . ' | ' .
|
||||
$menu['href'] . ' | ' .
|
||||
$menu['icon'] . ' | ' .
|
||||
$menu['sort'] . ' | ' .
|
||||
$menu['auth_node'] . ' | ' .
|
||||
$menu['status'] . ' | ' .
|
||||
$menu['type']);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('导出菜单失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
132
extend/base/common/command/admin/menu/AdminMenuListBase.php
Normal file
132
extend/base/common/command/admin/menu/AdminMenuListBase.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\menu;
|
||||
|
||||
use app\admin\model\SystemMenu;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminMenuListBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:menu:list')
|
||||
->setDescription('列出所有菜单(树形结构)')
|
||||
->addOption('format', null, Option::VALUE_OPTIONAL, '输出格式(tree/table/json)', 'tree')
|
||||
->addOption('status', null, Option::VALUE_OPTIONAL, '筛选状态(0=禁用,1=启用,all=全部)', 'all')
|
||||
->addOption('pid', null, Option::VALUE_OPTIONAL, '指定父菜单ID(默认从根菜单开始)', null);
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$format = $input->getOption('format');
|
||||
$statusFilter = $input->getOption('status');
|
||||
$pidFilter = $input->getOption('pid');
|
||||
|
||||
try {
|
||||
$query = SystemMenu::where('delete_time', 0);
|
||||
|
||||
if ($statusFilter !== 'all') {
|
||||
$query->where('status', (int)$statusFilter);
|
||||
}
|
||||
|
||||
$menus = $query->order(['sort' => 'desc', 'id' => 'asc'])
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
if (empty($menus)) {
|
||||
$output->comment('没有找到菜单数据');
|
||||
return true;
|
||||
}
|
||||
|
||||
$menuTree = $this->buildTree($menus, $pidFilter ? (int)$pidFilter : 0);
|
||||
|
||||
switch ($format) {
|
||||
case 'json':
|
||||
$this->outputJson($output, $menuTree, count($menus));
|
||||
break;
|
||||
case 'table':
|
||||
$this->outputTable($output, $menus);
|
||||
break;
|
||||
case 'tree':
|
||||
default:
|
||||
$this->outputTree($output, $menuTree);
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('获取菜单列表失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function buildTree(array $menus, int $pid = 0): array
|
||||
{
|
||||
$tree = [];
|
||||
foreach ($menus as $menu) {
|
||||
if ((int)$menu['pid'] === $pid) {
|
||||
$children = $this->buildTree($menus, (int)$menu['id']);
|
||||
if (!empty($children)) {
|
||||
$menu['children'] = $children;
|
||||
}
|
||||
$tree[] = $menu;
|
||||
}
|
||||
}
|
||||
return $tree;
|
||||
}
|
||||
|
||||
protected function outputTree(Output $output, array $tree, int $level = 0): void
|
||||
{
|
||||
$prefix = str_repeat(' ', $level);
|
||||
$branch = $level > 0 ? '├─ ' : '';
|
||||
|
||||
foreach ($tree as $node) {
|
||||
$status = $node['status'] ? '<info>●</info>' : '<comment>○</comment>';
|
||||
$href = $node['href'] ?? '-';
|
||||
$output->writeln("{$prefix}{$branch}{$status} [{$node['id']}] {$node['title']} <comment>({$href})</comment>");
|
||||
|
||||
if (!empty($node['children'])) {
|
||||
$this->outputTree($output, $node['children'], $level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function outputTable(Output $output, array $menus): void
|
||||
{
|
||||
$output->writeln('ID | PID | 标题 | 路径 | 状态');
|
||||
$output->writeln('---|-----|------|------|------');
|
||||
|
||||
foreach ($menus as $menu) {
|
||||
$status = $menu['status'] ? '启用' : '禁用';
|
||||
$output->writeln(sprintf(
|
||||
'%d | %d | %s | %s | %s',
|
||||
$menu['id'],
|
||||
$menu['pid'],
|
||||
$menu['title'],
|
||||
$menu['href'] ?? '-',
|
||||
$status
|
||||
));
|
||||
}
|
||||
|
||||
$output->writeln('');
|
||||
$output->info('共 ' . count($menus) . ' 个菜单');
|
||||
}
|
||||
|
||||
protected function outputJson(Output $output, array $tree, int $total): void
|
||||
{
|
||||
$data = [
|
||||
'success' => true,
|
||||
'data' => ['menus' => $tree],
|
||||
'metadata' => ['total' => $total],
|
||||
];
|
||||
$output->writeln(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
|
||||
}
|
||||
}
|
||||
129
extend/base/common/command/admin/menu/AdminMenuUpdateBase.php
Normal file
129
extend/base/common/command/admin/menu/AdminMenuUpdateBase.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\menu;
|
||||
|
||||
use app\admin\model\SystemMenu;
|
||||
use app\common\console\Command;
|
||||
use app\common\service\MenuService;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
/**
|
||||
* admin:menu:update command - 更新菜单
|
||||
*/
|
||||
class AdminMenuUpdateBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
// 指令配置
|
||||
$this->setName('admin:menu:update')
|
||||
->addOption('id', null, Option::VALUE_REQUIRED, '菜单ID(必填)')
|
||||
->addOption('title', null, Option::VALUE_OPTIONAL, '菜单标题')
|
||||
->addOption('path', null, Option::VALUE_OPTIONAL, '菜单路径')
|
||||
->addOption('icon', null, Option::VALUE_OPTIONAL, '菜单图标')
|
||||
->addOption('parent-id', null, Option::VALUE_OPTIONAL, '父级菜单ID')
|
||||
->addOption('sort', null, Option::VALUE_OPTIONAL, '排序')
|
||||
->setDescription('编辑菜单');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
// 获取参数
|
||||
$id = (int)($input->getOption('id') ?? 0);
|
||||
$title = $input->getOption('title');
|
||||
$path = $input->getOption('path');
|
||||
$icon = $input->getOption('icon');
|
||||
$parentId = $input->getOption('parent-id');
|
||||
$sort = $input->getOption('sort');
|
||||
|
||||
// 验证参数:id 是必填的
|
||||
if (empty($id)) {
|
||||
$output->error('菜单ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. 验证菜单是否存在
|
||||
$menu = SystemMenu::find($id);
|
||||
if (empty($menu)) {
|
||||
$output->writeln('<error>菜单ID ' . $id . ' 不存在</error>');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 准备更新数据
|
||||
$updateData = [];
|
||||
|
||||
if ($title !== null) {
|
||||
$updateData['title'] = $title;
|
||||
}
|
||||
|
||||
if ($path !== null) {
|
||||
$updateData['path'] = $path;
|
||||
}
|
||||
|
||||
if ($icon !== null) {
|
||||
$updateData['icon'] = $icon;
|
||||
}
|
||||
|
||||
if ($parentId !== null) {
|
||||
$updateData['parent_id'] = (int)$parentId;
|
||||
}
|
||||
|
||||
if ($sort !== null) {
|
||||
$updateData['sort'] = (int)$sort;
|
||||
}
|
||||
|
||||
// 检查是否有需要更新的字段
|
||||
if (empty($updateData)) {
|
||||
$output->error('没有提供需要更新的字段');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 调用 MenuService 更新菜单
|
||||
$menuService = new MenuService(0);
|
||||
$success = $menuService->update($id, $updateData);
|
||||
|
||||
if (!$success) {
|
||||
$output->writeln('<error>菜单更新失败</error>');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 重新查询菜单数据
|
||||
$updatedMenu = SystemMenu::find($id);
|
||||
if (empty($updatedMenu)) {
|
||||
$output->writeln('<error>菜单更新后查询失败</error>');
|
||||
return false;
|
||||
}
|
||||
|
||||
$outputData = [
|
||||
'id' => (int)$updatedMenu->id,
|
||||
'title' => $updatedMenu->title ?? '',
|
||||
'path' => $updatedMenu->href ?? '',
|
||||
'icon' => $updatedMenu->icon ?? '',
|
||||
'parent_id' => (int)($updatedMenu->pid ?? 0),
|
||||
'sort' => (int)($updatedMenu->sort ?? 0),
|
||||
'node' => $updatedMenu->auth_node ?? '',
|
||||
];
|
||||
|
||||
// 5. 输出结果
|
||||
$output->writeln('<info>菜单编辑成功</info>');
|
||||
$output->writeln('<info>菜单ID: ' . $outputData['id'] . '</info>');
|
||||
$output->writeln('<info>菜单标题: ' . $outputData['title'] . '</info>');
|
||||
$output->writeln('<info>菜单路径: ' . $outputData['path'] . '</info>');
|
||||
$output->writeln('<info>菜单图标: ' . $outputData['icon'] . '</info>');
|
||||
$output->writeln('<info>父级菜单ID: ' . $outputData['parent_id'] . '</info>');
|
||||
$output->writeln('<info>排序: ' . $outputData['sort'] . '</info>');
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('编辑菜单失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\permission;
|
||||
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\Input\Option;
|
||||
use think\console\Output;
|
||||
use app\admin\service\NodeService;
|
||||
|
||||
/**
|
||||
* admin:permission:nodes command - 查看权限节点
|
||||
*/
|
||||
class AdminPermissionNodesBase extends Command
|
||||
{
|
||||
/**
|
||||
* 配置命令参数
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
// 指令配置
|
||||
$this->setName('admin:permission:nodes')
|
||||
->setDescription('查看权限节点')
|
||||
->addOption('level', null, Option::VALUE_OPTIONAL, '按级别过滤 (1=控制器, 2=方法)')
|
||||
->addOption('module', null, Option::VALUE_OPTIONAL, '按模块过滤');
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行命令
|
||||
*
|
||||
* @param Input $input
|
||||
* @param Output $output
|
||||
* @return int
|
||||
* @throws \Doctrine\Common\Annotations\AnnotationException
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
try {
|
||||
// 获取所有权限节点
|
||||
$nodeService = new NodeService();
|
||||
$nodeList = $nodeService->getNodelist();
|
||||
|
||||
// 过滤条件
|
||||
$filterLevel = $input->getOption('level');
|
||||
$filterModule = $input->getOption('module');
|
||||
|
||||
// 应用过滤
|
||||
$filteredNodes = $nodeList;
|
||||
if ($filterLevel !== null) {
|
||||
$level = (int)$filterLevel;
|
||||
$filteredNodes = array_filter($filteredNodes, function ($node) use ($level) {
|
||||
return isset($node['type']) && $node['type'] === $level;
|
||||
});
|
||||
}
|
||||
|
||||
if ($filterModule !== null) {
|
||||
$filteredNodes = array_filter($filteredNodes, function ($node) use ($filterModule) {
|
||||
return isset($node['module']) && $node['module'] === $filterModule;
|
||||
});
|
||||
}
|
||||
|
||||
// 重新索引数组
|
||||
$filteredNodes = array_values($filteredNodes);
|
||||
|
||||
// 输出表头
|
||||
$output->info('权限节点列表');
|
||||
$output->writeln('================================');
|
||||
|
||||
if (empty($filteredNodes)) {
|
||||
$output->comment('没有找到符合条件的权限节点');
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 输出权限节点信息
|
||||
foreach ($filteredNodes as $node) {
|
||||
$levelText = $node['type'] == 1 ? '控制器' : '方法';
|
||||
$authText = isset($node['auth']) && $node['auth'] ? '是' : '否';
|
||||
|
||||
$output->info('节点: ' . ($node['node'] ?? ''));
|
||||
$output->comment(' 标题: ' . ($node['title'] ?? ''));
|
||||
$output->comment(' 级别: ' . $levelText . ' (' . ($node['type'] ?? 0) . ')');
|
||||
$output->comment(' 模块: ' . ($node['module'] ?? ''));
|
||||
$output->comment(' 需要授权: ' . $authText);
|
||||
$output->writeln('--------------------------------');
|
||||
}
|
||||
|
||||
$output->info('总计: ' . count($filteredNodes) . ' 个权限节点');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$output->error('获取权限节点失败: ' . $e->getMessage());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\permission;
|
||||
|
||||
use app\admin\model\SystemAdmin;
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\admin\model\SystemAuthNode;
|
||||
use app\admin\service\NodeService;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Argument;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminPermissionUserBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:permission:user')
|
||||
->addOption('user-id', 'u', Option::VALUE_OPTIONAL, '用户ID', null)
|
||||
->setDescription('查看用户权限');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$userId = $input->getOption('user-id');
|
||||
|
||||
// 验证用户ID参数
|
||||
if (empty($userId)) {
|
||||
$output->error('缺少必要参数 --user-id');
|
||||
return;
|
||||
}
|
||||
|
||||
// 查询用户
|
||||
$user = SystemAdmin::find($userId);
|
||||
|
||||
if (empty($user)) {
|
||||
$output->error('用户不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
// 查询用户角色
|
||||
$roles = [];
|
||||
$authIds = $user->auth_ids;
|
||||
$authIdArray = [];
|
||||
|
||||
if (!empty($authIds)) {
|
||||
$authIdArray = array_filter(explode(',', $authIds));
|
||||
|
||||
if (!empty($authIdArray)) {
|
||||
$roles = SystemAuth::whereIn('id', $authIdArray)
|
||||
->where('delete_time', 0)
|
||||
->field('id,title')
|
||||
->select()
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
// 查询用户权限节点
|
||||
$nodes = [];
|
||||
if (!empty($authIdArray)) {
|
||||
$nodes = SystemAuthNode::whereIn('auth_id', $authIdArray)
|
||||
->column('node');
|
||||
}
|
||||
|
||||
// 输出结果
|
||||
$output->info('用户权限信息');
|
||||
$output->info('用户ID: ' . $user->id);
|
||||
$output->info('用户名: ' . $user->username);
|
||||
|
||||
if (!empty($roles)) {
|
||||
$output->info('角色列表:');
|
||||
foreach ($roles as $role) {
|
||||
$output->comment(' - ID: ' . $role['id'] . ', 标题: ' . $role['title']);
|
||||
}
|
||||
} else {
|
||||
$output->comment('用户没有分配任何角色');
|
||||
}
|
||||
|
||||
if (!empty($nodes)) {
|
||||
$output->info('权限节点列表:');
|
||||
foreach ($nodes as $node) {
|
||||
$output->comment(' - ' . $node);
|
||||
}
|
||||
} else {
|
||||
$output->comment('用户没有分配任何权限节点');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\role;
|
||||
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminRoleCreateBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:role:create')
|
||||
->addOption('title', null, Option::VALUE_REQUIRED, '角色名称')
|
||||
->addOption('remark', null, Option::VALUE_OPTIONAL, '角色备注')
|
||||
->setDescription('创建角色');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$title = $input->getOption('title');
|
||||
$remark = $input->getOption('remark');
|
||||
|
||||
if (empty($title)) {
|
||||
$output->error('角色名称不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$auth = new SystemAuth();
|
||||
$auth->title = $title;
|
||||
$auth->remark = $remark ?? '';
|
||||
$auth->sort = 0;
|
||||
$auth->status = 1;
|
||||
$auth->save();
|
||||
|
||||
$output->info('角色创建成功');
|
||||
$output->info('角色ID: ' . $auth->id);
|
||||
$output->info('角色名称: ' . $auth->title);
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('创建角色失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\role;
|
||||
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\admin\model\SystemAuthNode;
|
||||
use app\admin\model\SystemAdmin;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminRoleDeleteBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:role:delete')
|
||||
->addOption('role-id', null, Option::VALUE_REQUIRED, '角色ID')
|
||||
->setDescription('删除角色');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$roleId = $input->getOption('role-id');
|
||||
|
||||
if (empty($roleId)) {
|
||||
$output->error('角色ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$auth = SystemAuth::find($roleId);
|
||||
if (empty($auth)) {
|
||||
$output->error('角色ID ' . $roleId . ' 不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
$checkUsers = SystemAdmin::where('auth_ids', 'like', '%' . $roleId . '%')
|
||||
->where('delete_time', 0)
|
||||
->count();
|
||||
|
||||
if ($checkUsers > 0) {
|
||||
$output->error('角色ID ' . $roleId . ' 已分配给 ' . $checkUsers . ' 个用户,无法删除');
|
||||
return false;
|
||||
}
|
||||
|
||||
SystemAuthNode::where('auth_id', $roleId)->delete();
|
||||
$auth->delete();
|
||||
|
||||
$output->info('角色删除成功');
|
||||
$output->info('角色ID: ' . $roleId);
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('删除角色失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
65
extend/base/common/command/admin/role/AdminRoleInfoBase.php
Normal file
65
extend/base/common/command/admin/role/AdminRoleInfoBase.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\role;
|
||||
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\admin\model\SystemAuthNode;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminRoleInfoBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:role:info')
|
||||
->addOption('role-id', null, Option::VALUE_REQUIRED, '角色ID')
|
||||
->setDescription('查看角色详情');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$roleId = $input->getOption('role-id');
|
||||
|
||||
if (empty($roleId)) {
|
||||
$output->error('角色ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$role = SystemAuth::find($roleId);
|
||||
if (empty($role)) {
|
||||
$output->error('角色ID ' . $roleId . ' 不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
$nodes = SystemAuthNode::where('auth_id', $roleId)
|
||||
->column('node');
|
||||
|
||||
$output->info('角色详情');
|
||||
$output->writeln('================================');
|
||||
$output->info('角色ID: ' . $role->id);
|
||||
$output->comment('角色名称: ' . $role->title);
|
||||
$output->comment('状态: ' . ($role->status == 1 ? '启用' : '禁用'));
|
||||
$output->comment('排序: ' . $role->sort);
|
||||
if (!empty($role->remark)) {
|
||||
$output->comment('备注: ' . $role->remark);
|
||||
}
|
||||
$output->writeln('--------------------------------');
|
||||
$output->info('权限节点列表 (' . count($nodes) . ' 个):');
|
||||
foreach ($nodes as $node) {
|
||||
$output->comment(' - ' . $node);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('获取角色详情失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
64
extend/base/common/command/admin/role/AdminRoleListBase.php
Normal file
64
extend/base/common/command/admin/role/AdminRoleListBase.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\role;
|
||||
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\admin\model\SystemAuthNode;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminRoleListBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:role:list')
|
||||
->setDescription('查看角色列表');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
try {
|
||||
$roles = SystemAuth::where('delete_time', 0)
|
||||
->field('id,title,sort,status,remark')
|
||||
->order('sort', 'asc')
|
||||
->order('id', 'desc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
if (empty($roles)) {
|
||||
$output->comment('没有找到任何角色');
|
||||
return true;
|
||||
}
|
||||
|
||||
$output->info('角色列表');
|
||||
$output->writeln('================================');
|
||||
|
||||
foreach ($roles as $role) {
|
||||
$nodeCount = SystemAuthNode::where('auth_id', $role['id'])->count();
|
||||
$statusText = $role['status'] == 1 ? '启用' : '禁用';
|
||||
|
||||
$output->info('角色ID: ' . $role['id']);
|
||||
$output->comment(' 角色名称: ' . $role['title']);
|
||||
$output->comment(' 权限节点数: ' . $nodeCount);
|
||||
$output->comment(' 状态: ' . $statusText);
|
||||
$output->comment(' 排序: ' . $role['sort']);
|
||||
if (!empty($role['remark'])) {
|
||||
$output->comment(' 备注: ' . $role['remark']);
|
||||
}
|
||||
$output->writeln('--------------------------------');
|
||||
}
|
||||
|
||||
$output->info('总计: ' . count($roles) . ' 个角色');
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('获取角色列表失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\role;
|
||||
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\admin\model\SystemAuthNode;
|
||||
use app\admin\service\NodeService;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminRolePermissionAssignBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:role:permission:assign')
|
||||
->addOption('role-id', null, Option::VALUE_REQUIRED, '角色ID')
|
||||
->addOption('nodes', null, Option::VALUE_REQUIRED, '权限节点列表(逗号分隔)')
|
||||
->setDescription('给角色分配权限');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$roleId = $input->getOption('role-id');
|
||||
$nodesParam = $input->getOption('nodes');
|
||||
|
||||
if (empty($roleId)) {
|
||||
$output->error('角色ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($nodesParam)) {
|
||||
$output->error('权限节点不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$auth = SystemAuth::find($roleId);
|
||||
if (empty($auth)) {
|
||||
$output->error('角色ID ' . $roleId . ' 不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
$nodes = $this->parseNodes($nodesParam);
|
||||
if (empty($nodes)) {
|
||||
$output->error('权限节点列表为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
$validNodes = $this->validateNodes($nodes);
|
||||
$invalidNodes = array_diff($nodes, $validNodes);
|
||||
|
||||
if (!empty($invalidNodes)) {
|
||||
$invalidCount = count($invalidNodes);
|
||||
$output->error("[错误] 发现 {$invalidCount} 个无效的权限节点:");
|
||||
foreach (array_values($invalidNodes) as $node) {
|
||||
$output->error(" - {$node}");
|
||||
}
|
||||
$output->writeln('');
|
||||
}
|
||||
|
||||
if (empty($validNodes)) {
|
||||
$output->error("有效权限节点数: 0");
|
||||
$output->error("分配失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
$existingNodes = SystemAuthNode::where('auth_id', $roleId)
|
||||
->column('node');
|
||||
$newNodes = array_diff($validNodes, $existingNodes);
|
||||
|
||||
if (empty($newNodes)) {
|
||||
$output->info('所有权限节点已存在,无需重复分配');
|
||||
return true;
|
||||
}
|
||||
|
||||
$authNodes = [];
|
||||
foreach ($newNodes as $node) {
|
||||
$authNodes[] = [
|
||||
'auth_id' => $roleId,
|
||||
'node' => $node,
|
||||
];
|
||||
}
|
||||
|
||||
(new SystemAuthNode())->saveAll($authNodes);
|
||||
|
||||
$output->info('权限分配成功');
|
||||
$output->info('角色ID: ' . $roleId);
|
||||
$output->info('新增的权限节点: ' . implode(', ', $newNodes));
|
||||
$output->info('该角色总权限节点数: ' . (count($existingNodes) + count($newNodes)));
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('分配权限失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function parseNodes(string $nodesParam): array
|
||||
{
|
||||
$nodes = explode(',', $nodesParam);
|
||||
$nodes = array_map('trim', $nodes);
|
||||
$nodes = array_filter($nodes);
|
||||
|
||||
return array_values($nodes);
|
||||
}
|
||||
|
||||
protected function validateNodes(array $nodes): array
|
||||
{
|
||||
$nodeService = new NodeService();
|
||||
$allNodes = $nodeService->getNodeParis();
|
||||
|
||||
$validNodes = [];
|
||||
foreach ($nodes as $node) {
|
||||
if (isset($allNodes[$node])) {
|
||||
$validNodes[] = $node;
|
||||
}
|
||||
}
|
||||
|
||||
return $validNodes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\role;
|
||||
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\admin\model\SystemAuthNode;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminRolePermissionListBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:role:permission:list')
|
||||
->addOption('role-id', null, Option::VALUE_REQUIRED, '角色ID')
|
||||
->setDescription('查看角色权限');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$roleId = $input->getOption('role-id');
|
||||
|
||||
if (empty($roleId)) {
|
||||
$output->error('角色ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$role = SystemAuth::find($roleId);
|
||||
if (empty($role)) {
|
||||
$output->error('角色ID ' . $roleId . ' 不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
$nodes = SystemAuthNode::where('auth_id', $roleId)
|
||||
->column('node');
|
||||
|
||||
$output->info('角色权限列表');
|
||||
$output->writeln('================================');
|
||||
$output->info('角色ID: ' . $role->id);
|
||||
$output->comment('角色名称: ' . $role->title);
|
||||
$output->writeln('--------------------------------');
|
||||
|
||||
if (empty($nodes)) {
|
||||
$output->comment('该角色没有分配任何权限节点');
|
||||
} else {
|
||||
$output->info('权限节点 (' . count($nodes) . ' 个):');
|
||||
foreach ($nodes as $node) {
|
||||
$output->comment(' - ' . $node);
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('获取角色权限失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\role;
|
||||
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\admin\model\SystemAuthNode;
|
||||
use app\admin\service\NodeService;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminRolePermissionRevokeBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:role:permission:revoke')
|
||||
->addOption('role-id', null, Option::VALUE_REQUIRED, '角色ID')
|
||||
->addOption('nodes', null, Option::VALUE_REQUIRED, '权限节点列表(逗号分隔)')
|
||||
->setDescription('撤回角色权限');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$roleId = $input->getOption('role-id');
|
||||
$nodesParam = $input->getOption('nodes');
|
||||
|
||||
if (empty($roleId)) {
|
||||
$output->error('角色ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($nodesParam)) {
|
||||
$output->error('权限节点不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$auth = SystemAuth::find($roleId);
|
||||
if (empty($auth)) {
|
||||
$output->error('角色ID ' . $roleId . ' 不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
$nodes = $this->parseNodes($nodesParam);
|
||||
if (empty($nodes)) {
|
||||
$output->error('权限节点列表为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
$validNodes = $this->validateNodes($nodes);
|
||||
$invalidNodes = array_diff($nodes, $validNodes);
|
||||
|
||||
if (!empty($invalidNodes)) {
|
||||
$output->comment('警告: 以下权限节点无效: ' . implode(', ', array_values($invalidNodes)));
|
||||
}
|
||||
|
||||
if (empty($validNodes)) {
|
||||
$output->error('没有有效的权限节点');
|
||||
return false;
|
||||
}
|
||||
|
||||
$deletedCount = SystemAuthNode::where('auth_id', $roleId)
|
||||
->where('node', 'in', $validNodes)
|
||||
->delete();
|
||||
|
||||
if ($deletedCount == 0) {
|
||||
$output->error('没有权限可以撤回(角色不包含指定的权限节点)');
|
||||
return false;
|
||||
}
|
||||
|
||||
$remainingCount = SystemAuthNode::where('auth_id', $roleId)->count();
|
||||
|
||||
$output->info('权限撤回成功');
|
||||
$output->info('角色ID: ' . $roleId);
|
||||
$output->info('撤回的权限节点: ' . implode(', ', $validNodes));
|
||||
$output->info('该角色剩余权限节点数: ' . $remainingCount);
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('撤回权限失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function parseNodes(string $nodesParam): array
|
||||
{
|
||||
$nodes = explode(',', $nodesParam);
|
||||
$nodes = array_map('trim', $nodes);
|
||||
$nodes = array_filter($nodes);
|
||||
|
||||
return array_values($nodes);
|
||||
}
|
||||
|
||||
protected function validateNodes(array $nodes): array
|
||||
{
|
||||
$nodeService = new NodeService();
|
||||
$allNodes = $nodeService->getNodeParis();
|
||||
|
||||
$validNodes = [];
|
||||
foreach ($nodes as $node) {
|
||||
if (isset($allNodes[$node])) {
|
||||
$validNodes[] = $node;
|
||||
}
|
||||
}
|
||||
|
||||
return $validNodes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\user;
|
||||
|
||||
use app\admin\model\SystemAdmin;
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminUserRoleAssignBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:user:role:assign')
|
||||
->addOption('user-id', null, Option::VALUE_REQUIRED, '用户ID')
|
||||
->addOption('role-ids', null, Option::VALUE_REQUIRED, '角色ID列表(逗号分隔)')
|
||||
->setDescription('给用户分配角色');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$userId = $input->getOption('user-id');
|
||||
$roleIdsParam = $input->getOption('role-ids');
|
||||
|
||||
if (empty($userId)) {
|
||||
$output->error('用户ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($roleIdsParam)) {
|
||||
$output->error('角色ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$admin = SystemAdmin::find($userId);
|
||||
if (empty($admin)) {
|
||||
$output->error('用户ID ' . $userId . ' 不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
$roleIds = $this->parseRoleIds($roleIdsParam);
|
||||
if (empty($roleIds)) {
|
||||
$output->error('角色ID列表为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
$validRoleIds = $this->validateRoleIds($roleIds);
|
||||
$invalidRoleIds = array_diff($roleIds, $validRoleIds);
|
||||
|
||||
if (!empty($invalidRoleIds)) {
|
||||
$invalidCount = count($invalidRoleIds);
|
||||
$output->error("[错误] 发现 {$invalidCount} 个无效的角色ID:");
|
||||
foreach (array_values($invalidRoleIds) as $roleId) {
|
||||
$output->error(" - {$roleId}");
|
||||
}
|
||||
$output->writeln('');
|
||||
}
|
||||
|
||||
if (empty($validRoleIds)) {
|
||||
$output->error("有效角色ID数: 0");
|
||||
$output->error("分配失败");
|
||||
return false;
|
||||
}
|
||||
|
||||
$existingAuthIds = $admin->auth_ids;
|
||||
$existingAuthIdArray = [];
|
||||
if (!empty($existingAuthIds)) {
|
||||
$existingAuthIdArray = array_filter(explode(',', $existingAuthIds));
|
||||
}
|
||||
|
||||
$newRoleIds = array_diff($validRoleIds, $existingAuthIdArray);
|
||||
|
||||
if (empty($newRoleIds)) {
|
||||
$output->info('所有角色已存在,无需重复分配');
|
||||
return true;
|
||||
}
|
||||
|
||||
$mergedRoleIds = array_merge($existingAuthIdArray, $newRoleIds);
|
||||
$mergedRoleIds = array_values(array_unique($mergedRoleIds));
|
||||
|
||||
$admin->auth_ids = implode(',', $mergedRoleIds);
|
||||
$admin->save();
|
||||
|
||||
$output->info('角色分配成功');
|
||||
$output->info('用户ID: ' . $userId);
|
||||
$output->info('新增的角色ID: ' . implode(', ', $newRoleIds));
|
||||
$output->info('该用户总角色数: ' . count($mergedRoleIds));
|
||||
$output->info('所有角色ID: ' . implode(', ', $mergedRoleIds));
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('分配角色失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function parseRoleIds(string $roleIdsParam): array
|
||||
{
|
||||
$roleIds = explode(',', $roleIdsParam);
|
||||
$roleIds = array_map('trim', $roleIds);
|
||||
$roleIds = array_filter($roleIds);
|
||||
|
||||
return array_values($roleIds);
|
||||
}
|
||||
|
||||
protected function validateRoleIds(array $roleIds): array
|
||||
{
|
||||
$validRoleIds = SystemAuth::whereIn('id', $roleIds)
|
||||
->where('delete_time', 0)
|
||||
->column('id');
|
||||
|
||||
return $validRoleIds;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\user;
|
||||
|
||||
use app\admin\model\SystemAdmin;
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminUserRoleListBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:user:role:list')
|
||||
->addOption('user-id', null, Option::VALUE_REQUIRED, '用户ID')
|
||||
->setDescription('查看用户角色');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$userId = $input->getOption('user-id');
|
||||
|
||||
if (empty($userId)) {
|
||||
$output->error('用户ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$user = SystemAdmin::find($userId);
|
||||
if (empty($user)) {
|
||||
$output->error('用户ID ' . $userId . ' 不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
$authIds = $user->auth_ids;
|
||||
$authIdArray = [];
|
||||
|
||||
if (!empty($authIds)) {
|
||||
$authIdArray = array_filter(explode(',', $authIds));
|
||||
}
|
||||
|
||||
if (empty($authIdArray)) {
|
||||
$output->info('用户角色列表');
|
||||
$output->writeln('================================');
|
||||
$output->info('用户ID: ' . $user->id);
|
||||
$output->info('用户名: ' . $user->username);
|
||||
$output->writeln('--------------------------------');
|
||||
$output->comment('该用户没有分配任何角色');
|
||||
return true;
|
||||
}
|
||||
|
||||
$roles = SystemAuth::whereIn('id', $authIdArray)
|
||||
->where('delete_time', 0)
|
||||
->field('id,title,status,remark')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$output->info('用户角色列表');
|
||||
$output->writeln('================================');
|
||||
$output->info('用户ID: ' . $user->id);
|
||||
$output->info('用户名: ' . $user->username);
|
||||
$output->writeln('--------------------------------');
|
||||
|
||||
if (empty($roles)) {
|
||||
$output->comment('没有找到有效的角色信息');
|
||||
} else {
|
||||
foreach ($roles as $role) {
|
||||
$statusText = $role['status'] == 1 ? '启用' : '禁用';
|
||||
$output->info('角色ID: ' . $role['id']);
|
||||
$output->comment(' 角色名称: ' . $role['title']);
|
||||
$output->comment(' 状态: ' . $statusText);
|
||||
if (!empty($role['remark'])) {
|
||||
$output->comment(' 备注: ' . $role['remark']);
|
||||
}
|
||||
$output->writeln('--------------------------------');
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('获取用户角色失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace base\common\command\admin\user;
|
||||
|
||||
use app\admin\model\SystemAdmin;
|
||||
use app\admin\model\SystemAuth;
|
||||
use app\common\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\input\Option;
|
||||
use think\console\Output;
|
||||
|
||||
class AdminUserRoleRevokeBase extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
parent::configure();
|
||||
|
||||
$this->setName('admin:user:role:revoke')
|
||||
->addOption('user-id', null, Option::VALUE_REQUIRED, '用户ID')
|
||||
->addOption('role-ids', null, Option::VALUE_REQUIRED, '角色ID列表(逗号分隔)')
|
||||
->setDescription('撤回用户角色');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
$userId = $input->getOption('user-id');
|
||||
$roleIdsParam = $input->getOption('role-ids');
|
||||
|
||||
if (empty($userId)) {
|
||||
$output->error('用户ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (empty($roleIdsParam)) {
|
||||
$output->error('角色ID不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$admin = SystemAdmin::find($userId);
|
||||
if (empty($admin)) {
|
||||
$output->error('用户ID ' . $userId . ' 不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
$roleIds = $this->parseRoleIds($roleIdsParam);
|
||||
if (empty($roleIds)) {
|
||||
$output->error('角色ID列表为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
$validRoleIds = $this->validateRoleIds($roleIds);
|
||||
$invalidRoleIds = array_diff($roleIds, $validRoleIds);
|
||||
|
||||
if (!empty($invalidRoleIds)) {
|
||||
$output->comment('警告: 以下角色ID无效: ' . implode(', ', array_values($invalidRoleIds)));
|
||||
}
|
||||
|
||||
if (empty($validRoleIds)) {
|
||||
$output->error('没有有效的角色ID');
|
||||
return false;
|
||||
}
|
||||
|
||||
$existingAuthIds = $admin->auth_ids;
|
||||
if (empty($existingAuthIds)) {
|
||||
$output->error('用户未分配任何角色,无法撤回');
|
||||
return false;
|
||||
}
|
||||
|
||||
$existingAuthIdArray = array_filter(explode(',', $existingAuthIds));
|
||||
|
||||
$revokedRoleIds = array_intersect($validRoleIds, $existingAuthIdArray);
|
||||
|
||||
if (empty($revokedRoleIds)) {
|
||||
$output->error('没有角色可以撤回(用户不拥有指定的角色)');
|
||||
return false;
|
||||
}
|
||||
|
||||
$remainingRoleIds = array_diff($existingAuthIdArray, $revokedRoleIds);
|
||||
$admin->auth_ids = empty($remainingRoleIds) ? '' : implode(',', $remainingRoleIds);
|
||||
$admin->save();
|
||||
|
||||
$output->info('角色撤回成功');
|
||||
$output->info('用户ID: ' . $userId);
|
||||
$output->info('撤回的角色ID: ' . implode(', ', $revokedRoleIds));
|
||||
$output->info('该用户剩余角色数: ' . count($remainingRoleIds));
|
||||
if (!empty($remainingRoleIds)) {
|
||||
$output->info('剩余角色ID: ' . implode(', ', $remainingRoleIds));
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$output->error('撤回角色失败: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function parseRoleIds(string $roleIdsParam): array
|
||||
{
|
||||
$roleIds = explode(',', $roleIdsParam);
|
||||
$roleIds = array_map('trim', $roleIds);
|
||||
$roleIds = array_filter($roleIds);
|
||||
|
||||
return array_values($roleIds);
|
||||
}
|
||||
|
||||
protected function validateRoleIds(array $roleIds): array
|
||||
{
|
||||
$validRoleIds = SystemAuth::whereIn('id', $roleIds)
|
||||
->where('delete_time', 0)
|
||||
->column('id');
|
||||
|
||||
return $validRoleIds;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user