feat: 发布智能体版

This commit is contained in:
augushong
2026-03-26 20:22:34 +08:00
parent 7ee9e102a5
commit 8cc08bcb8c
138 changed files with 7964 additions and 660 deletions

View File

@@ -0,0 +1,199 @@
<?php
namespace base\common\command\tools\log;
use app\common\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
/**
* tools:log:search 命令基类
*/
class ToolsLogSearchBase extends Command
{
protected function configure()
{
parent::configure();
$this->setName('tools:log:search')
->setDescription('搜索数据库日志')
->addArgument('keywords', Argument::REQUIRED, '搜索关键词')
->addOption('level', 'l', Option::VALUE_OPTIONAL, '过滤日志级别 (info, warning, error)')
->addOption('limit', null, Option::VALUE_OPTIONAL, '限制显示条数', 50)
->addOption('controller', 'c', Option::VALUE_OPTIONAL, '过滤控制器名称')
->addOption('help', 'h', Option::VALUE_NONE, '显示帮助信息');
}
protected function execute($input, $output)
{
if ($input->getOption('help')) {
$this->showHelp($output);
return;
}
$keywords = $input->getArgument('keywords');
if (empty($keywords)) {
$output->error('请提供搜索关键词');
return;
}
$filters = $this->buildFilters($input);
$limit = (int)$input->getOption('limit') ?? 50;
try {
$query = Db::name('debug_log');
// 搜索关键词(在 content 字段中)
$query->whereLike('content', '%' . $keywords . '%');
// 应用过滤条件
if (!empty($filters['level'])) {
$query->where('level', '=', $filters['level']);
}
if (!empty($filters['controller'])) {
$query->whereLike('controller_name', '%' . $filters['controller'] . '%');
}
// 获取总数
$count = $query->count();
// 获取日志记录
$logs = $query->order('create_time', 'desc')
->limit($limit)
->select()
->toArray();
// 格式化时间戳并高亮关键词
foreach ($logs as &$log) {
if (!empty($log['create_time'])) {
$log['create_time_formatted'] = date('Y-m-d H:i:s', $log['create_time']);
}
// 高亮关键词
$log['content_highlighted'] = $this->highlightKeywords($log['content'] ?? '', $keywords);
}
unset($log);
$this->outputText($logs, $count, $keywords, $filters, $output);
} catch (\Exception $e) {
$output->error('搜索失败:' . $e->getMessage());
return;
}
}
/**
* 构建过滤条件
*/
protected function buildFilters(Input $input): array
{
return [
'level' => $input->getOption('level'),
'controller' => $input->getOption('controller')
];
}
/**
* 高亮关键词
*/
protected function highlightKeywords(string $content, string $keywords): string
{
// 使用 ANSI 颜色代码高亮关键词(仅用于文本模式)
return str_replace($keywords, '<comment>' . $keywords . '</comment>', $content);
}
/**
* 文本格式输出
*/
protected function outputText(array $logs, int $count, string $keywords, array $filters, Output $output): void
{
$output->newLine();
$output->info('=== 数据库日志搜索结果 ===');
$output->newLine();
$output->comment('搜索关键词:' . $keywords);
$output->newLine();
// 显示过滤条件
$activeFilters = array_filter($filters, function($value) {
return !empty($value);
});
if (!empty($activeFilters)) {
$output->comment('过滤条件:');
foreach ($activeFilters as $key => $value) {
$output->writeln(' - ' . $key . ': ' . $value);
}
$output->newLine();
}
if (empty($logs)) {
$output->comment('没有找到包含 "' . $keywords . '" 的日志');
return;
}
// 显示搜索结果
$output->info('搜索结果(共 ' . $count . ' 条,显示 ' . count($logs) . ' 条):');
$output->newLine();
foreach ($logs as $log) {
$levelMethod = $this->getLevelMethod($log['level'] ?? '');
$output->$levelMethod('[' . $log['level'] . '] ' .
'[' . ($log['create_time_formatted'] ?? 'N/A') . '] ' .
'[' . ($log['controller_name'] ?? '') . '::' . ($log['action_name'] ?? '') . ']');
// 显示内容并高亮关键词
$content = $log['content'] ?? '';
if (strlen($content) > 200) {
$content = substr($content, 0, 200) . '...';
}
$output->writeln(' ' . $this->highlightKeywords($content, $keywords));
$output->newLine();
}
}
/**
* 获取日志级别对应的方法名
*/
protected function getLevelMethod(string $level): string
{
$level = strtolower($level);
$methods = [
'error' => 'error',
'warning' => 'comment',
'info' => 'info',
'debug' => 'info'
];
return $methods[$level] ?? 'info';
}
/**
* 显示帮助信息
*/
protected function showHelp(Output $output): void
{
$output->newLine();
$output->info('命令名称:');
$output->writeln(' tools:log:search - 搜索数据库日志');
$output->newLine();
$output->info('用法:');
$output->writeln(' php think tools:log:search 关键词 [选项]');
$output->newLine();
$output->info('参数:');
$output->writeln(' keywords 搜索关键词(必填)');
$output->newLine();
$output->info('选项:');
$output->writeln(' -l, --level 过滤日志级别 (info, warning, error)');
$output->writeln(' --limit 限制显示条数 (默认: 50)');
$output->writeln(' -c, --controller 过滤控制器名称');
$output->writeln(' -h, --help 显示帮助信息');
$output->newLine();
$output->info('示例:');
$output->writeln(' php think tools:log:search "用户登录失败" --level=error');
$output->writeln(' php think tools:log:search "数据库连接" --controller=Admin --limit=20');
$output->writeln(' php think tools:log:search "Exception" --level=error');
$output->newLine();
}
}

View File

@@ -0,0 +1,195 @@
<?php
namespace base\common\command\tools\log;
use app\common\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
/**
* tools:log:show 命令基类
*/
class ToolsLogShowBase extends Command
{
protected function configure()
{
parent::configure();
$this->setName('tools:log:show')
->setDescription('查看数据库日志')
->addOption('level', 'l', Option::VALUE_OPTIONAL, '过滤日志级别 (info, warning, error)')
->addOption('limit', null, Option::VALUE_OPTIONAL, '限制显示条数', 50)
->addOption('controller', 'c', Option::VALUE_OPTIONAL, '过滤控制器名称')
->addOption('action', 'a', Option::VALUE_OPTIONAL, '过滤操作名称')
->addOption('start', 's', Option::VALUE_OPTIONAL, '开始时间 (Y-m-d H:i:s)')
->addOption('end', 'e', Option::VALUE_OPTIONAL, '结束时间 (Y-m-d H:i:s)')
->addOption('help', 'h', Option::VALUE_NONE, '显示帮助信息');
}
protected function execute($input, $output)
{
if ($input->getOption('help')) {
$this->showHelp($output);
return;
}
$filters = $this->buildFilters($input);
$limit = (int)$input->getOption('limit') ?? 50;
try {
$query = Db::name('debug_log');
// 应用过滤条件
if (!empty($filters['level'])) {
$query->where('level', '=', $filters['level']);
}
if (!empty($filters['controller'])) {
$query->whereLike('controller_name', '%' . $filters['controller'] . '%');
}
if (!empty($filters['action'])) {
$query->whereLike('action_name', '%' . $filters['action'] . '%');
}
if (!empty($filters['start'])) {
$startTime = strtotime($filters['start']);
if ($startTime !== false) {
$query->where('create_time', '>=', $startTime);
}
}
if (!empty($filters['end'])) {
$endTime = strtotime($filters['end']);
if ($endTime !== false) {
$query->where('create_time', '<=', $endTime);
}
}
// 获取总数
$count = $query->count();
// 获取日志记录
$logs = $query->order('create_time', 'desc')
->limit($limit)
->select()
->toArray();
// 格式化时间戳
foreach ($logs as &$log) {
if (!empty($log['create_time'])) {
$log['create_time_formatted'] = date('Y-m-d H:i:s', $log['create_time']);
}
}
unset($log);
$this->outputText($logs, $count, $filters, $output);
} catch (\Exception $e) {
$output->error('查询失败:' . $e->getMessage());
return;
}
}
/**
* 构建过滤条件
*/
protected function buildFilters(Input $input): array
{
return [
'level' => $input->getOption('level'),
'controller' => $input->getOption('controller'),
'action' => $input->getOption('action'),
'start' => $input->getOption('start'),
'end' => $input->getOption('end')
];
}
/**
* 文本格式输出
*/
protected function outputText(array $logs, int $count, array $filters, Output $output): void
{
$output->newLine();
$output->info('=== 数据库日志查询结果 ===');
$output->newLine();
// 显示过滤条件
$activeFilters = array_filter($filters, function($value) {
return !empty($value);
});
if (!empty($activeFilters)) {
$output->comment('过滤条件:');
foreach ($activeFilters as $key => $value) {
$output->writeln(' - ' . $key . ': ' . $value);
}
$output->newLine();
}
if (empty($logs)) {
$output->comment('没有找到符合条件的日志');
return;
}
// 显示日志列表
$output->info('日志列表(共 ' . $count . ' 条,显示 ' . count($logs) . ' 条):');
$output->newLine();
foreach ($logs as $log) {
$levelMethod = $this->getLevelMethod($log['level'] ?? '');
$output->$levelMethod('[' . $log['level'] . '] ' .
'[' . ($log['create_time_formatted'] ?? 'N/A') . '] ' .
'[' . ($log['controller_name'] ?? '') . '::' . ($log['action_name'] ?? '') . ']');
// 显示内容摘要
$content = $log['content'] ?? '';
if (strlen($content) > 200) {
$content = substr($content, 0, 200) . '...';
}
$output->writeln(' ' . $content);
$output->newLine();
}
}
/**
* 获取日志级别对应的方法名
*/
protected function getLevelMethod(string $level): string
{
$level = strtolower($level);
$methods = [
'error' => 'error',
'warning' => 'comment',
'info' => 'info',
'debug' => 'info'
];
return $methods[$level] ?? 'info';
}
/**
* 显示帮助信息
*/
protected function showHelp(Output $output): void
{
$output->newLine();
$output->info('命令名称:');
$output->writeln(' tools:log:show - 查看数据库日志');
$output->newLine();
$output->info('用法:');
$output->writeln(' php think tools:log:show [选项]');
$output->newLine();
$output->info('选项:');
$output->writeln(' -l, --level 过滤日志级别 (info, warning, error)');
$output->writeln(' --limit 限制显示条数 (默认: 50)');
$output->writeln(' -c, --controller 过滤控制器名称');
$output->writeln(' -a, --action 过滤操作名称');
$output->writeln(' -s, --start 开始时间 (Y-m-d H:i:s)');
$output->writeln(' -e, --end 结束时间 (Y-m-d H:i:s)');
$output->writeln(' -h, --help 显示帮助信息');
$output->newLine();
$output->info('示例:');
$output->writeln(' php think tools:log:show --level=error --limit=10');
$output->writeln(' php think tools:log:show --controller=Admin --limit=20');
$output->writeln(' php think tools:log:show --start="2024-01-01 00:00:00" --end="2024-12-31 23:59:59"');
$output->newLine();
}
}

View File

@@ -0,0 +1,259 @@
<?php
namespace base\common\command\tools\log;
use app\common\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\facade\Db;
/**
* tools:log:stats 命令基类
*/
class ToolsLogStatsBase extends Command
{
protected function configure()
{
parent::configure();
$this->setName('tools:log:stats')
->setDescription('统计数据库日志')
->addOption('by-level', null, Option::VALUE_NONE, '按日志级别统计')
->addOption('by-controller', null, Option::VALUE_NONE, '按控制器统计')
->addOption('by-time', null, Option::VALUE_NONE, '按时间统计')
->addOption('time-group', null, Option::VALUE_OPTIONAL, '时间分组 (hour|day|week|month)', 'day')
->addOption('help', 'h', Option::VALUE_NONE, '显示帮助信息');
}
protected function execute($input, $output)
{
if ($input->getOption('help')) {
$this->showHelp($output);
return;
}
$byLevel = $input->getOption('by-level');
$byController = $input->getOption('by-controller');
$byTime = $input->getOption('by-time');
$timeGroup = $input->getOption('time-group') ?? 'day';
// 如果没有指定任何统计类型,默认显示所有统计
if (!$byLevel && !$byController && !$byTime) {
$byLevel = $byController = $byTime = true;
}
try {
$stats = [
'by_level' => [],
'by_controller' => [],
'by_time' => []
];
// 按日志级别统计
if ($byLevel) {
$stats['by_level'] = $this->statsByLevel();
}
// 按控制器统计
if ($byController) {
$stats['by_controller'] = $this->statsByController();
}
// 按时间统计
if ($byTime) {
$stats['by_time'] = $this->statsByTime($timeGroup);
}
// 总数
$stats['total'] = Db::name('debug_log')->count();
$this->outputText($stats, $byLevel, $byController, $byTime, $output);
} catch (\Exception $e) {
$output->error('统计失败:' . $e->getMessage());
return;
}
}
/**
* 按日志级别统计
*/
protected function statsByLevel(): array
{
$results = Db::name('debug_log')
->field('level, COUNT(*) as count')
->group('level')
->select()
->toArray();
$stats = [];
foreach ($results as $row) {
$stats[$row['level']] = (int)$row['count'];
}
return $stats;
}
/**
* 按控制器统计
*/
protected function statsByController(): array
{
$results = Db::name('debug_log')
->field('controller_name, COUNT(*) as count')
->where('controller_name', '<>', '')
->group('controller_name')
->order('count', 'desc')
->limit(20)
->select()
->toArray();
$stats = [];
foreach ($results as $row) {
$stats[$row['controller_name']] = (int)$row['count'];
}
return $stats;
}
/**
* 按时间统计
*/
protected function statsByTime(string $group): array
{
$query = Db::name('debug_log');
// 根据分组类型格式化时间
switch ($group) {
case 'hour':
$dateFormat = '%Y-%m-%d %H:00';
$phpFormat = 'Y-m-d H:00';
break;
case 'week':
$dateFormat = '%Y-%u'; // 年-周数
$phpFormat = 'Y-W'; // 年-周数
break;
case 'month':
$dateFormat = '%Y-%m';
$phpFormat = 'Y-m';
break;
case 'day':
default:
$dateFormat = '%Y-%m-%d';
$phpFormat = 'Y-m-d';
break;
}
// 使用 MySQL DATE_FORMAT 函数
$results = $query->field('FROM_UNIXTIME(create_time, \'' . $dateFormat . '\') as time_period, COUNT(*) as count')
->where('create_time', '>', 0)
->group('time_period')
->order('time_period', 'desc')
->limit(30)
->select()
->toArray();
$stats = [];
foreach ($results as $row) {
$stats[$row['time_period']] = (int)$row['count'];
}
return $stats;
}
/**
* 文本格式输出
*/
protected function outputText(array $stats, bool $byLevel, bool $byController, bool $byTime, Output $output): void
{
$output->newLine();
$output->info('=== 数据库日志统计 ===');
$output->newLine();
// 总数
$output->info('总日志数:' . ($stats['total'] ?? 0));
$output->newLine();
// 按级别统计
if ($byLevel) {
$output->comment('按日志级别统计:');
if (empty($stats['by_level'])) {
$output->writeln(' 无数据');
} else {
foreach ($stats['by_level'] as $level => $count) {
$output->writeln(' ' . $level . '' . $count . ' 条');
}
}
$output->newLine();
}
// 按控制器统计
if ($byController) {
$output->comment('按控制器统计Top 20');
if (empty($stats['by_controller'])) {
$output->writeln(' 无数据');
} else {
foreach ($stats['by_controller'] as $controller => $count) {
$output->writeln(' ' . $controller . '' . $count . ' 条');
}
}
$output->newLine();
}
// 按时间统计
if ($byTime) {
$output->comment('按时间统计(最近 30 个时段):');
if (empty($stats['by_time'])) {
$output->writeln(' 无数据');
} else {
foreach ($stats['by_time'] as $timePeriod => $count) {
$output->writeln(' ' . $timePeriod . '' . $count . ' 条');
}
}
$output->newLine();
}
}
/**
* 获取日志级别对应的颜色
*/
protected function getLevelColor(string $level): string
{
$level = strtolower($level);
$colors = [
'error' => 'error',
'warning' => 'comment',
'info' => 'info',
'debug' => 'info'
];
return $colors[$level] ?? 'info';
}
/**
* 显示帮助信息
*/
protected function showHelp(Output $output): void
{
$output->newLine();
$output->info('命令名称:');
$output->writeln(' tools:log:stats - 统计数据库日志');
$output->newLine();
$output->info('用法:');
$output->writeln(' php think tools:log:stats [选项]');
$output->newLine();
$output->info('选项:');
$output->writeln(' --by-level 按日志级别统计');
$output->writeln(' --by-controller 按控制器统计');
$output->writeln(' --by-time 按时间统计');
$output->writeln(' --time-group 时间分组 (hour|day|week|month默认: day)');
$output->writeln(' -h, --help 显示帮助信息');
$output->newLine();
$output->info('示例:');
$output->writeln(' php think tools:log:stats');
$output->writeln(' php think tools:log:stats --by-level');
$output->writeln(' php think tools:log:stats --by-controller --by-time');
$output->writeln(' php think tools:log:stats --by-time --time-group=hour');
$output->newLine();
}
}