mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-08-30 04:35:33 +08:00
feat(mcp): MCP 管理菜单与分发迁移
This commit is contained in:
88
database/migrations/20260816204000_system_mcp_menu_seed.php
Normal file
88
database/migrations/20260816204000_system_mcp_menu_seed.php
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use think\migration\Migrator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MCP 管理菜单数据 - 「系统管理」分组追加两条
|
||||||
|
*
|
||||||
|
* 分发背景:基础菜单结构由框架内核数据 extend/base/admin/service/adminInitData/SystemMenu.php
|
||||||
|
* (显式 id 227~311,seed:run 时经 AdminInitService 写入)初始化;空库安装顺序为
|
||||||
|
* migrate:run 先于 seed:run,故本迁移使用显式 id 312/313 与内核 id 序列衔接,
|
||||||
|
* 保证 sort=0 组内排在「快捷入口」(id 252) 之后(菜单排序规则:sort DESC, id ASC),
|
||||||
|
* 即分组尾部;pid=228 为内核数据中「系统管理」分组的固定 id。
|
||||||
|
*
|
||||||
|
* 节点说明:auth_node 填控制器 index 节点(同 xhprof 菜单行 305~307 惯例),
|
||||||
|
* 菜单可见性由 MenuServiceBase::buildMenuChild 经 checkNode(auth_node) 精确校验;
|
||||||
|
* 动作级权限(add/edit/delete/authorize/saveAuthorize/read 等)由 auth 注解节点体系承担,
|
||||||
|
* 不在菜单 auth_node(char 100,单节点)表达。
|
||||||
|
*
|
||||||
|
* 幂等:system_menu.href 无唯一键,up 用存在性检查(href + delete_time=0)防重,
|
||||||
|
* 经 CLI(admin:menu:create)先行建行的环境重放为 no-op。
|
||||||
|
* down 与 up 对称:按 href 物理删除本迁移引入的两行。
|
||||||
|
*/
|
||||||
|
class SystemMcpMenuSeed extends Migrator
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$prefix = $this->getAdapter()->getOption('table_prefix');
|
||||||
|
$now = time();
|
||||||
|
$rows = [
|
||||||
|
[
|
||||||
|
'id' => 312,
|
||||||
|
'title' => 'MCP密钥管理',
|
||||||
|
'icon' => 'fa fa-key',
|
||||||
|
'href' => 'system.mcp_key/index',
|
||||||
|
'auth_node' => 'system.mcp_key/index',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'id' => 313,
|
||||||
|
'title' => 'MCP调用日志',
|
||||||
|
'icon' => 'fa fa-file-text-o',
|
||||||
|
'href' => 'system.mcp_log/index',
|
||||||
|
'auth_node' => 'system.mcp_log/index',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$href = $this->quoteLiteral($row['href']);
|
||||||
|
$exists = $this->fetchRow(
|
||||||
|
"SELECT `id` FROM `{$prefix}system_menu` WHERE `href` = {$href} AND `delete_time` = 0"
|
||||||
|
);
|
||||||
|
if (!empty($exists)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = sprintf(
|
||||||
|
"INSERT INTO `%ssystem_menu` (`id`, `pid`, `title`, `icon`, `href`, `auth_node`, `params`, `target`, `sort`, `status`, `remark`, `create_time`, `update_time`, `delete_time`)"
|
||||||
|
. " VALUES (%d, 228, %s, %s, %s, %s, '', '_self', 0, 1, '', %d, %d, 0)",
|
||||||
|
$prefix,
|
||||||
|
$row['id'],
|
||||||
|
$this->quoteLiteral($row['title']),
|
||||||
|
$this->quoteLiteral($row['icon']),
|
||||||
|
$this->quoteLiteral($row['href']),
|
||||||
|
$this->quoteLiteral($row['auth_node']),
|
||||||
|
$now,
|
||||||
|
$now
|
||||||
|
);
|
||||||
|
$this->execute($sql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
$prefix = $this->getAdapter()->getOption('table_prefix');
|
||||||
|
$hrefs = implode(', ', [
|
||||||
|
$this->quoteLiteral('system.mcp_key/index'),
|
||||||
|
$this->quoteLiteral('system.mcp_log/index'),
|
||||||
|
]);
|
||||||
|
$this->execute("DELETE FROM `{$prefix}system_menu` WHERE `href` IN ({$hrefs})");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MySQL 字面量包装:单引号包裹 + 反斜杠转义(照 XhprofWatchSeed 惯例).
|
||||||
|
*/
|
||||||
|
private function quoteLiteral(string $value): string
|
||||||
|
{
|
||||||
|
return "'" . addcslashes($value, "\\") . "'";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user