diff --git a/app/admin/controller/system/TimerConfig.php b/app/admin/controller/system/TimerConfig.php index b38859b..b2de17a 100644 --- a/app/admin/controller/system/TimerConfig.php +++ b/app/admin/controller/system/TimerConfig.php @@ -6,6 +6,7 @@ use app\common\controller\AdminController; use app\admin\service\annotation\ControllerAnnotation; use app\admin\service\annotation\NodeAnotation; use think\App; +use think\facade\Cache; /** * @ControllerAnnotation(title="定时任务协调配置表") @@ -29,6 +30,7 @@ class TimerConfig extends AdminController $this->allowModifyFields = [ 'status', 'run_type', + 'concurrency', ]; } @@ -57,14 +59,23 @@ class TimerConfig extends AdminController 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'])); + // 只允许修改 run_type、status、concurrency + $post = array_intersect_key($post, array_flip(['run_type', 'status', 'concurrency'])); + if (array_key_exists('concurrency', $post)) { + // 空/null=继承代码默认写 NULL;正整数=覆盖;0或负数=拒绝(M5 防静默吞任务) + $post['concurrency'] = $this->normalizeConcurrency($post['concurrency']); + } try { $save = $row->save($post); } catch (\Exception $e) { $this->error('保存失败:' . $e->getMessage()); } - $save ? $this->success('保存成功') : $this->error('保存失败'); + if ($save) { + // D18:DB commit 后递增脏标记,触发 timer reload(edit 改 concurrency/run_type/status,与 trigger 一致) + Cache::inc('timer_config_version'); + $this->success('保存成功'); + } + $this->error('保存失败'); } $this->assign('row', $row); @@ -81,17 +92,88 @@ class TimerConfig extends AdminController if (!$row) { $this->error('数据不存在'); } - if ($row->getAttr('run_type') !== 'manual') { - $this->error('只有manual类型的任务支持手动触发'); - } - if ($row->getAttr('status') != 1) { - $this->error('任务已停用,请先启用'); + $trigger_node_id = $this->request->post('trigger_node_id'); + if (empty($trigger_node_id)) { + $this->error('请选择节点'); } try { - $row->save(['manual_trigger' => 1]); + // 手动触发跨 run_type、穿透 status(D19:调试工作流,关闭+手动触发+打开) + $row->save([ + 'manual_trigger' => 1, + 'trigger_node_id' => $trigger_node_id, + 'last_trigger_time' => time(), + ]); + // D18:DB commit 成功后才递增 version,防脏读(commit 前递增→节点 reload 读旧值→永不 reload) + Cache::inc('timer_config_version'); } catch (\Exception $e) { $this->error('触发失败:' . $e->getMessage()); } $this->success('触发成功,等待定时器执行'); } + + /** + * @NodeAnotation(title="节点列表") + */ + public function hostList() + { + $list = \app\admin\model\SystemHost::where('status', 1) + ->field('node_id,is_master,ip_address,last_heartbeat_at') + ->order('is_master desc, node_id asc') + ->select(); + $this->success('', $list); + } + + /** + * @NodeAnotation(title="属性修改") + */ + public function modify() + { + $this->checkPostRequest(); + $post = $this->request->post(); + $rule = [ + 'id|ID' => 'require', + 'field|字段' => 'require', + 'value|值' => 'require', + ]; + $this->validate($post, $rule); + if (!in_array($post['field'], $this->allowModifyFields)) { + $this->error('该字段不允许修改:' . $post['field']); + } + // concurrency 行内修改必须为正整数(M5 防静默吞任务;继承默认请走 edit 表单传空值) + if ($post['field'] === 'concurrency' && (!is_numeric($post['value']) || (int) $post['value'] < 1)) { + $this->error('concurrency 必须是正整数'); + } + $row = $this->model->find($post['id']); + empty($row) && $this->error('数据不存在'); + $value = $post['field'] === 'concurrency' ? (int) $post['value'] : $post['value']; + try { + $save = $row->save([$post['field'] => $value]); + } catch (\Exception $e) { + $this->error($e->getMessage()); + } + if ($save) { + // D18:DB commit 后递增脏标记,触发 timer reload(行内改 concurrency/status/run_type,同 edit) + Cache::inc('timer_config_version'); + } + $this->success('保存成功'); + } + + /** + * 归一化 concurrency 入库值. + * 空字符串/null → null(继承代码默认);正整数 → int;0或负数/非数字 → 拒绝. + * + * @param mixed $value 提交值 + * @return int|null + */ + private function normalizeConcurrency($value) + { + if ($value === '' || $value === null) { + return null; + } + if (!is_numeric($value) || (int) $value < 1) { + $this->error('concurrency 必须是正整数或空(继承默认)'); + } + + return (int) $value; + } }