mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-08-30 12:45:32 +08:00
- 跑 admin:permission:nodes 扫描 138 个权限节点(17 个 nginx 相关节点)
- 17 个 nginx 节点 assign 给 role-id=1(写入 ul_system_auth_node 满足 plan 验收)
- curd 路径修复:菜单 href 由 system.nginx_access_log/index 改为 nginx.access_log/index(匹配 curd 生成的实际 URL,方案 B)
- SystemMenu.php / v2.4.0.php / DB ul_system_menu 三处同步(含 id=303 log_position)
- dashboard id=301 system.nginx_log_stat/index 保持不变(控制器确实在 system 模块)
- 端到端 QA 全通过:100 行日志 → import 74 行(静态过滤)→ aggregate stat_hour=1/url=6 → dashboard 数据完整
- 修复 T10 遗留 bug:cleanStatTables 用 Unix 时间戳当阈值,与 stat_date YYYYMMDD 不匹配导致误删
- threshold 从 strtotime('today')-days*86400 改为 (int) date('Ymd', strtotime('today')-days*86400)
- 验证:366 天前 stat 数据被删,今天 stat 数据保留
- 权限隔离:超管可访问,未登录被拦(code=40101 请先登录后台)
- Evidence: .omo/evidence/task-16-nginx-log-analytics-e2e/(15 个文件)
196 lines
6.7 KiB
PHP
196 lines
6.7 KiB
PHP
<?php
|
||
/**
|
||
* @internal-framework
|
||
*
|
||
* 此文件为框架内置功能
|
||
*
|
||
* 用途:框架版本更新代码(v2.4.0)- nginx_log 分析模块存量升级
|
||
* 维护者:框架维护者
|
||
*
|
||
* 变更:
|
||
* - system_config 新增 nginx_log 组 4 条运行参数配置
|
||
* raw_retention_days 原始日志保留天数(0=永久)
|
||
* stat_retention_days 统计聚合保留天数(0=永久)
|
||
* topn_default Top N 默认值
|
||
* exclude_static 是否排除静态资源访问
|
||
* - system_menu 新增 4 条菜单(顶级分组 300 + 3 个子菜单 301/302/303)
|
||
* 300 Nginx 日志分析(顶级分组,href 为空)
|
||
* 301 访问统计仪表盘 system.nginx_log_stat/index
|
||
* 302 原始访问日志 nginx.access_log/index
|
||
* 303 读取位置管理 nginx.log_position/index
|
||
*
|
||
* 设计说明:
|
||
* - 幂等 check-then-insert(先查询存在性,不存在才插入)
|
||
* - 不分配超管权限:AuthServiceBase::isSuperAdmin() 对 admin_id=1 直接返回 true,
|
||
* 为 auth_id=1 植入 system_auth_node 是冗余且无效
|
||
* - 不直接植入权限节点:节点由 admin:permission:nodes 扫描控制器 @NodeAnotation 注解生成
|
||
*
|
||
* 注意:此文件属于框架内核,业务开发者不应修改
|
||
*/
|
||
|
||
use think\console\Input;
|
||
use think\console\Output;
|
||
use think\facade\Db;
|
||
|
||
class UpdateFunction
|
||
{
|
||
/**
|
||
* @var Input
|
||
*/
|
||
public $input;
|
||
|
||
/**
|
||
* @var Output
|
||
*/
|
||
public $output;
|
||
|
||
/**
|
||
* 待新增 sysconfig 配置(nginx_log 组).
|
||
* 字段顺序与 adminInitData/SystemConfig.php 一致:name/group/value/remark/sort.
|
||
*/
|
||
public $newConfigs = [
|
||
[
|
||
'name' => 'raw_retention_days',
|
||
'group' => 'nginx_log',
|
||
'value' => '7',
|
||
'remark' => '原始日志保留天数(0=永久)',
|
||
'sort' => 0,
|
||
],
|
||
[
|
||
'name' => 'stat_retention_days',
|
||
'group' => 'nginx_log',
|
||
'value' => '365',
|
||
'remark' => '统计聚合保留天数(0=永久)',
|
||
'sort' => 0,
|
||
],
|
||
[
|
||
'name' => 'topn_default',
|
||
'group' => 'nginx_log',
|
||
'value' => '10',
|
||
'remark' => 'Top N 默认值(热门 URL/Referer/UA)',
|
||
'sort' => 0,
|
||
],
|
||
[
|
||
'name' => 'exclude_static',
|
||
'group' => 'nginx_log',
|
||
'value' => '1',
|
||
'remark' => '是否排除静态资源访问(0=不排除,1=排除 /css/.js/.png 等扩展名)',
|
||
'sort' => 0,
|
||
],
|
||
];
|
||
|
||
/**
|
||
* 待新增菜单.
|
||
* 字段顺序与 adminInitData/SystemMenu.php 一致:id/pid/title/icon/href/params/target/sort/status.
|
||
* id 显式分配 300-303,与 adminInitData 保持一致(顶级 300 + 3 个子菜单)。
|
||
*/
|
||
public $newMenus = [
|
||
[
|
||
'id' => 300,
|
||
'pid' => 0,
|
||
'title' => 'Nginx 日志分析',
|
||
'icon' => 'fa fa-chart-bar',
|
||
'href' => '',
|
||
'params' => '',
|
||
'target' => '_self',
|
||
'sort' => 0,
|
||
'status' => 1,
|
||
],
|
||
[
|
||
'id' => 301,
|
||
'pid' => 300,
|
||
'title' => '访问统计仪表盘',
|
||
'icon' => 'fa fa-line-chart',
|
||
'href' => 'system.nginx_log_stat/index',
|
||
'params' => '',
|
||
'target' => '_self',
|
||
'sort' => 0,
|
||
'status' => 1,
|
||
],
|
||
[
|
||
'id' => 302,
|
||
'pid' => 300,
|
||
'title' => '原始访问日志',
|
||
'icon' => 'fa fa-file-text',
|
||
'href' => 'nginx.access_log/index',
|
||
'params' => '',
|
||
'target' => '_self',
|
||
'sort' => 0,
|
||
'status' => 1,
|
||
],
|
||
[
|
||
'id' => 303,
|
||
'pid' => 300,
|
||
'title' => '读取位置管理',
|
||
'icon' => 'fa fa-map-marker',
|
||
'href' => 'nginx.log_position/index',
|
||
'params' => '',
|
||
'target' => '_self',
|
||
'sort' => 0,
|
||
'status' => 1,
|
||
],
|
||
];
|
||
|
||
public function update()
|
||
{
|
||
$this->output->writeln('更新代码');
|
||
|
||
$this->output->info('v2.4.0:nginx_log 分析模块存量升级(补齐 4 条 sysconfig + 4 条菜单)');
|
||
|
||
$configTable = config('database.connections.mysql.prefix', 'ul_') . 'system_config';
|
||
$menuTable = config('database.connections.mysql.prefix', 'ul_') . 'system_menu';
|
||
|
||
// 确认表存在(防御性检查,参照 v2.3.0.php 范式)
|
||
$tablesExist = Db::query(
|
||
"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME IN (?, ?)",
|
||
[$configTable, $menuTable]
|
||
);
|
||
if (count($tablesExist) < 2) {
|
||
$this->output->warning("表 {$configTable} 或 {$menuTable} 不存在,跳过数据补齐。请先执行 scheme:sync 或 migrate:run 初始化表结构。");
|
||
|
||
return;
|
||
}
|
||
|
||
$configAdded = 0;
|
||
$configSkipped = 0;
|
||
foreach ($this->newConfigs as $cfg) {
|
||
// 幂等:用 (group, name) 检查存在性
|
||
$exists = Db::name('system_config')
|
||
->where('group', $cfg['group'])
|
||
->where('name', $cfg['name'])
|
||
->find();
|
||
if ($exists) {
|
||
$this->output->writeln(" - 配置 {$cfg['group']}.{$cfg['name']} 已存在,跳过");
|
||
++$configSkipped;
|
||
continue;
|
||
}
|
||
|
||
Db::name('system_config')->insert($cfg);
|
||
$this->output->writeln(" - 新增配置 {$cfg['group']}.{$cfg['name']} 完成");
|
||
++$configAdded;
|
||
}
|
||
|
||
$menuAdded = 0;
|
||
$menuSkipped = 0;
|
||
foreach ($this->newMenus as $menu) {
|
||
// 幂等:用 id 检查存在性(顶级菜单 href 为空,不能用 href 去重)
|
||
$exists = Db::name('system_menu')
|
||
->where('id', $menu['id'])
|
||
->find();
|
||
if ($exists) {
|
||
$this->output->writeln(" - 菜单 id={$menu['id']} ({$menu['title']}) 已存在,跳过");
|
||
++$menuSkipped;
|
||
continue;
|
||
}
|
||
|
||
Db::name('system_menu')->insert($menu);
|
||
$this->output->writeln(" - 新增菜单 id={$menu['id']} ({$menu['title']}) 完成");
|
||
++$menuAdded;
|
||
}
|
||
|
||
$totalSkipped = $configSkipped + $menuSkipped;
|
||
$this->output->info("本次新增 {$configAdded} 条配置、{$menuAdded} 条菜单,跳过 {$totalSkipped} 条已存在");
|
||
$this->output->writeln('更新代码完成');
|
||
}
|
||
}
|