feat(timer): 新增定时器配置、日志和主机的后台管理界面

T10: TimerConfig CURD - task management with run_type/status editing,
     manual trigger button, task_name read-only, no add/delete
T11: TimerLog CURD - read-only log viewer with filters and color badges
T12: Host list enhanced - is_master column, setMaster button
This commit is contained in:
augushong
2026-05-26 02:50:40 +08:00
parent 25fab093fa
commit 90e584f5a1
23 changed files with 943 additions and 18 deletions

View File

@@ -20,5 +20,26 @@ class HostBase extends AdminController
$this->model = new \app\admin\model\SystemHost();
$this->assign('select_list_status', $this->model::SELECT_LIST_STATUS, true);
$this->assign('select_list_is_master', $this->model::SELECT_LIST_IS_MASTER, true);
}
/**
* 设置主节点.
*
* @auth true
*/
public function setMaster()
{
$nodeId = $this->request->param('node_id', '');
if (empty($nodeId)) {
$this->error('参数错误');
}
$result = \app\common\service\HostService::setMasterNode($nodeId);
if ($result) {
$this->success('主节点切换成功');
} else {
$this->error('节点不存在');
}
}
}

View File

@@ -26,4 +26,6 @@ class SystemHostBase extends TimeModel
protected $deleteTime = false;
public const SELECT_LIST_STATUS = ['0' => '离线', '1' => '在线'];
public const SELECT_LIST_IS_MASTER = ['0' => '从节点', '1' => '主节点'];
}

View File

@@ -7,4 +7,5 @@ var init = {
deleteUrl: 'system.host/delete',
exportUrl: 'system.host/export',
modifyUrl: 'system.host/modify',
set_master_url: 'system.host/setMaster',
};

View File

@@ -7,6 +7,7 @@
data-auth-delete="{:auth('system.host/delete')}"
data-auth-export="{:auth('system.host/export')}"
data-auth-modify="{:auth('system.host/modify')}"
data-auth-set-master="{:auth('system.host/setMaster')}"
lay-filter="currentTable">
</table>
</div>

View File

@@ -1,10 +1,47 @@
$(function(){
ua.table.render({
init: init,
cols: [[
{type: 'checkbox'},
{field: 'id', title: 'ID'},
{field: 'node_id', title: '节点ID'},
{field: 'ip_address', title: 'IP地址'},
{field: 'status', search: 'select', selectList: ua.getDataBrage('select_list_status'), title: '状态', templet: ua.table.switch},
{field: 'last_heartbeat_at', title: '最后心跳时间'},
$(function(){
ua.table.render({
init: init,
cols: [[
{type: 'checkbox'},
{field: 'id', title: 'ID'},
{field: 'node_id', title: '节点ID'},
{field: 'ip_address', title: 'IP地址'},
{field: 'status', search: 'select', selectList: ua.getDataBrage('select_list_status'), title: '状态', templet: ua.table.switch},
{field: 'is_master', search: 'select', selectList: ua.getDataBrage('select_list_is_master'), title: '节点角色', templet: function(data) {
if (data.is_master == 1) {
return '<span class="layui-badge layui-bg-green">主节点</span>';
}
return '<span class="layui-badge layui-bg-gray">从节点</span>';
}},
{field: 'last_heartbeat_at', title: '最后心跳时间'},
{field: 'os_info', title: '系统信息'},
{field: 'php_version', title: 'PHP版本'},
{field: 'cpu_load', title: 'CPU负载'},
{field: 'memory_usage', title: '内存占用'},
{field: 'disk_free', title: '磁盘可用空间'},
{field: 'disk_total', title: '磁盘总空间'},
{field: 'create_time', title: '首次运行时间'},
{width: 300, title: '操作', templet: ua.table.tool, operat: [
'edit',
[{
text: '设为主节点',
url: init.set_master_url,
method: 'request',
field: function(data) {
return {node_id: data.node_id};
},
auth: 'set-master',
class: 'layui-btn layui-btn-xs layui-btn-warm',
title: '确认将该节点设为主节点?切换后原主节点将变为从节点。',
_if: function(data) {
return data.status == 1 && data.is_master != 1;
}
}],
'delete'
], fixed:'right'},
]],
});
ua.listen();
})