/// <summary>
        ///     Trigger 被触发并且完成了 Job 的执行时,Scheduler 调用这个方法。这不是说这个 Trigger 将不再触发了,而仅仅是当前 Trigger 的触发(并且紧接着的 Job 执行) 结束时。这个 Trigger
        ///     也许还要在将来触发多次的。
        ///     Called by the Quartz.IScheduler when a Quartz.ITrigger has fired, it's associated
        ///     Quartz.IJobDetail has been executed, and it's Quartz.Spi.IOperableTrigger.Triggered(Quartz.ICalendar)
        ///     method has been called.
        /// </summary>
        /// <param name="trigger">The Quartz.ITrigger that was fired.</param>
        /// <param name="context">
        ///     The Quartz.IJobExecutionContext that was passed to the
        ///     Quartz.IJob'sQuartz.IJob.Execute(Quartz.IJobExecutionContext) method.
        /// </param>
        /// <param name="triggerInstructionCode">
        ///     The result of the call on the
        ///     Quartz.ITrigger'sQuartz.Spi.IOperableTrigger.Triggered(Quartz.ICalendar) method.
        /// </param>
        /// <param name="cancellationToken">The cancellation instruction.</param>
        /// <returns></returns>
        public virtual async Task TriggerComplete(ITrigger trigger, IJobExecutionContext context,
                                                  SchedulerInstruction triggerInstructionCode,
                                                  CancellationToken cancellationToken = default)
        {
            Debug(nameof(ITriggerListener), nameof(TriggerComplete));
            var beginTicks   = context.GetJobBeginDateTimeTicks();
            var milliseconds = (long)TimeSpan.FromTicks(DateTime.Now.Ticks - beginTicks).TotalMilliseconds;

            if (milliseconds > 5 * 1000)
            {
                JobLogHelper.Warn($"{JobInfo} 耗时{milliseconds} ms ", null, nameof(TriggerComplete));
            }
            else if (milliseconds > 0)
            {
                JobLogHelper.Info($"{JobInfo} 耗时{milliseconds} ms ", nameof(TriggerComplete));
            }
            var bizState    = context.GetJobBusinessState();
            var bizStatsStr = bizState.ToString();

            if (bizState == JobBusinessStateEnum.Success)
            {
                bizStatsStr = $"<font color=#20CE43>{bizState}</font>";
            }
            if (bizState == JobBusinessStateEnum.Fail)
            {
                bizStatsStr = $"<font color=#FF0000>{bizState}</font>";
            }
            await DoNoticeAsync($"耗时 {milliseconds} ms. 任务状态为 {bizStatsStr}", context.GetTempConfig("BizContent").ToString());

            await Task.CompletedTask;
        }
        /// <summary>
        ///     Job完成后调用
        ///     Called by the Quartz.IScheduler after a Quartz.IJobDetail has been executed,
        ///     and be for the associated Quartz.Spi.IOperableTrigger's Quartz.Spi.IOperableTrigger.Triggered(Quartz.ICalendar)
        ///     method has been called.
        /// </summary>
        /// <param name="context">
        ///     The Quartz.IJobExecutionContext that will be passed to the
        ///     Quartz.IJob'sQuartz.IJob.Execute(Quartz.IJobExecutionContext) method.
        /// </param>
        /// <param name="cancellationToken">The cancellation instruction.</param>
        /// <param name="jobException"></param>
        /// <returns></returns>
        public virtual async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException,
                                                 CancellationToken cancellationToken = default)
        {
            Debug(nameof(IJobListener), nameof(JobWasExecuted));
            var retCode = 0;

            try
            {
                var jobName = context.GetJobName();
                // var jobCode = JobContextFunc.GetJobCode(context);

                var autoClose = context.GetAutoClose();
                var runParams = context.GetJobRunParams();

                // 如果是单次运行,则删除job
                // OnceJob not support now
                if (context.IsOnceJob())
                {
                    var delJobRet = await new ScheduleCtrl().StopJobAsync(jobName);
                    if (delJobRet != JobActionRetEnum.Success)
                    {
                        JobLogHelper.Error(
                            $"{JobInfo}:单次运行job结束后删除job失败,job :{JobContext.CurrentJobBaseInfo},返回结果:{delJobRet }", null, nameof(JobWasExecuted));
                    }
                }

                var jobId = JobId;

                var jobRunState = JobRunStateEnum.Ok;

                if (jobException != null)
                {
                    jobRunState = JobRunStateEnum.Exception;
                    JobLogHelper.Error($"{JobInfo} 发生异常",
                                       jobException, nameof(JobWasExecuted));
                }
                else
                {
                    var jobBusinessState = context.GetJobBusinessState();
                    switch (jobBusinessState)
                    {
                    case JobBusinessStateEnum.Unknown:     //基本上是没有继承BaseJob的
                        JobLogHelper.Info($"{JobInfo} 获取到Job的业务状态为 {JobBusinessStateEnum.Unknown},可能是该Job 未继承BaseJob ", nameof(JobWasExecuted));
                        break;

                    case JobBusinessStateEnum.Success:
                        break;

                    case JobBusinessStateEnum.Fail:
                        jobRunState = JobRunStateEnum.BusinessError;
                        break;

                    default:
                        jobRunState = JobRunStateEnum.Error;
                        JobLogHelper.Error(
                            $"{JobInfo} 发生异常,无法获取到Job的业务状态", null, nameof(JobWasExecuted));
                        break;
                    }
                }

                var msg =
                    $"{JobInfo} end time:{DateTime.Now:yyyy-MM-dd HH:mm:sss}, jobRunState:{jobRunState},autoClose:{autoClose}, runParams:{runParams}";
                JobLogHelper.Info(msg, nameof(JobWasExecuted));

                // DoJobLog
                var ctrl = Ioc.GetService <IScheduleOrderCtrl>();
                if (ctrl != null)
                {
                    await ctrl.CompleteJobSafety(JobId, jobRunState);
                }
            }
            catch (Exception ex)
            {
                JobLogHelper.Info($"{JobInfo}: JobWasExecuted Error {ex}", nameof(JobWasExecuted));
                retCode = 1;
            }
            finally
            {
                var autoClose = JobContextFunc.GetAutoClose(context);
                if (autoClose)
                {
                    // TODO 通知注册中心下线
                    Environment.Exit(retCode);
                }
            }

            await Task.CompletedTask;
            //  return TaskUtil.CompletedTask;
        }