diff --git a/app/admin/controller/system/TimerConfig.php b/app/admin/controller/system/TimerConfig.php
new file mode 100644
index 0000000..b38859b
--- /dev/null
+++ b/app/admin/controller/system/TimerConfig.php
@@ -0,0 +1,97 @@
+model = new \app\admin\model\SystemTimerConfig();
+
+ $this->assign('select_list_run_type', $this->model::SELECT_LIST_RUN_TYPE, true);
+ $this->assign('select_list_status', $this->model::SELECT_LIST_STATUS, true);
+ $this->assign('select_list_is_synced', $this->model::SELECT_LIST_IS_SYNCED, true);
+ $this->assign('select_list_manual_trigger', $this->model::SELECT_LIST_MANUAL_TRIGGER, true);
+
+ // 允许通过行内修改的字段
+ $this->allowModifyFields = [
+ 'status',
+ 'run_type',
+ ];
+ }
+
+ /**
+ * @NodeAnotation(title="添加")
+ */
+ public function add()
+ {
+ $this->error('定时任务配置由系统同步生成,不支持手动添加');
+ }
+
+ /**
+ * @NodeAnotation(title="删除")
+ */
+ public function delete($id)
+ {
+ $this->error('定时任务配置由系统管理,不支持删除');
+ }
+
+ /**
+ * @NodeAnotation(title="编辑")
+ */
+ public function edit($id)
+ {
+ $row = $this->model->find($id);
+ empty($row) && $this->error('数据不存在');
+ if ($this->request->isPost()) {
+ $post = $this->request->post();
+ // 只允许修改 run_type 和 status
+ $post = array_intersect_key($post, array_flip(['run_type', 'status']));
+ try {
+ $save = $row->save($post);
+ } catch (\Exception $e) {
+ $this->error('保存失败:' . $e->getMessage());
+ }
+ $save ? $this->success('保存成功') : $this->error('保存失败');
+ }
+ $this->assign('row', $row);
+
+ return $this->fetch();
+ }
+
+ /**
+ * @NodeAnotation(title="手动触发")
+ */
+ public function trigger($id)
+ {
+ $this->checkPostRequest();
+ $row = $this->model->find($id);
+ if (!$row) {
+ $this->error('数据不存在');
+ }
+ if ($row->getAttr('run_type') !== 'manual') {
+ $this->error('只有manual类型的任务支持手动触发');
+ }
+ if ($row->getAttr('status') != 1) {
+ $this->error('任务已停用,请先启用');
+ }
+ try {
+ $row->save(['manual_trigger' => 1]);
+ } catch (\Exception $e) {
+ $this->error('触发失败:' . $e->getMessage());
+ }
+ $this->success('触发成功,等待定时器执行');
+ }
+}
diff --git a/app/admin/controller/system/TimerLog.php b/app/admin/controller/system/TimerLog.php
new file mode 100644
index 0000000..820a37b
--- /dev/null
+++ b/app/admin/controller/system/TimerLog.php
@@ -0,0 +1,109 @@
+ 'desc',
+ ];
+
+ public function __construct(App $app)
+ {
+ parent::__construct($app);
+
+ $this->model = new \app\admin\model\SystemTimerLog();
+ }
+
+ /**
+ * @NodeAnotation(title="列表")
+ */
+ public function index()
+ {
+ if ($this->request->isAjax()) {
+ if (input('selectFields')) {
+ return $this->selectList();
+ }
+ list($page, $limit, $where, $excludes, $request_options, $group) = $this->buildTableParames();
+ $count = $this->model
+ ->where($where)
+ ->group($group)
+ ->count();
+ $list = $this->model
+ ->where($where)
+ ->page($page, $limit)
+ ->order($this->sort)
+ ->group($group)
+ ->select();
+ $data = [
+ 'code' => 0,
+ 'msg' => '',
+ 'count' => $count,
+ 'data' => $list,
+ ];
+
+ return json($data);
+ }
+
+ return $this->fetch();
+ }
+
+ /**
+ * @NodeAnotation(title="详情")
+ */
+ public function read($id)
+ {
+ $row = $this->model->find($id);
+ empty($row) && $this->error('数据不存在');
+
+ $title = $row->title;
+
+ $this->assign('row', $row);
+ $this->assign('title', $title);
+
+ return $this->fetch();
+ }
+
+ /**
+ * @NodeAnotation(title="添加")
+ */
+ public function add()
+ {
+ $this->error('日志表不允许手动添加');
+ }
+
+ /**
+ * @NodeAnotation(title="编辑")
+ */
+ public function edit($id)
+ {
+ $this->error('日志表不允许编辑');
+ }
+
+ /**
+ * @NodeAnotation(title="删除")
+ */
+ public function delete($id)
+ {
+ $this->error('日志表不允许删除');
+ }
+
+ /**
+ * @NodeAnotation(title="属性修改")
+ */
+ public function modify()
+ {
+ $this->error('日志表不允许修改');
+ }
+}
diff --git a/app/admin/model/SystemTimerConfig.php b/app/admin/model/SystemTimerConfig.php
index c32d62a..7f2dd3c 100644
--- a/app/admin/model/SystemTimerConfig.php
+++ b/app/admin/model/SystemTimerConfig.php
@@ -2,11 +2,36 @@
namespace app\admin\model;
-use think\Model;
+use app\common\model\TimeModel;
-class SystemTimerConfig extends Model
+/**
+ * @property int $id
+ * @property string $task_name 任务名称
+ * @property string $run_type 运行类型:main/auto/all/manual main:main,auto:auto,all:all,manual:manual
+ * @property int $status 状态:0=停用,1=启用 0:停用,1:启用
+ * @property int $is_synced 是否已同步:0=未同步,1=已同步 0:未同步,1:已同步
+ * @property string $last_execute_node 最后执行节点ID
+ * @property int $last_execute_time 最后执行时间戳
+ * @property int $manual_trigger 手动触发标记:0=未触发,1=已触发 0:未触发,1:已触发
+ * @property int $create_time 创建时间
+ */
+class SystemTimerConfig extends TimeModel
{
- protected $name = 'system_timer_config';
- protected $autoWriteTimestamp = true;
+ protected $name = "system_timer_config";
+
+ protected $deleteTime = false;
+
+
+ public const SELECT_LIST_RUN_TYPE = ['main' => 'main', 'auto' => 'auto', 'all' => 'all', 'manual' => 'manual'];
+
+ public const SELECT_LIST_STATUS = ['0' => '停用', '1' => '启用'];
+
+ public const SELECT_LIST_IS_SYNCED = ['0' => '未同步', '1' => '已同步'];
+
+ public const SELECT_LIST_MANUAL_TRIGGER = ['0' => '未触发', '1' => '已触发'];
+
+
+
+
}
diff --git a/app/admin/model/SystemTimerLog.php b/app/admin/model/SystemTimerLog.php
index 2771d6c..221b720 100644
--- a/app/admin/model/SystemTimerLog.php
+++ b/app/admin/model/SystemTimerLog.php
@@ -2,11 +2,30 @@
namespace app\admin\model;
-use think\Model;
+use app\common\model\TimeModel;
-class SystemTimerLog extends Model
+/**
+ * @property int $id
+ * @property string $task_name 任务名称
+ * @property string $node_id 执行节点ID
+ * @property string $run_type 运行类型
+ * @property int $start_time 开始时间戳
+ * @property int $end_time 结束时间戳
+ * @property int $duration 耗时
+ * @property string $status 状态:running/success/error
+ * @property string $error_message 错误信息
+ * @property int $concurrency_id 并发分片ID
+ * @property int $create_time 创建时间
+ */
+class SystemTimerLog extends TimeModel
{
- protected $name = 'system_timer_log';
- protected $autoWriteTimestamp = true;
+ protected $name = "system_timer_log";
+
+ protected $deleteTime = false;
+
+
+
+
+
}
diff --git a/app/admin/view/system/timer_config/_common.js b/app/admin/view/system/timer_config/_common.js
new file mode 100644
index 0000000..a9aa393
--- /dev/null
+++ b/app/admin/view/system/timer_config/_common.js
@@ -0,0 +1,12 @@
+var init = {
+ tableElem: '#currentTable',
+ tableRenderId: 'currentTableRenderId',
+ indexUrl: 'system.timer_config/index',
+ addUrl: 'system.timer_config/add' + location.search,
+ editUrl: 'system.timer_config/edit',
+ readUrl: 'system.timer_config/read',
+ deleteUrl: 'system.timer_config/delete',
+ exportUrl: 'system.timer_config/export',
+ modifyUrl: 'system.timer_config/modify',
+ triggerUrl: 'system.timer_config/trigger',
+};
diff --git a/app/admin/view/system/timer_config/add.html b/app/admin/view/system/timer_config/add.html
new file mode 100644
index 0000000..eeee5ae
--- /dev/null
+++ b/app/admin/view/system/timer_config/add.html
@@ -0,0 +1,70 @@
+
\ No newline at end of file
diff --git a/app/admin/view/system/timer_config/add.js b/app/admin/view/system/timer_config/add.js
new file mode 100644
index 0000000..4a445e0
--- /dev/null
+++ b/app/admin/view/system/timer_config/add.js
@@ -0,0 +1,3 @@
+$(function(){
+ ua.listen();
+})
\ No newline at end of file
diff --git a/app/admin/view/system/timer_config/edit.html b/app/admin/view/system/timer_config/edit.html
new file mode 100644
index 0000000..43e4852
--- /dev/null
+++ b/app/admin/view/system/timer_config/edit.html
@@ -0,0 +1,69 @@
+
diff --git a/app/admin/view/system/timer_config/edit.js b/app/admin/view/system/timer_config/edit.js
new file mode 100644
index 0000000..4a445e0
--- /dev/null
+++ b/app/admin/view/system/timer_config/edit.js
@@ -0,0 +1,3 @@
+$(function(){
+ ua.listen();
+})
\ No newline at end of file
diff --git a/app/admin/view/system/timer_config/index.html b/app/admin/view/system/timer_config/index.html
new file mode 100644
index 0000000..e1a373d
--- /dev/null
+++ b/app/admin/view/system/timer_config/index.html
@@ -0,0 +1,11 @@
+
diff --git a/app/admin/view/system/timer_config/index.js b/app/admin/view/system/timer_config/index.js
new file mode 100644
index 0000000..748db9a
--- /dev/null
+++ b/app/admin/view/system/timer_config/index.js
@@ -0,0 +1,78 @@
+$(function(){
+ ua.table.render({
+ init: init,
+ cols: [[
+ {type: 'checkbox'},
+ {field: 'id', title: 'ID', width: 80},
+ {field: 'task_name', title: '任务名称', minWidth: 160},
+ {field: 'run_type', search: 'select', selectList: ua.getDataBrage('select_list_run_type'), title: '运行类型', width: 130, templet: function(d){
+ var map = ua.getDataBrage('select_list_run_type');
+ return map[d.run_type] || d.run_type;
+ }},
+ {field: 'status', search: 'select', selectList: ua.getDataBrage('select_list_status'), title: '状态', width: 100, templet: ua.table.switch},
+ {field: 'is_synced', search: 'select', selectList: ua.getDataBrage('select_list_is_synced'), title: '同步状态', width: 100, templet: function(d){
+ if(d.is_synced == 1){
+ return '已同步';
+ }
+ return '未同步';
+ }},
+ {field: 'last_execute_node', title: '最后执行节点', width: 140},
+ {field: 'last_execute_time', title: '最后执行时间', width: 170, templet: function(d){
+ if(!d.last_execute_time || d.last_execute_time == 0){
+ return '暂无';
+ }
+ var date = new Date(d.last_execute_time * 1000);
+ var Y = date.getFullYear();
+ var m = ('0' + (date.getMonth()+1)).slice(-2);
+ var day = ('0' + date.getDate()).slice(-2);
+ var H = ('0' + date.getHours()).slice(-2);
+ var i = ('0' + date.getMinutes()).slice(-2);
+ var s = ('0' + date.getSeconds()).slice(-2);
+ return Y+'-'+m+'-'+day+' '+H+':'+i+':'+s;
+ }},
+ {
+ width: 200, 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: ''
+ }],
+ 'edit',
+ [{
+ class: 'layui-btn layui-btn-warm layui-btn-xs',
+ method: 'request',
+ field: 'id',
+ text: '触发',
+ title: '手动触发',
+ auth: 'trigger',
+ url: init.triggerUrl,
+ icon: '',
+ extend: '',
+ callback: function(o){
+ // 只对 manual 类型显示,通过 CSS 控制显隐
+ }
+ }]
+ ]
+ },
+
+ ]],
+ });
+
+ // 控制触发按钮显隐:只有 run_type=manual 时显示
+ ua.listen();
+
+ // 监听表格渲染完成后处理触发按钮显隐
+ $(document).on('renderComplete', function(){
+ $('table tbody tr').each(function(){
+ var runType = $(this).find('td[data-field="run_type"] .layui-table-cell').text().trim();
+ if(runType !== 'manual'){
+ $(this).find('.layui-btn[title="手动触发"]').hide();
+ }
+ });
+ });
+})
diff --git a/app/admin/view/system/timer_config/read.html b/app/admin/view/system/timer_config/read.html
new file mode 100644
index 0000000..83c9987
--- /dev/null
+++ b/app/admin/view/system/timer_config/read.html
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
任务名称
+
+ {notempty name="row.task_name"}
+ {$row.task_name}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
运行类型
+
+ {$select_list_run_type[$row.run_type]|default=''}
+
+
+
+
同步状态
+
+ {if $row.is_synced == 1}
+ 已同步
+ {else/}
+ 未同步
+ {/if}
+
+
+
+
最后执行节点
+
+ {notempty name="row.last_execute_node"}
+ {$row.last_execute_node}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
最后执行时间
+
+ {notempty name="row.last_execute_time"}
+ {$row.last_execute_time|date="Y-m-d H:i:s"}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
手动触发标记
+
+ {$select_list_manual_trigger[$row.manual_trigger]|default=''}
+
+
+
+
+
+
基础信息
+
+
+
+
状态
+
+ {$select_list_status[$row.status]|default=''}
+
+
+
+
创建时间
+
+ {notempty name="row.create_time"}
+ {$row.create_time|date="Y-m-d H:i:s"}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
+
+
+
+
+
diff --git a/app/admin/view/system/timer_config/read.js b/app/admin/view/system/timer_config/read.js
new file mode 100644
index 0000000..81a35d4
--- /dev/null
+++ b/app/admin/view/system/timer_config/read.js
@@ -0,0 +1,3 @@
+$(function(){
+ ua.listen();
+})
diff --git a/app/admin/view/system/timer_log/_common.js b/app/admin/view/system/timer_log/_common.js
new file mode 100644
index 0000000..1c140a5
--- /dev/null
+++ b/app/admin/view/system/timer_log/_common.js
@@ -0,0 +1,11 @@
+var init = {
+ tableElem: '#currentTable',
+ tableRenderId: 'currentTableRenderId',
+ indexUrl: 'system.timer_log/index',
+ addUrl: '',
+ editUrl: '',
+ readUrl: 'system.timer_log/read',
+ deleteUrl: '',
+ exportUrl: '',
+ modifyUrl: '',
+};
diff --git a/app/admin/view/system/timer_log/index.html b/app/admin/view/system/timer_log/index.html
new file mode 100644
index 0000000..4498cc3
--- /dev/null
+++ b/app/admin/view/system/timer_log/index.html
@@ -0,0 +1,9 @@
+
diff --git a/app/admin/view/system/timer_log/index.js b/app/admin/view/system/timer_log/index.js
new file mode 100644
index 0000000..af6f874
--- /dev/null
+++ b/app/admin/view/system/timer_log/index.js
@@ -0,0 +1,99 @@
+$(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 ''+item.text+'';
+ };
+
+ // 时间格式化模板
+ var timeTemplet = function(d) {
+ if (!d.start_time || d.start_time === 0) return '-';
+ 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 '-';
+ 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 '-';
+ if (d.duration < 1000) {
+ return d.duration + ' ms';
+ }
+ return (d.duration / 1000).toFixed(2) + ' s';
+ };
+
+ // 错误信息截断模板
+ var errorMsgTemplet = function(d) {
+ if (!d.error_message) return '-';
+ var text = d.error_message;
+ if (text.length > 50) {
+ return ''+text.substring(0,50)+'...';
+ }
+ 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(''+text.replace(//g,'>')+'
', {
+ title: '错误信息详情',
+ area: ['600px', '400px']
+ });
+ }
+ });
+
+ ua.listen();
+})
diff --git a/app/admin/view/system/timer_log/read.html b/app/admin/view/system/timer_log/read.html
new file mode 100644
index 0000000..fe205c6
--- /dev/null
+++ b/app/admin/view/system/timer_log/read.html
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
任务名称
+
+ {notempty name="row.task_name"}
+ {$row.task_name}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
执行节点ID
+
+ {notempty name="row.node_id"}
+ {$row.node_id}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
运行类型
+
+ {notempty name="row.run_type"}
+ {$row.run_type}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
开始时间
+
+ {notempty name="row.start_time"}
+ {:date('Y-m-d H:i:s', $row['start_time'])}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
结束时间
+
+ {notempty name="row.end_time"}
+ {:date('Y-m-d H:i:s', $row['end_time'])}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
耗时
+
+ {notempty name="row.duration"}
+ {:php echo ($row['duration'] < 1000) ? $row['duration'].' ms' : round($row['duration']/1000, 2).' s';}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
错误信息
+
+ {notempty name="row.error_message"}
+ {$row.error_message|raw}
+ {else/}
+ 暂无内容
+ {/notempty}
+
+
+
+
并发分片ID
+
+ {notempty name="row.concurrency_id"}
+ {$row.concurrency_id}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
+
+
+
+
基础信息
+
+
+
+
状态
+
+ {switch name="row.status"}
+ {case value="success"}成功{/case}
+ {case value="error"}失败{/case}
+ {case value="running"}运行中{/case}
+ {default /}{$row.status}
+ {/switch}
+
+
+
+
创建时间
+
+ {notempty name="row.create_time"}
+ {$row.create_time|date="Y-m-d H:i:s"}
+ {else/}
+ 暂无数据
+ {/notempty}
+
+
+
+
+
+
+
+
+
+
diff --git a/app/admin/view/system/timer_log/read.js b/app/admin/view/system/timer_log/read.js
new file mode 100644
index 0000000..81a35d4
--- /dev/null
+++ b/app/admin/view/system/timer_log/read.js
@@ -0,0 +1,3 @@
+$(function(){
+ ua.listen();
+})
diff --git a/extend/base/admin/controller/system/HostBase.php b/extend/base/admin/controller/system/HostBase.php
index 723fe41..c09336c 100644
--- a/extend/base/admin/controller/system/HostBase.php
+++ b/extend/base/admin/controller/system/HostBase.php
@@ -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('节点不存在');
+ }
}
}
diff --git a/extend/base/admin/model/SystemHostBase.php b/extend/base/admin/model/SystemHostBase.php
index e2d941a..e2d5112 100644
--- a/extend/base/admin/model/SystemHostBase.php
+++ b/extend/base/admin/model/SystemHostBase.php
@@ -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' => '主节点'];
}
diff --git a/extend/base/admin/view/system/host/_common.js b/extend/base/admin/view/system/host/_common.js
index ad6eb5d..984b2ab 100644
--- a/extend/base/admin/view/system/host/_common.js
+++ b/extend/base/admin/view/system/host/_common.js
@@ -7,4 +7,5 @@ var init = {
deleteUrl: 'system.host/delete',
exportUrl: 'system.host/export',
modifyUrl: 'system.host/modify',
+ set_master_url: 'system.host/setMaster',
};
\ No newline at end of file
diff --git a/extend/base/admin/view/system/host/index.html b/extend/base/admin/view/system/host/index.html
index 083bdc6..146e27c 100644
--- a/extend/base/admin/view/system/host/index.html
+++ b/extend/base/admin/view/system/host/index.html
@@ -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">
diff --git a/extend/base/admin/view/system/host/index.js b/extend/base/admin/view/system/host/index.js
index 21b3c53..61d5ac7 100644
--- a/extend/base/admin/view/system/host/index.js
+++ b/extend/base/admin/view/system/host/index.js
@@ -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: '最后心跳时间'},
{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: 250, title: '操作', templet: ua.table.tool , fixed:'right'},
- ]],
- });
-
- ua.listen();
-})
\ No newline at end of file
+$(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 '主节点';
+ }
+ return '从节点';
+ }},
+ {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();
+})