Files
augushong 90e584f5a1 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
2026-05-26 18:33:43 +08:00

100 lines
4.6 KiB
PHP

$(function(){
// 状态徽章模板
var statusTemplet = function(d) {
var statusMap = {
'success': {text: '成功', color: '#5FB878', bgColor: '#e8f8ef'},
'error': {text: '失败', color: '#FF5722', bgColor: '#ffe8e2'},
'running': {text: '运行中', color: '#1E9FFF', bgColor: '#e2f1ff'},
};
var item = statusMap[d.status] || {text: d.status, color: '#999', bgColor: '#f5f5f5'};
return '<span style="display:inline-block;padding:2px 10px;border-radius:3px;color:'+item.color+';background:'+item.bgColor+';font-size:12px;">'+item.text+'</span>';
};
// 时间格式化模板
var timeTemplet = function(d) {
if (!d.start_time || d.start_time === 0) return '<span style="color:#999">-</span>';
var date = new Date(d.start_time * 1000);
var Y = date.getFullYear();
var M = (date.getMonth()+1).toString().padStart(2,'0');
var D = date.getDate().toString().padStart(2,'0');
var h = date.getHours().toString().padStart(2,'0');
var m = date.getMinutes().toString().padStart(2,'0');
var s = date.getSeconds().toString().padStart(2,'0');
return Y+'-'+M+'-'+D+' '+h+':'+m+':'+s;
};
var endTimeTemplet = function(d) {
if (!d.end_time || d.end_time === 0) return '<span style="color:#999">-</span>';
var date = new Date(d.end_time * 1000);
var Y = date.getFullYear();
var M = (date.getMonth()+1).toString().padStart(2,'0');
var D = date.getDate().toString().padStart(2,'0');
var h = date.getHours().toString().padStart(2,'0');
var m = date.getMinutes().toString().padStart(2,'0');
var s = date.getSeconds().toString().padStart(2,'0');
return Y+'-'+M+'-'+D+' '+h+':'+m+':'+s;
};
// 耗时格式化模板
var durationTemplet = function(d) {
if (!d.duration || d.duration === 0) return '<span style="color:#999">-</span>';
if (d.duration < 1000) {
return d.duration + ' ms';
}
return (d.duration / 1000).toFixed(2) + ' s';
};
// 错误信息截断模板
var errorMsgTemplet = function(d) {
if (!d.error_message) return '<span style="color:#999">-</span>';
var text = d.error_message;
if (text.length > 50) {
return '<span title="'+text.replace(/"/g,'&quot;').replace(/'/g,'&#39;')+'" style="cursor:pointer;" lay-event="showError">'+text.substring(0,50)+'...</span>';
}
return text;
};
ua.table.render({
init: init,
cols: [[
{type: 'checkbox'},
{field: 'id', title: 'ID', width: 80, sort: true},
{field: 'task_name', title: '任务名称', width: 160, search: 'select', searchUrl: 'system.timer_log/index?selectFields=task_name'},
{field: 'node_id', title: '节点ID', width: 120, search: 'select', searchUrl: 'system.timer_log/index?selectFields=node_id'},
{field: 'run_type', title: '运行类型', width: 100},
{field: 'start_time', title: '开始时间', width: 170, templet: timeTemplet, search: 'range'},
{field: 'end_time', title: '结束时间', width: 170, templet: endTimeTemplet},
{field: 'duration', title: '耗时', width: 100, templet: durationTemplet},
{field: 'status', title: '状态', width: 100, templet: statusTemplet, search: 'select', selectList: {success:'成功', error:'失败', running:'运行中'}},
{field: 'error_message', title: '错误信息', minWidth: 200, templet: errorMsgTemplet},
{
width: 100, title: '操作', templet: ua.table.tool, fixed: 'right', operat: [
[{
class: 'layui-btn layui-btn-primary layui-btn-xs',
method: 'tab',
field: 'id',
text: '详情',
title: '查看详情',
auth: 'read',
url: init.readUrl,
icon: ''
}]
]
},
]],
});
// 点击错误信息查看完整内容
ua.table.on('tool(currentTable)', function(obj) {
if (obj.event === 'showError') {
var text = obj.data.error_message || '';
layer.alert('<pre style="white-space:pre-wrap;word-break:break-all;max-height:400px;overflow-y:auto;">'+text.replace(/</g,'&lt;').replace(/>/g,'&gt;')+'</pre>', {
title: '错误信息详情',
area: ['600px', '400px']
});
}
});
ua.listen();
})