Эх сурвалжийг харах

定时任务增加作业和触发器启动、暂停、唤醒、修改、删除等操作

zuohuaijun 3 жил өмнө
parent
commit
f772abcd3a

+ 3 - 3
Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj

@@ -14,9 +14,9 @@
   <ItemGroup>
     <PackageReference Include="AngleSharp" Version="0.17.1" />
     <PackageReference Include="AspNetCoreRateLimit" Version="4.0.2" />
-    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.8.1.4" />
-    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.8.1.4" />
-    <PackageReference Include="Furion.Pure" Version="4.8.1.4" />
+    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.8.1.6" />
+    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.8.1.6" />
+    <PackageReference Include="Furion.Pure" Version="4.8.1.6" />
     <PackageReference Include="Lazy.Captcha.Core" Version="1.1.6" />
     <PackageReference Include="Magicodes.IE.Excel" Version="2.7.0" />
     <PackageReference Include="Magicodes.IE.Pdf" Version="2.7.0" />

+ 48 - 1
Admin.NET/Admin.NET.Core/Admin.NET.Core.xml

@@ -822,6 +822,11 @@
             是否启动时执行一次
             </summary>
         </member>
+        <member name="P:Admin.NET.Core.SysJobTrigger.ResetOnlyOnce">
+            <summary>
+            是否在启动时重置最大触发次数等于一次的作业
+            </summary>
+        </member>
         <member name="P:Admin.NET.Core.SysJobTrigger.UpdatedTime">
             <summary>
             更新时间
@@ -5393,7 +5398,7 @@
         </member>
         <member name="M:Admin.NET.Core.Service.SysJobService.AddJobTrigger(Admin.NET.Core.Service.AddJobTriggerInput)">
             <summary>
-            添加作业
+            添加触发器
             </summary>
             <returns></returns>
         </member>
@@ -5409,6 +5414,48 @@
             </summary>
             <returns></returns>
         </member>
+        <member name="M:Admin.NET.Core.Service.SysJobService.PauseAllJob">
+            <summary>
+            暂停所有作业
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Admin.NET.Core.Service.SysJobService.StartAllJob">
+            <summary>
+            启动所有作业
+            </summary>
+            <returns></returns>
+        </member>
+        <member name="M:Admin.NET.Core.Service.SysJobService.PauseJob(Admin.NET.Core.Service.JobDetailInput)">
+            <summary>
+            暂停作业
+            </summary>
+        </member>
+        <member name="M:Admin.NET.Core.Service.SysJobService.StartJob(Admin.NET.Core.Service.JobDetailInput)">
+            <summary>
+            启动作业
+            </summary>
+        </member>
+        <member name="M:Admin.NET.Core.Service.SysJobService.PauseTrigger(Admin.NET.Core.Service.JobTriggerInput)">
+            <summary>
+            暂停触发器
+            </summary>
+        </member>
+        <member name="M:Admin.NET.Core.Service.SysJobService.StartTrigger(Admin.NET.Core.Service.JobTriggerInput)">
+            <summary>
+            启动触发器
+            </summary>
+        </member>
+        <member name="M:Admin.NET.Core.Service.SysJobService.CancelSleep">
+            <summary>
+            强制唤醒作业调度器
+            </summary>
+        </member>
+        <member name="M:Admin.NET.Core.Service.SysJobService.PersistAll">
+            <summary>
+            强制触发所有作业持久化
+            </summary>
+        </member>
         <member name="M:Admin.NET.Core.Service.SysJobService.GetJobClusterList">
             <summary>
             获取集群列表

+ 6 - 0
Admin.NET/Admin.NET.Core/Entity/SysJobTrigger.cs

@@ -126,6 +126,12 @@ public class SysJobTrigger : BaseId
     [SugarColumn(ColumnDescription = "是否启动时执行一次")]
     public bool RunOnStart { get; set; } = false;
 
+    /// <summary>
+    /// 是否在启动时重置最大触发次数等于一次的作业
+    /// </summary>
+    [SugarColumn(ColumnDescription = "是否只运行一次")]
+    public bool ResetOnlyOnce { get; set; } = true;
+
     /// <summary>
     /// 更新时间
     /// </summary>

+ 0 - 1
Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs

@@ -100,7 +100,6 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
             new SysMenu{ Id=252885263005352, Pid=252885263005350, Title="编辑", Permission="sysJob:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263005353, Pid=252885263005350, Title="增加", Permission="sysJob:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
             new SysMenu{ Id=252885263005354, Pid=252885263005350, Title="删除", Permission="sysJob:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
-            new SysMenu{ Id=252885263005355, Pid=252885263005350, Title="状态", Permission="sysJob:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=100 },
 
             new SysMenu{ Id=252885263005360, Pid=252885263005300, Title="系统监控", Path="/platform/server", Name="sysServer", Component="/system/server/index", Icon="ele-Monitor", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Order=140 },
 

+ 2 - 4
Admin.NET/Admin.NET.Core/Service/Job/DbJobPersistence.cs

@@ -40,10 +40,8 @@ public class DbJobPersistence : IJobPersistence
         {
             return builder.Updated();
         }
-        else
-        {
-            return builder.Appended();
-        }
+
+        return builder.Appended();
     }
 
     /// <summary>

+ 1 - 1
Admin.NET/Admin.NET.Core/Service/Job/Dto/JobTriggerInput.cs

@@ -30,7 +30,7 @@ public class AddJobTriggerInput : SysJobTrigger
 }
 
 [NotTable]
-public class UpdateJobTriggerInput : AddJobDetailInput
+public class UpdateJobTriggerInput : AddJobTriggerInput
 {
 }
 

+ 87 - 10
Admin.NET/Admin.NET.Core/Service/Job/SysJobService.cs

@@ -75,13 +75,12 @@ public class SysJobService : IDynamicApiController, ITransient
     /// </summary>
     /// <returns></returns>
     [HttpPost("/sysJob/detailDelete")]
-    public async Task<ScheduleResult> DeleteJobDetail(DeleteJobDetailInput input)
+    public async Task DeleteJobDetail(DeleteJobDetailInput input)
     {
+        _schedulerFactory.RemoveJob(input.JobId);
+
         await _sysJobDetailRep.DeleteAsync(u => u.JobId == input.JobId);
         await _sysJobTriggerRep.DeleteAsync(u => u.JobId == input.JobId);
-
-        var schedulerResult = _schedulerFactory.TryRemoveJob(input.JobId, out _);
-        return await Task.FromResult(schedulerResult);
     }
 
     /// <summary>
@@ -96,17 +95,17 @@ public class SysJobService : IDynamicApiController, ITransient
     }
 
     /// <summary>
-    /// 添加作业
+    /// 添加触发器
     /// </summary>
     /// <returns></returns>
     [HttpPost("/sysJob/triggerAdd")]
     public async Task AddJobTrigger(AddJobTriggerInput input)
     {
-        var isExist = await _sysJobDetailRep.IsAnyAsync(u => u.JobId == input.JobId && u.Id != input.Id);
+        var isExist = await _sysJobTriggerRep.IsAnyAsync(u => u.TriggerId == input.TriggerId && u.Id != input.Id);
         if (isExist)
             throw Oops.Oh(ErrorCodeEnum.D1006);
 
-        await _sysJobDetailRep.UpdateAsync(input.Adapt<SysJobDetail>());
+        await _sysJobTriggerRep.UpdateAsync(input.Adapt<SysJobTrigger>());
     }
 
     /// <summary>
@@ -116,11 +115,11 @@ public class SysJobService : IDynamicApiController, ITransient
     [HttpPost("/sysJob/triggerUpdate")]
     public async Task UpdateJobTrigger(UpdateJobTriggerInput input)
     {
-        var isExist = await _sysJobDetailRep.IsAnyAsync(u => u.JobId == input.JobId && u.Id != input.Id);
+        var isExist = await _sysJobTriggerRep.IsAnyAsync(u => u.TriggerId == input.TriggerId && u.Id != input.Id);
         if (isExist)
             throw Oops.Oh(ErrorCodeEnum.D1006);
 
-        await _sysJobDetailRep.UpdateAsync(input.Adapt<SysJobDetail>());
+        await _sysJobTriggerRep.UpdateAsync(input.Adapt<SysJobTrigger>());
     }
 
     /// <summary>
@@ -130,7 +129,85 @@ public class SysJobService : IDynamicApiController, ITransient
     [HttpPost("/sysJob/triggerDelete")]
     public async Task DeleteJobTrigger(DeleteJobTriggerInput input)
     {
-        await _sysJobTriggerRep.DeleteAsync(u => u.JobId == input.JobId);
+        await _sysJobTriggerRep.DeleteAsync(u => u.TriggerId == input.TriggerId);
+    }
+
+    /// <summary>
+    /// 暂停所有作业
+    /// </summary>
+    /// <returns></returns>
+    [HttpPost("/sysJob/pauseAll")]
+    public void PauseAllJob()
+    {
+        _schedulerFactory.PauseAll();
+    }
+
+    /// <summary>
+    /// 启动所有作业
+    /// </summary>
+    /// <returns></returns>
+    [HttpPost("/sysJob/startAll")]
+    public void StartAllJob()
+    {
+        _schedulerFactory.StartAll();
+    }
+
+    /// <summary>
+    /// 暂停作业
+    /// </summary>
+    [HttpPost("/sysJob/pauseJob")]
+    public void PauseJob(JobDetailInput input)
+    {
+        _ = _schedulerFactory.TryGetJob(input.JobId, out var _scheduler);
+        _scheduler?.Pause();
+    }
+
+    /// <summary>
+    /// 启动作业
+    /// </summary>
+    [HttpPost("/sysJob/startJob")]
+    public void StartJob(JobDetailInput input)
+    {
+        _ = _schedulerFactory.TryGetJob(input.JobId, out var _scheduler);
+        _scheduler?.Start();
+    }
+
+    /// <summary>
+    /// 暂停触发器
+    /// </summary>
+    [HttpPost("/sysJob/pauseTrigger")]
+    public void PauseTrigger(JobTriggerInput input)
+    {
+        _ = _schedulerFactory.TryGetJob(input.JobId, out var _scheduler);
+        _scheduler?.PauseTrigger(input.TriggerId);
+    }
+
+    /// <summary>
+    /// 启动触发器
+    /// </summary>
+    [HttpPost("/sysJob/startTrigger")]
+    public void StartTrigger(JobTriggerInput input)
+    {
+        _ = _schedulerFactory.TryGetJob(input.JobId, out var _scheduler);
+        _scheduler?.StartTrigger(input.TriggerId);
+    }
+
+    /// <summary>
+    /// 强制唤醒作业调度器
+    /// </summary>
+    [HttpPost("/sysJob/cancelSleep")]
+    public void CancelSleep()
+    {
+        _schedulerFactory.CancelSleep();
+    }
+
+    /// <summary>
+    /// 强制触发所有作业持久化
+    /// </summary>
+    [HttpPost("/sysJob/persistAll")]
+    public void PersistAll()
+    {
+        _schedulerFactory.PersistAll();
     }
 
     /// <summary>

+ 585 - 8
Web/src/api-services/apis/sys-job-api.ts

@@ -20,10 +20,11 @@ import { AddJobDetailInput } from '../models';
 import { AddJobTriggerInput } from '../models';
 import { AdminResultListSysJobCluster } from '../models';
 import { AdminResultListSysJobTrigger } from '../models';
-import { AdminResultScheduleResult } from '../models';
 import { AdminResultSqlSugarPagedListJobOutput } from '../models';
 import { DeleteJobDetailInput } from '../models';
 import { DeleteJobTriggerInput } from '../models';
+import { JobDetailInput } from '../models';
+import { JobTriggerInput } from '../models';
 import { UpdateJobDetailInput } from '../models';
 import { UpdateJobTriggerInput } from '../models';
 /**
@@ -32,6 +33,42 @@ import { UpdateJobTriggerInput } from '../models';
  */
 export const SysJobApiAxiosParamCreator = function (configuration?: Configuration) {
     return {
+        /**
+         * 
+         * @summary 强制唤醒作业调度器
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        sysJobCancelSleepPost: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysJob/cancelSleep`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
         /**
          * 
          * @summary 获取集群列表
@@ -264,7 +301,279 @@ export const SysJobApiAxiosParamCreator = function (configuration?: Configuratio
         },
         /**
          * 
-         * @summary 添加作业
+         * @summary 暂停所有作业
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        sysJobPauseAllPost: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysJob/pauseAll`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 暂停作业
+         * @param {JobDetailInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        sysJobPauseJobPost: async (body?: JobDetailInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysJob/pauseJob`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 暂停触发器
+         * @param {JobTriggerInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        sysJobPauseTriggerPost: async (body?: JobTriggerInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysJob/pauseTrigger`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 强制触发所有作业持久化
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        sysJobPersistAllPost: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysJob/persistAll`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 启动所有作业
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        sysJobStartAllPost: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysJob/startAll`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 启动作业
+         * @param {JobDetailInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        sysJobStartJobPost: async (body?: JobDetailInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysJob/startJob`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 启动触发器
+         * @param {JobTriggerInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        sysJobStartTriggerPost: async (body?: JobTriggerInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/sysJob/startTrigger`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 添加触发器
          * @param {AddJobTriggerInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
@@ -435,6 +744,19 @@ export const SysJobApiAxiosParamCreator = function (configuration?: Configuratio
  */
 export const SysJobApiFp = function(configuration?: Configuration) {
     return {
+        /**
+         * 
+         * @summary 强制唤醒作业调度器
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobCancelSleepPost(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysJobApiAxiosParamCreator(configuration).sysJobCancelSleepPost(options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary 获取集群列表
@@ -469,7 +791,7 @@ export const SysJobApiFp = function(configuration?: Configuration) {
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysJobDetailDeletePost(body?: DeleteJobDetailInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultScheduleResult>>> {
+        async sysJobDetailDeletePost(body?: DeleteJobDetailInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
             const localVarAxiosArgs = await SysJobApiAxiosParamCreator(configuration).sysJobDetailDeletePost(body, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
@@ -512,7 +834,102 @@ export const SysJobApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 添加作业
+         * @summary 暂停所有作业
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobPauseAllPost(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysJobApiAxiosParamCreator(configuration).sysJobPauseAllPost(options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 暂停作业
+         * @param {JobDetailInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobPauseJobPost(body?: JobDetailInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysJobApiAxiosParamCreator(configuration).sysJobPauseJobPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 暂停触发器
+         * @param {JobTriggerInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobPauseTriggerPost(body?: JobTriggerInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysJobApiAxiosParamCreator(configuration).sysJobPauseTriggerPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 强制触发所有作业持久化
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobPersistAllPost(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysJobApiAxiosParamCreator(configuration).sysJobPersistAllPost(options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 启动所有作业
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobStartAllPost(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysJobApiAxiosParamCreator(configuration).sysJobStartAllPost(options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 启动作业
+         * @param {JobDetailInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobStartJobPost(body?: JobDetailInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysJobApiAxiosParamCreator(configuration).sysJobStartJobPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 启动触发器
+         * @param {JobTriggerInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobStartTriggerPost(body?: JobTriggerInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysJobApiAxiosParamCreator(configuration).sysJobStartTriggerPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 添加触发器
          * @param {AddJobTriggerInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
@@ -575,6 +992,15 @@ export const SysJobApiFp = function(configuration?: Configuration) {
  */
 export const SysJobApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
     return {
+        /**
+         * 
+         * @summary 强制唤醒作业调度器
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobCancelSleepPost(options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysJobApiFp(configuration).sysJobCancelSleepPost(options).then((request) => request(axios, basePath));
+        },
         /**
          * 
          * @summary 获取集群列表
@@ -601,7 +1027,7 @@ export const SysJobApiFactory = function (configuration?: Configuration, basePat
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async sysJobDetailDeletePost(body?: DeleteJobDetailInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultScheduleResult>> {
+        async sysJobDetailDeletePost(body?: DeleteJobDetailInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
             return SysJobApiFp(configuration).sysJobDetailDeletePost(body, options).then((request) => request(axios, basePath));
         },
         /**
@@ -632,7 +1058,74 @@ export const SysJobApiFactory = function (configuration?: Configuration, basePat
         },
         /**
          * 
-         * @summary 添加作业
+         * @summary 暂停所有作业
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobPauseAllPost(options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysJobApiFp(configuration).sysJobPauseAllPost(options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 暂停作业
+         * @param {JobDetailInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobPauseJobPost(body?: JobDetailInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysJobApiFp(configuration).sysJobPauseJobPost(body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 暂停触发器
+         * @param {JobTriggerInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobPauseTriggerPost(body?: JobTriggerInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysJobApiFp(configuration).sysJobPauseTriggerPost(body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 强制触发所有作业持久化
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobPersistAllPost(options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysJobApiFp(configuration).sysJobPersistAllPost(options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 启动所有作业
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobStartAllPost(options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysJobApiFp(configuration).sysJobStartAllPost(options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 启动作业
+         * @param {JobDetailInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobStartJobPost(body?: JobDetailInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysJobApiFp(configuration).sysJobStartJobPost(body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 启动触发器
+         * @param {JobTriggerInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async sysJobStartTriggerPost(body?: JobTriggerInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysJobApiFp(configuration).sysJobStartTriggerPost(body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 添加触发器
          * @param {AddJobTriggerInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
@@ -680,6 +1173,16 @@ export const SysJobApiFactory = function (configuration?: Configuration, basePat
  * @extends {BaseAPI}
  */
 export class SysJobApi extends BaseAPI {
+    /**
+     * 
+     * @summary 强制唤醒作业调度器
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysJobApi
+     */
+    public async sysJobCancelSleepPost(options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysJobApiFp(this.configuration).sysJobCancelSleepPost(options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary 获取集群列表
@@ -709,7 +1212,7 @@ export class SysJobApi extends BaseAPI {
      * @throws {RequiredError}
      * @memberof SysJobApi
      */
-    public async sysJobDetailDeletePost(body?: DeleteJobDetailInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultScheduleResult>> {
+    public async sysJobDetailDeletePost(body?: DeleteJobDetailInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
         return SysJobApiFp(this.configuration).sysJobDetailDeletePost(body, options).then((request) => request(this.axios, this.basePath));
     }
     /**
@@ -742,7 +1245,81 @@ export class SysJobApi extends BaseAPI {
     }
     /**
      * 
-     * @summary 添加作业
+     * @summary 暂停所有作业
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysJobApi
+     */
+    public async sysJobPauseAllPost(options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysJobApiFp(this.configuration).sysJobPauseAllPost(options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 暂停作业
+     * @param {JobDetailInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysJobApi
+     */
+    public async sysJobPauseJobPost(body?: JobDetailInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysJobApiFp(this.configuration).sysJobPauseJobPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 暂停触发器
+     * @param {JobTriggerInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysJobApi
+     */
+    public async sysJobPauseTriggerPost(body?: JobTriggerInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysJobApiFp(this.configuration).sysJobPauseTriggerPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 强制触发所有作业持久化
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysJobApi
+     */
+    public async sysJobPersistAllPost(options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysJobApiFp(this.configuration).sysJobPersistAllPost(options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 启动所有作业
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysJobApi
+     */
+    public async sysJobStartAllPost(options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysJobApiFp(this.configuration).sysJobStartAllPost(options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 启动作业
+     * @param {JobDetailInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysJobApi
+     */
+    public async sysJobStartJobPost(body?: JobDetailInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysJobApiFp(this.configuration).sysJobStartJobPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 启动触发器
+     * @param {JobTriggerInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysJobApi
+     */
+    public async sysJobStartTriggerPost(body?: JobTriggerInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysJobApiFp(this.configuration).sysJobStartTriggerPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 添加触发器
      * @param {AddJobTriggerInput} [body] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}

+ 6 - 0
Web/src/api-services/models/add-job-trigger-input.ts

@@ -126,6 +126,12 @@ export interface AddJobTriggerInput {
      * @memberof AddJobTriggerInput
      */
     runOnStart?: boolean;
+    /**
+     * 是否在启动时重置最大触发次数等于一次的作业
+     * @type {boolean}
+     * @memberof AddJobTriggerInput
+     */
+    resetOnlyOnce?: boolean;
     /**
      * 更新时间
      * @type {Date}

+ 0 - 57
Web/src/api-services/models/admin-result-schedule-result.ts

@@ -1,57 +0,0 @@
-/* tslint:disable */
-/* eslint-disable */
-/**
- * Admin.NET
- * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/><a href='https://gitee.com/zuohuaijun/Admin.NET/'>https://gitee.com/zuohuaijun/Admin.NET</a>
- *
- * OpenAPI spec version: 1.0.0
- * Contact: 515096995@qq.com
- *
- * NOTE: This class is auto generated by the swagger code generator program.
- * https://github.com/swagger-api/swagger-codegen.git
- * Do not edit the class manually.
- */
-import { ScheduleResult } from './schedule-result';
-/**
- * 全局返回结果
- * @export
- * @interface AdminResultScheduleResult
- */
-export interface AdminResultScheduleResult {
-    /**
-     * 状态码
-     * @type {number}
-     * @memberof AdminResultScheduleResult
-     */
-    code?: number;
-    /**
-     * 类型success、warning、error
-     * @type {string}
-     * @memberof AdminResultScheduleResult
-     */
-    type?: string | null;
-    /**
-     * 错误信息
-     * @type {string}
-     * @memberof AdminResultScheduleResult
-     */
-    message?: string | null;
-    /**
-     * 
-     * @type {ScheduleResult}
-     * @memberof AdminResultScheduleResult
-     */
-    result?: ScheduleResult;
-    /**
-     * 附加数据
-     * @type {any}
-     * @memberof AdminResultScheduleResult
-     */
-    extras?: any | null;
-    /**
-     * 时间
-     * @type {Date}
-     * @memberof AdminResultScheduleResult
-     */
-    time?: Date;
-}

+ 2 - 2
Web/src/api-services/models/index.ts

@@ -45,7 +45,6 @@ export * from './admin-result-list-table-output';
 export * from './admin-result-login-output';
 export * from './admin-result-login-user-output';
 export * from './admin-result-object';
-export * from './admin-result-schedule-result';
 export * from './admin-result-sql-sugar-paged-list-job-output';
 export * from './admin-result-sql-sugar-paged-list-sys-code-gen';
 export * from './admin-result-sql-sugar-paged-list-sys-config';
@@ -112,7 +111,9 @@ export * from './file-output';
 export * from './gen-auth-url-input';
 export * from './gender-enum';
 export * from './iaction-result';
+export * from './job-detail-input';
 export * from './job-output';
+export * from './job-trigger-input';
 export * from './login-input';
 export * from './login-output';
 export * from './login-type-enum';
@@ -130,7 +131,6 @@ export * from './role-input';
 export * from './role-menu-input';
 export * from './role-org-input';
 export * from './role-output';
-export * from './schedule-result';
 export * from './signature-input';
 export * from './sql-sugar-paged-list-job-output';
 export * from './sql-sugar-paged-list-sys-code-gen';

+ 9 - 10
Web/src/api-services/models/schedule-result.ts → Web/src/api-services/models/job-detail-input.ts

@@ -12,16 +12,15 @@
  * Do not edit the class manually.
  */
 /**
- * <br />&nbsp; NotFound = 0<br />&nbsp; NotIdentify = 1<br />&nbsp; Exists = 2<br />&nbsp; Succeed = 3<br />&nbsp; Removed = 4<br />&nbsp; Failed = 5<br />
+ * 
  * @export
- * @enum {string}
+ * @interface JobDetailInput
  */
-export enum ScheduleResult {
-    NUMBER_0 = 0,
-    NUMBER_1 = 1,
-    NUMBER_2 = 2,
-    NUMBER_3 = 3,
-    NUMBER_4 = 4,
-    NUMBER_5 = 5
+export interface JobDetailInput {
+    /**
+     * 作业Id
+     * @type {string}
+     * @memberof JobDetailInput
+     */
+    jobId?: string | null;
 }
-

+ 32 - 0
Web/src/api-services/models/job-trigger-input.ts

@@ -0,0 +1,32 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET
+ * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/><a href='https://gitee.com/zuohuaijun/Admin.NET/'>https://gitee.com/zuohuaijun/Admin.NET</a>
+ *
+ * OpenAPI spec version: 1.0.0
+ * Contact: 515096995@qq.com
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+/**
+ * 
+ * @export
+ * @interface JobTriggerInput
+ */
+export interface JobTriggerInput {
+    /**
+     * 作业Id
+     * @type {string}
+     * @memberof JobTriggerInput
+     */
+    jobId?: string | null;
+    /**
+     * 触发器Id
+     * @type {string}
+     * @memberof JobTriggerInput
+     */
+    triggerId?: string | null;
+}

+ 6 - 0
Web/src/api-services/models/sys-job-trigger.ts

@@ -138,6 +138,12 @@ export interface SysJobTrigger {
      * @memberof SysJobTrigger
      */
     runOnStart?: boolean;
+    /**
+     * 是否在启动时重置最大触发次数等于一次的作业
+     * @type {boolean}
+     * @memberof SysJobTrigger
+     */
+    resetOnlyOnce?: boolean;
     /**
      * 更新时间
      * @type {Date}

+ 86 - 13
Web/src/api-services/models/update-job-trigger-input.ts

@@ -11,6 +11,7 @@
  * https://github.com/swagger-api/swagger-codegen.git
  * Do not edit the class manually.
  */
+import { TriggerStatus } from './trigger-status';
 /**
  * 
  * @export
@@ -24,23 +25,23 @@ export interface UpdateJobTriggerInput {
      */
     id?: number;
     /**
-     * 组名称
+     * 触发器类型FullName
      * @type {string}
      * @memberof UpdateJobTriggerInput
      */
-    groupName?: string | null;
+    triggerType?: string | null;
     /**
-     * 作业类型FullName
+     * 程序集Name
      * @type {string}
      * @memberof UpdateJobTriggerInput
      */
-    jobType?: string | null;
+    assemblyName?: string | null;
     /**
-     * 程序集Name
+     * 参数
      * @type {string}
      * @memberof UpdateJobTriggerInput
      */
-    assemblyName?: string | null;
+    args?: string | null;
     /**
      * 描述信息
      * @type {string}
@@ -48,23 +49,89 @@ export interface UpdateJobTriggerInput {
      */
     description?: string | null;
     /**
-     * 是否并行执行
+     * 
+     * @type {TriggerStatus}
+     * @memberof UpdateJobTriggerInput
+     */
+    status?: TriggerStatus;
+    /**
+     * 起始时间
+     * @type {Date}
+     * @memberof UpdateJobTriggerInput
+     */
+    startTime?: Date | null;
+    /**
+     * 结束时间
+     * @type {Date}
+     * @memberof UpdateJobTriggerInput
+     */
+    endTime?: Date | null;
+    /**
+     * 最近运行时间
+     * @type {Date}
+     * @memberof UpdateJobTriggerInput
+     */
+    lastRunTime?: Date | null;
+    /**
+     * 下一次运行时间
+     * @type {Date}
+     * @memberof UpdateJobTriggerInput
+     */
+    nextRunTime?: Date | null;
+    /**
+     * 触发次数
+     * @type {number}
+     * @memberof UpdateJobTriggerInput
+     */
+    numberOfRuns?: number;
+    /**
+     * 最大触发次数(0:不限制,n:N次)
+     * @type {number}
+     * @memberof UpdateJobTriggerInput
+     */
+    maxNumberOfRuns?: number;
+    /**
+     * 出错次数
+     * @type {number}
+     * @memberof UpdateJobTriggerInput
+     */
+    numberOfErrors?: number;
+    /**
+     * 最大出错次数(0:不限制,n:N次)
+     * @type {number}
+     * @memberof UpdateJobTriggerInput
+     */
+    maxNumberOfErrors?: number;
+    /**
+     * 重试次数
+     * @type {number}
+     * @memberof UpdateJobTriggerInput
+     */
+    numRetries?: number;
+    /**
+     * 重试间隔时间(ms)
+     * @type {number}
+     * @memberof UpdateJobTriggerInput
+     */
+    retryTimeout?: number;
+    /**
+     * 是否立即启动
      * @type {boolean}
      * @memberof UpdateJobTriggerInput
      */
-    concurrent?: boolean;
+    startNow?: boolean;
     /**
-     * 是否扫描特性触发器
+     * 是否启动时执行一次
      * @type {boolean}
      * @memberof UpdateJobTriggerInput
      */
-    includeAnnotations?: boolean;
+    runOnStart?: boolean;
     /**
-     * 额外数据
-     * @type {string}
+     * 是否在启动时重置最大触发次数等于一次的作业
+     * @type {boolean}
      * @memberof UpdateJobTriggerInput
      */
-    properties?: string | null;
+    resetOnlyOnce?: boolean;
     /**
      * 更新时间
      * @type {Date}
@@ -77,4 +144,10 @@ export interface UpdateJobTriggerInput {
      * @memberof UpdateJobTriggerInput
      */
     jobId: string;
+    /**
+     * 触发器Id
+     * @type {string}
+     * @memberof UpdateJobTriggerInput
+     */
+    triggerId: string;
 }

+ 1 - 1
Web/src/utils/axios-utils.ts

@@ -125,7 +125,7 @@ axiosInstance.interceptors.response.use(
 		}
 
 		// 响应拦截及自定义处理
-		if (serve.code === 401 || serve.code === 400) {
+		if (serve.code === 401) {
 			clearAccessTokens();
 		} else if (serve.code === undefined) {
 			return Promise.resolve(res);

+ 1 - 1
Web/src/views/system/job/component/editJobDetail.vue

@@ -1,6 +1,6 @@
 <template>
 	<div class="sys-jobDetail-container">
-		<el-dialog v-model="isShowDialog" draggable width="769px">
+		<el-dialog v-model="isShowDialog" draggable :close-on-click-modal="false" width="769px">
 			<template #header>
 				<div style="color: #fff">
 					<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>

+ 152 - 0
Web/src/views/system/job/component/editJobTrigger.vue

@@ -0,0 +1,152 @@
+<template>
+	<div class="sys-jobTrigger-container">
+		<el-dialog v-model="isShowDialog" draggable :close-on-click-modal="false" width="769px">
+			<template #header>
+				<div style="color: #fff">
+					<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
+					<span> {{ title }} </span>
+				</div>
+			</template>
+			<el-form :model="ruleForm" ref="ruleFormRef" size="default" label-width="110px">
+				<el-row :gutter="35">
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="触发器编号" prop="triggerId" :rules="[{ required: true, message: '触发器编号不能为空', trigger: 'blur' }]">
+							<el-input v-model="ruleForm.triggerId" placeholder="触发器编号" clearable />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="参数">
+							<el-input v-model="ruleForm.args" placeholder="参数" clearable type="textarea" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="起始时间">
+							<el-date-picker v-model="ruleForm.startTime" type="datetime" placeholder="起始时间" style="width: 100%" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="结束时间">
+							<el-date-picker v-model="ruleForm.endTime" type="datetime" placeholder="结束时间" style="width: 100%" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="最大触发次数">
+							<el-input-number v-model="ruleForm.maxNumberOfRuns" placeholder="最大触发次数" class="w100" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="最大出错次数">
+							<el-input-number v-model="ruleForm.maxNumberOfErrors" placeholder="最大出错次数" class="w100" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="重试次数">
+							<el-input-number v-model="ruleForm.numRetries" placeholder="重试次数" class="w100" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="重试间隔(ms)">
+							<el-input-number v-model="ruleForm.retryTimeout" placeholder="重试间隔ms" class="w100" />
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="立即启动">
+							<el-radio-group v-model="ruleForm.startNow">
+								<el-radio :label="true">是</el-radio>
+								<el-radio :label="false">否</el-radio>
+							</el-radio-group>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="启动时执行一次">
+							<el-radio-group v-model="ruleForm.runOnStart">
+								<el-radio :label="true">是</el-radio>
+								<el-radio :label="false">否</el-radio>
+							</el-radio-group>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="仅执行一次">
+							<el-radio-group v-model="ruleForm.resetOnlyOnce">
+								<el-radio :label="true">是</el-radio>
+								<el-radio :label="false">否</el-radio>
+							</el-radio-group>
+						</el-form-item>
+					</el-col>
+					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
+						<el-form-item label="描述信息" prop="description">
+							<el-input v-model="ruleForm.description" placeholder="描述信息" clearable type="textarea" />
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button @click="cancel" size="default">取 消</el-button>
+					<el-button type="primary" @click="submit" size="default">确 定</el-button>
+				</span>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+
+<script lang="ts">
+import { reactive, toRefs, defineComponent, ref } from 'vue';
+import mittBus from '/@/utils/mitt';
+
+import { getAPI } from '/@/utils/axios-utils';
+import { SysJobApi } from '/@/api-services/api';
+import { UpdateJobTriggerInput } from '/@/api-services/models';
+
+export default defineComponent({
+	name: 'sysEditJobTrigger',
+	components: {},
+	props: {
+		title: {
+			type: String,
+			default: '',
+		},
+	},
+	setup() {
+		const ruleFormRef = ref();
+		const state = reactive({
+			isShowDialog: false,
+			ruleForm: {} as UpdateJobTriggerInput,
+		});
+		// 打开弹窗
+		const openDialog = (row: any) => {
+			state.ruleForm = JSON.parse(JSON.stringify(row));
+			state.isShowDialog = true;
+		};
+		// 关闭弹窗
+		const closeDialog = () => {
+			mittBus.emit('submitRefresh');
+			state.isShowDialog = false;
+		};
+		// 取消
+		const cancel = () => {
+			state.isShowDialog = false;
+		};
+		// 提交
+		const submit = () => {
+			ruleFormRef.value.validate(async (valid: boolean) => {
+				if (!valid) return;
+				if (state.ruleForm.id != undefined && state.ruleForm.id > 0) {
+					await getAPI(SysJobApi).sysJobTriggerUpdatePost(state.ruleForm);
+				} else {
+					await getAPI(SysJobApi).sysJobTriggerAddPost(state.ruleForm);
+				}
+				closeDialog();
+			});
+		};
+		return {
+			ruleFormRef,
+			openDialog,
+			closeDialog,
+			cancel,
+			submit,
+			...toRefs(state),
+		};
+	},
+});
+</script>

+ 55 - 0
Web/src/views/system/job/component/jobCluster.vue

@@ -0,0 +1,55 @@
+<template>
+	<div class="sys-jobCluster-container">
+		<el-drawer v-model="state.isVisible" title="作业集群" size="30%">
+			<el-card shadow="hover" style="margin: 8px">
+				<el-table :data="state.jobClusterList" style="width: 100%" v-loading="state.loading" border>
+					<el-table-column type="index" label="序号" width="55" align="center" />
+					<el-table-column prop="clusterId" label="集群编号" show-overflow-tooltip />
+					<el-table-column prop="status" label="状态" align="center" show-overflow-tooltip>
+						<template #default="scope">
+							<el-tag v-if="scope.row.status == 0"> 宕机 </el-tag>
+							<el-tag v-if="scope.row.status == 1"> 工作中 </el-tag>
+							<el-tag v-if="scope.row.status == 2"> 等待被唤醒 </el-tag>
+						</template>
+					</el-table-column>
+					<el-table-column prop="description" label="描述" show-overflow-tooltip />
+					<el-table-column prop="updatedTime " label="更新时间" show-overflow-tooltip />
+				</el-table>
+			</el-card>
+		</el-drawer>
+	</div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, reactive } from 'vue';
+
+import { getAPI } from '/@/utils/axios-utils';
+import { SysJobApi } from '/@/api-services/api';
+import { SysJobCluster } from '/@/api-services/models';
+
+const state = reactive({
+	loading: false,
+	isVisible: false,
+	jobClusterList: [] as Array<SysJobCluster>,
+});
+
+onMounted(async () => {
+	handleQuery();
+});
+// 查询操作
+const handleQuery = async () => {
+	state.loading = true;
+	var res = await getAPI(SysJobApi).sysJobClusterListGet();
+	state.jobClusterList = res.data.result ?? [];
+	state.loading = false;
+};
+// 打开页面
+const openDrawer = () => {
+	state.isVisible = true;
+};
+
+// 导出
+defineExpose({ openDrawer });
+</script>
+
+<style lang="scss"></style>

+ 153 - 31
Web/src/views/system/job/index.vue

@@ -11,7 +11,26 @@
 				<el-form-item>
 					<el-button icon="ele-Refresh" @click="resetQuery"> 重置 </el-button>
 					<el-button type="primary" icon="ele-Search" @click="handleQuery" v-auth="'sysJob:page'"> 查询 </el-button>
-					<el-button icon="ele-Plus" @click="openAddJobDetail" v-auth="'sysJob:add'"> 新增作业 </el-button>
+					<el-button-group style="margin: 0px 12px">
+						<el-tooltip content="增加作业">
+							<el-button icon="ele-CirclePlus" @click="openAddJobDetail" v-auth="'sysJob:add'"> </el-button>
+						</el-tooltip>
+						<el-tooltip content="启动所有作业">
+							<el-button icon="ele-VideoPlay" @click="startAllJob" />
+						</el-tooltip>
+						<el-tooltip content="暂停所有作业">
+							<el-button icon="ele-VideoPause" @click="pauseAllJob" />
+						</el-tooltip>
+					</el-button-group>
+					<el-button-group style="margin: 0px 12px 0px 0px">
+						<el-tooltip content="强制唤醒作业调度器">
+							<el-button icon="ele-AlarmClock" @click="cancelSleep" />
+						</el-tooltip>
+						<el-tooltip content="强制触发所有作业持久化">
+							<el-button icon="ele-Connection" @click="persistAll" />
+						</el-tooltip>
+					</el-button-group>
+					<el-button icon="ele-Coin" @click="openJobCluster" type="danger" plain> 集群控制 </el-button>
 				</el-form-item>
 			</el-form>
 		</el-card>
@@ -46,31 +65,47 @@
 							</el-table-column>
 							<el-table-column prop="startTime" label="起始时间" width="100" align="center" show-overflow-tooltip />
 							<el-table-column prop="endTime" label="结束时间" width="100" align="center" show-overflow-tooltip />
-							<el-table-column prop="lastRunTime" label="最近运行时间" width="160" align="center" show-overflow-tooltip />
-							<el-table-column prop="nextRunTime" label="下一次运行时间" width="160" align="center" show-overflow-tooltip />
+							<el-table-column prop="lastRunTime" label="最近运行时间" width="140" align="center" show-overflow-tooltip />
+							<el-table-column prop="nextRunTime" label="下一次运行时间" width="140" align="center" show-overflow-tooltip />
 							<el-table-column prop="numberOfRuns" label="触发次数" width="100" align="center" show-overflow-tooltip />
-							<el-table-column prop="maxNumberOfRuns" label="最大触发次数" width="150" align="center" show-overflow-tooltip />
+							<el-table-column prop="maxNumberOfRuns" label="最大触发次数" width="120" align="center" show-overflow-tooltip />
 							<el-table-column prop="numberOfErrors" label="出错次数" width="100" align="center" show-overflow-tooltip />
-							<el-table-column prop="maxNumberOfErrors" label="最大出错次数" width="150" align="center" show-overflow-tooltip />
+							<el-table-column prop="maxNumberOfErrors" label="最大出错次数" width="120" align="center" show-overflow-tooltip />
 							<el-table-column prop="numRetries" label="重试次数" width="100" align="center" show-overflow-tooltip />
-							<el-table-column prop="retryTimeout" label="重试间隔ms" width="120" align="center" show-overflow-tooltip />
-							<el-table-column prop="startNow" label="是否立即启动" width="120" align="center" show-overflow-tooltip>
+							<el-table-column prop="retryTimeout" label="重试间隔ms" width="100" align="center" show-overflow-tooltip />
+							<el-table-column prop="startNow" label="是否立即启动" width="100" align="center" show-overflow-tooltip>
 								<template #default="scope">
 									<el-tag v-if="scope.row.startNow == true"> 是 </el-tag>
 									<el-tag v-else> 否 </el-tag>
 								</template>
 							</el-table-column>
-							<el-table-column prop="runOnStart" label="是否启动时执行一次" width="160" align="center" show-overflow-tooltip>
+							<el-table-column prop="runOnStart" label="是否启动时执行一次" width="150" align="center" show-overflow-tooltip>
 								<template #default="scope">
 									<el-tag v-if="scope.row.runOnStart == true"> 是 </el-tag>
 									<el-tag v-else> 否 </el-tag>
 								</template>
 							</el-table-column>
-							<el-table-column prop="updatedTime" label="更新时间" width="160" align="center" show-overflow-tooltip />
+							<el-table-column prop="resetOnlyOnce" label="是否只运行一次" width="120" align="center" show-overflow-tooltip>
+								<template #default="scope">
+									<el-tag v-if="scope.row.resetOnlyOnce == true"> 是 </el-tag>
+									<el-tag v-else> 否 </el-tag>
+								</template>
+							</el-table-column>
+							<el-table-column prop="updatedTime" label="更新时间" width="140" align="center" show-overflow-tooltip />
 							<el-table-column label="操作" width="140" align="center" show-overflow-tooltip>
 								<template #default="scope">
-									<el-button icon="ele-Edit" size="small" text type="primary"> 编辑 </el-button>
-									<el-button icon="ele-Delete" size="small" text type="danger"> 删除 </el-button>
+									<el-tooltip content="启动触发器">
+										<el-button size="small" type="primary" icon="ele-VideoPlay" text @click="startTrigger(scope.row)" />
+									</el-tooltip>
+									<el-tooltip content="暂停触发器">
+										<el-button size="small" type="primary" icon="ele-VideoPause" text @click="pauseTrigger(scope.row)" />
+									</el-tooltip>
+									<el-tooltip content="编辑触发器">
+										<el-button size="small" type="primary" icon="ele-Edit" text @click="openEditJobTrigger(scope.row)"> </el-button>
+									</el-tooltip>
+									<el-tooltip content="删除触发器">
+										<el-button size="small" type="danger" icon="ele-Delete" text @click="delJobTrigger(scope.row)"> </el-button>
+									</el-tooltip>
 								</template>
 							</el-table-column>
 						</el-table>
@@ -103,11 +138,23 @@
 				</el-table-column>
 				<el-table-column prop="jobDetail.properties" label="额外数据" show-overflow-tooltip />
 				<el-table-column prop="jobDetail.updatedTime" label="更新时间" width="160" align="center" show-overflow-tooltip />
-				<el-table-column label="操作" width="230" fixed="right" align="center" show-overflow-tooltip>
+				<el-table-column label="操作" width="170" fixed="right" align="center" show-overflow-tooltip>
 					<template #default="scope">
-						<el-button icon="ele-Clock" size="small" text type="warning"> 新增触发器 </el-button>
-						<el-button icon="ele-Edit" size="small" text type="primary" @click="openEditJobDetail(scope.row)" v-auth="'sysJob:update'"> 编辑 </el-button>
-						<el-button icon="ele-Delete" size="small" text type="danger" @click="delJobDetail(scope.row)" v-auth="'sysJob:delete'"> 删除 </el-button>
+						<el-tooltip content="增加触发器">
+							<el-button size="small" type="primary" icon="ele-CirclePlus" text @click="openAddJobTrigger"> </el-button>
+						</el-tooltip>
+						<el-tooltip content="启动作业">
+							<el-button size="small" type="primary" icon="ele-VideoPlay" text @click="startJob(scope.row)" />
+						</el-tooltip>
+						<el-tooltip content="暂停作业">
+							<el-button size="small" type="primary" icon="ele-VideoPause" text @click="pauseJob(scope.row)" />
+						</el-tooltip>
+						<el-tooltip content="编辑作业">
+							<el-button size="small" type="primary" icon="ele-Edit" text @click="openEditJobDetail(scope.row)" v-auth="'sysJob:update'"> </el-button>
+						</el-tooltip>
+						<el-tooltip content="删除作业">
+							<el-button size="small" type="danger" icon="ele-Delete" text @click="delJobDetail(scope.row)" v-auth="'sysJob:delete'"> </el-button>
+						</el-tooltip>
 					</template>
 				</el-table-column>
 			</el-table>
@@ -124,15 +171,19 @@
 			/>
 		</el-card>
 		<EditJobDetail ref="editJobDetailRef" :title="editJobDetailTitle" />
+		<EditJobTrigger ref="editJobTriggerRef" :title="editJobTriggerTitle" />
+		<JobCluster ref="editJobClusterRef" />
 	</div>
 </template>
 
 <script lang="ts">
-import { toRefs, reactive, onMounted, ref, defineComponent, onUnmounted, onActivated, onDeactivated } from 'vue';
+import { toRefs, reactive, onMounted, ref, defineComponent, onUnmounted } from 'vue';
 import { ElMessageBox, ElMessage } from 'element-plus';
 import mittBus from '/@/utils/mitt';
 import { Timer } from '@element-plus/icons-vue';
 import EditJobDetail from '/@/views/system/job/component/editJobDetail.vue';
+import EditJobTrigger from '/@/views/system/job/component/editJobTrigger.vue';
+import JobCluster from '/@/views/system/job/component/jobCluster.vue';
 
 import { getAPI } from '/@/utils/axios-utils';
 import { SysJobApi } from '/@/api-services/api';
@@ -140,9 +191,11 @@ import { JobOutput } from '/@/api-services/models';
 
 export default defineComponent({
 	name: 'sysJob',
-	components: { Timer, EditJobDetail },
+	components: { Timer, EditJobDetail, EditJobTrigger, JobCluster },
 	setup() {
 		const editJobDetailRef = ref();
+		const editJobTriggerRef = ref();
+		const editJobClusterRef = ref();
 		const state = reactive({
 			loading: false,
 			jobData: [] as Array<JobOutput>,
@@ -156,7 +209,7 @@ export default defineComponent({
 				total: 0 as any,
 			},
 			editJobDetailTitle: '',
-			timer: null as any,
+			editJobTriggerTitle: '',
 		});
 		onMounted(async () => {
 			handleQuery();
@@ -189,7 +242,6 @@ export default defineComponent({
 		};
 		// 打开编辑作业页面
 		const openEditJobDetail = (row: any) => {
-			console.log(row)
 			state.editJobDetailTitle = '编辑作业';
 			editJobDetailRef.value.openDialog(row.jobDetail);
 		};
@@ -207,6 +259,31 @@ export default defineComponent({
 				})
 				.catch(() => {});
 		};
+		// 打开新增触发器页面
+		const openAddJobTrigger = () => {
+			state.editJobTriggerTitle = '添加触发器';
+			editJobTriggerRef.value.openDialog({ retryTimeout: 1000, startNow: true, runOnStart: true, resetOnlyOnce: true });
+		};
+		// 打开编辑触发器页面
+		const openEditJobTrigger = (row: any) => {
+			console.log(row);
+			state.editJobTriggerTitle = '编辑触发器';
+			editJobTriggerRef.value.openDialog(row);
+		};
+		// 删除触发器
+		const delJobTrigger = (row: any) => {
+			ElMessageBox.confirm(`确定删除触发器:【${row.triggerId}】?`, '提示', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(async () => {
+					await getAPI(SysJobApi).sysJobTriggerDeletePost({ triggerId: row.triggerId });
+					handleQuery();
+					ElMessage.success('删除成功');
+				})
+				.catch(() => {});
+		};
 		// 改变页面容量
 		const handleSizeChange = (val: number) => {
 			state.tableParams.pageSize = val;
@@ -217,20 +294,54 @@ export default defineComponent({
 			state.tableParams.page = val;
 			handleQuery();
 		};
-		// 修改状态
-		const changeStatus = async (row: any) => {
-			//await getAPI(SysJobApi).sysTimerSetStatusPost({ timerName: row.timerName, status: row.status });
+		// 启动所有作业
+		const startAllJob = async () => {
+			await getAPI(SysJobApi).sysJobStartAllPost();
+			ElMessage.success('启动所有作业');
+		};
+		// 暂停所有作业
+		const pauseAllJob = async () => {
+			await getAPI(SysJobApi).sysJobPauseAllPost();
+			ElMessage.success('暂停所有作业');
+		};
+		// 启动某个作业
+		const startJob = async (row: any) => {
+			await getAPI(SysJobApi).sysJobStartJobPost({ jobId: row.jobDetail.jobId });
+			ElMessage.success('启动作业');
+		};
+		// 暂停某个作业
+		const pauseJob = async (row: any) => {
+			await getAPI(SysJobApi).sysJobPauseJobPost({ jobId: row.jobDetail.jobId });
+			ElMessage.success('暂停作业');
+		};
+		// 启动触发器
+		const startTrigger = async (row: any) => {
+			await getAPI(SysJobApi).sysJobStartTriggerPost({ jobId: row.jobId, triggerId: row.triggerId });
+			ElMessage.success('启动触发器');
+		};
+		// 暂停触发器
+		const pauseTrigger = async (row: any) => {
+			await getAPI(SysJobApi).sysJobPauseTriggerPost({ jobId: row.jobId, triggerId: row.triggerId });
+			ElMessage.success('暂停触发器');
+		};
+		// 强制唤醒作业调度器
+		const cancelSleep = async () => {
+			await getAPI(SysJobApi).sysJobCancelSleepPost();
+			ElMessage.success('强制唤醒作业调度器');
+		};
+		// 强制触发所有作业持久化
+		const persistAll = async () => {
+			await getAPI(SysJobApi).sysJobPersistAllPost();
+			ElMessage.success('强制触发所有作业持久化');
+		};
+		// 打开集群控制页面
+		const openJobCluster = () => {
+			editJobClusterRef.value.openDrawer();
 		};
-		onActivated(() => {
-			// state.timer = setInterval(() => {
-			// 	handleQuery();
-			// }, 10000);
-		});
-		onDeactivated(() => {
-			clearInterval(state.timer);
-		});
 		return {
 			editJobDetailRef,
+			editJobTriggerRef,
+			editJobClusterRef,
 			handleQuery,
 			resetQuery,
 			openAddJobDetail,
@@ -238,7 +349,18 @@ export default defineComponent({
 			delJobDetail,
 			handleSizeChange,
 			handleCurrentChange,
-			changeStatus,
+			openAddJobTrigger,
+			openEditJobTrigger,
+			delJobTrigger,
+			startAllJob,
+			pauseAllJob,
+			startJob,
+			pauseJob,
+			startTrigger,
+			pauseTrigger,
+			cancelSleep,
+			persistAll,
+			openJobCluster,
 			...toRefs(state),
 		};
 	},