mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-09-05 07:15:31 +08:00
feat(mcp): MCP 调用日志只读列表页
This commit is contained in:
14
app/admin/controller/system/McpLog.php
Normal file
14
app/admin/controller/system/McpLog.php
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace app\admin\controller\system;
|
||||||
|
|
||||||
|
use app\admin\service\annotation\ControllerAnnotation;
|
||||||
|
use base\admin\controller\system\McpLogBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ControllerAnnotation(title="MCP调用日志",module="系统")
|
||||||
|
* Class McpLog
|
||||||
|
*/
|
||||||
|
class McpLog extends McpLogBase
|
||||||
|
{
|
||||||
|
}
|
||||||
86
extend/base/admin/controller/system/McpLogBase.php
Normal file
86
extend/base/admin/controller/system/McpLogBase.php
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace base\admin\controller\system;
|
||||||
|
|
||||||
|
use app\admin\model\SystemMcpKey;
|
||||||
|
use app\admin\model\SystemMcpLog;
|
||||||
|
use app\admin\service\annotation\ControllerAnnotation;
|
||||||
|
use app\admin\service\annotation\NodeAnotation;
|
||||||
|
use app\common\controller\AdminController;
|
||||||
|
use think\App;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MCP调用日志(只读列表).
|
||||||
|
* 日志仅由系统写入,不提供 add/edit/read/modify;
|
||||||
|
* 保留 delete 供清理旧日志。
|
||||||
|
*
|
||||||
|
* @ControllerAnnotation(title="MCP调用日志")
|
||||||
|
*/
|
||||||
|
class McpLogBase extends AdminController
|
||||||
|
{
|
||||||
|
protected $relationSearch = true;
|
||||||
|
|
||||||
|
protected $sort = [
|
||||||
|
'id' => 'desc',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(App $app)
|
||||||
|
{
|
||||||
|
parent::__construct($app);
|
||||||
|
|
||||||
|
$this->model = new SystemMcpLog();
|
||||||
|
|
||||||
|
// 密钥下拉(搜索用);SystemMcpKey 软删自动排除
|
||||||
|
$this->assign('select_list_mcp_key', SystemMcpKey::select(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NodeAnotation(title="列表")
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
if ($this->request->isAjax()) {
|
||||||
|
if (input('selectFields')) {
|
||||||
|
return $this->selectList();
|
||||||
|
}
|
||||||
|
list($page, $limit, $where) = $this->buildTableParames();
|
||||||
|
$count = $this->model
|
||||||
|
->withJoin('mcpKey', 'LEFT')
|
||||||
|
->where($where)
|
||||||
|
->count();
|
||||||
|
$list = $this->model
|
||||||
|
->withJoin('mcpKey', 'LEFT')
|
||||||
|
->where($where)
|
||||||
|
->page($page, $limit)
|
||||||
|
->order($this->sort)
|
||||||
|
->select();
|
||||||
|
$data = [
|
||||||
|
'code' => 0,
|
||||||
|
'msg' => '',
|
||||||
|
'count' => $count,
|
||||||
|
'data' => $list,
|
||||||
|
];
|
||||||
|
|
||||||
|
return json($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NodeAnotation(title="删除")
|
||||||
|
*/
|
||||||
|
public function delete($id)
|
||||||
|
{
|
||||||
|
$this->checkPostRequest();
|
||||||
|
$row = $this->model->whereIn('id', $id)->select();
|
||||||
|
$row->isEmpty() && $this->error('数据不存在');
|
||||||
|
try {
|
||||||
|
// 仅删除日志记录,不级联影响密钥表
|
||||||
|
$save = $row->delete();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->error('删除失败:' . $e->getMessage());
|
||||||
|
}
|
||||||
|
$save ? $this->success('删除成功') : $this->error('删除失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,9 +4,30 @@ namespace base\admin\model;
|
|||||||
|
|
||||||
use app\common\model\TimeModel;
|
use app\common\model\TimeModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property int $key_id 密钥ID
|
||||||
|
* @property string $node 节点
|
||||||
|
* @property string $arguments 参数摘要JSON
|
||||||
|
* @property int $is_success 是否成功 0:失败,1:成功
|
||||||
|
* @property int $cost_ms 耗时毫秒
|
||||||
|
* @property int $create_time 创建时间
|
||||||
|
* @property \app\admin\model\SystemMcpKey|null $mcpKey 密钥
|
||||||
|
*/
|
||||||
class SystemMcpLogBase extends TimeModel
|
class SystemMcpLogBase extends TimeModel
|
||||||
{
|
{
|
||||||
protected $updateTime = false;
|
protected $updateTime = false;
|
||||||
|
|
||||||
protected $deleteTime = false;
|
protected $deleteTime = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所属密钥.
|
||||||
|
* withJoin 为 LEFT JOIN 且不附加软删条件:
|
||||||
|
* 密钥不存在时关联字段为 null、软删密钥仍可 join 出(delete_time > 0),
|
||||||
|
* 前端据 mcp_key.title / mcp_key.delete_time 兜底显示"(已删除)#id"。
|
||||||
|
*/
|
||||||
|
public function mcpKey()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('app\admin\model\SystemMcpKey', 'key_id', 'id');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
extend/base/admin/view/system/mcp_log/_common.js
Normal file
11
extend/base/admin/view/system/mcp_log/_common.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
var init = {
|
||||||
|
tableElem: '#currentTable',
|
||||||
|
tableRenderId: 'currentTableRenderId',
|
||||||
|
indexUrl: 'system.mcp_log/index',
|
||||||
|
addUrl: '',
|
||||||
|
editUrl: '',
|
||||||
|
readUrl: '',
|
||||||
|
deleteUrl: 'system.mcp_log/delete',
|
||||||
|
exportUrl: '',
|
||||||
|
modifyUrl: '',
|
||||||
|
};
|
||||||
9
extend/base/admin/view/system/mcp_log/index.html
Normal file
9
extend/base/admin/view/system/mcp_log/index.html
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<div class="layuimini-container">
|
||||||
|
<div class="layuimini-main">
|
||||||
|
<table id="currentTable" class="layui-table layui-hide"
|
||||||
|
data-auth-index="{:auth('system.mcp_log/index')}"
|
||||||
|
data-auth-delete="{:auth('system.mcp_log/delete')}"
|
||||||
|
lay-filter="currentTable">
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
46
extend/base/admin/view/system/mcp_log/index.js
Normal file
46
extend/base/admin/view/system/mcp_log/index.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
$(function(){
|
||||||
|
// 密钥名称:LEFT JOIN 关联,密钥不存在或已软删时兜底显示
|
||||||
|
var keyNameTemplet = function(d) {
|
||||||
|
if (d.mcp_key && d.mcp_key.title && (!d.mcp_key.delete_time || d.mcp_key.delete_time === 0)) {
|
||||||
|
return d.mcp_key.title;
|
||||||
|
}
|
||||||
|
return '<span style="color:#999">(已删除)#' + d.key_id + '</span>';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 成功/失败徽章
|
||||||
|
var successTemplet = function(d) {
|
||||||
|
if (d.is_success == 1) {
|
||||||
|
return '<span style="display:inline-block;padding:2px 10px;border-radius:3px;color:#5FB878;background:#e8f8ef;font-size:12px;">成功</span>';
|
||||||
|
}
|
||||||
|
return '<span style="display:inline-block;padding:2px 10px;border-radius:3px;color:#FF5722;background:#ffe8e2;font-size:12px;">失败</span>';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 参数摘要:截断 200 字符,title 悬浮全文
|
||||||
|
var argumentsTemplet = function(d) {
|
||||||
|
if (!d.arguments) return '<span style="color:#999">-</span>';
|
||||||
|
var text = String(d.arguments);
|
||||||
|
var safe = text.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,''');
|
||||||
|
if (text.length > 200) {
|
||||||
|
return '<span title="' + safe + '" style="cursor:pointer;">' + safe.substring(0, 200) + '...</span>';
|
||||||
|
}
|
||||||
|
return safe;
|
||||||
|
};
|
||||||
|
|
||||||
|
ua.table.render({
|
||||||
|
init: init,
|
||||||
|
toolbar: ['refresh', 'delete'],
|
||||||
|
defaultToolbar: ['filter'],
|
||||||
|
cols: [[
|
||||||
|
{type: 'checkbox'},
|
||||||
|
{field: 'id', title: 'ID', width: 80, sort: true},
|
||||||
|
{field: 'key_id', title: '密钥', minWidth: 140, templet: keyNameTemplet, search: 'select', selectList: ua.getDataBrage('select_list_mcp_key'), selectValue: 'id', selectLabel: 'title'},
|
||||||
|
{field: 'node', title: '节点', minWidth: 180},
|
||||||
|
{field: 'is_success', title: '状态', width: 90, templet: successTemplet, search: 'select', selectList: {1: '成功', 0: '失败'}},
|
||||||
|
{field: 'cost_ms', title: '耗时(ms)', width: 100, search: false},
|
||||||
|
{field: 'arguments', title: '参数摘要', minWidth: 220, templet: argumentsTemplet, search: false},
|
||||||
|
{field: 'create_time', title: '调用时间', width: 170, templet: ua.table.date, search: 'range'},
|
||||||
|
]],
|
||||||
|
});
|
||||||
|
|
||||||
|
ua.listen();
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user