hwh
2024-06-24 98a44975b0c4755e2a709d5ef7f912809af09860
定时任务页面
3个文件已修改
1个文件已添加
398 ■■■■■ 已修改文件
HTML/views/SystemSettings/Job.html 342 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Wms/Utility/Entity/JobInfoEntity.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Wms/Utility/Job/SchedulerCenter.cs 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Wms/Wms/Controllers/JobController.cs 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
HTML/views/SystemSettings/Job.html
New file
@@ -0,0 +1,342 @@
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>定时任务列表</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport"
        content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
    <script>
        // 这里是需要在页面渲染之前执行的代码
        document.addEventListener("DOMContentLoaded", function () {
            //获取table默认显示数
            pageCntFirst();
        });
    </script>
</head>
<body id="body">
    <div class="layui-fluid" style="padding-bottom: 0; ">
        <div class="layui-card">
            <div class="layui-form layui-card-header layuiadmin-card-header-auto" style="border-bottom:1px solid #CCC"
                id="top">
                <div class="layui-form-item">
                    <div class="layui-inline">
                        <button class="layui-btn layui-btn-sm layuiadmin-btn-list" lay-submit
                            lay-filter="LAY-app-contlist-add">
                            <i class="layui-icon layui-icon-add-1 layuiadmin-button-btn"></i>添加
                        </button>
                    </div>
                </div>
            </div>
            <div id="center"></div>
            <div class="layui-card-body">
                <table id="LAY-app-content-list" lay-filter="LAY-app-content-list"></table>
            </div>
        </div>
    </div>
    <script src="../../layuiadmin/layui/layui.js"></script>
    <script src="../../js/public.js"></script>
    <script src="../../js/jquery-3.5.1.min.js"></script>
    <script src="../../js/jquery.cookie.js"></script>
    <script type="text/html" id="toolBar">
        <!-- d代表的是layui 引擎模板中所使用的单个数据 -->
        {{#  if(d.TriggerState ==0){ }}
    <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="Pause">
        <i class="layui-icon layui-icon-pause"></i>暂停</a>
    {{# } }}
    {{# if(d.TriggerState ==1){ }}
    <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="Play">
        <i class="layui-icon layui-icon-play"></i>开始</a>
    {{# } }}
    <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-edit"></i>编辑</a>
    <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>删除</a>
    <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="detail"><i
            class="layui-icon layui-icon-log"></i>日志</a>
    <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="execute"><i
            class="layui-icon layui-icon-triangle-r"></i>执行</a>
    </script>
    <script>
        layui.config({
            base: '../../layuiadmin/' //静态资源所在路径
        }).extend({
            index: 'lib/index' //主入口模块
        }).use(['index', 'table', 'laypage', 'layer'], function () {
            var table = layui.table,
                form = layui.form,
                laypage = layui.laypage,
                layer = layui.layer;
            var h1 = GetTableHeight();
            refreshTable("", "", "", "", "");
            var tableIns;
            function refreshTable(MenuName, Type, Msg, MenuNo, ParentNo) {
                var param = {
                    MenuName: MenuName,
                    Type: Type,
                    Msg: Msg,
                    MenuNo: MenuNo,
                    ParentNo: ParentNo,
                };
                ParentNo = '系统设置'; //模块名称
                var url = "/Job/GetAllJob";
                sendData(IP + url, {}, 'get', function (res) {
                    // console.log(res.data)
                    if (res.code == 200) //成功
                    {
                        var list = res.data;
                        $.extend(infoOptions, {
                            data: list
                        });
                        tableIns = table.render(infoOptions);
                    }
                    else //不成功
                    {
                        layer.msg('获取任务列表信息失败!', {
                            icon: 2,
                            time: 2000 //2秒关闭(如果不配置,默认是3秒)
                        }, function () { });
                    }
                });
            }
            var infoOptions = {
                elem: '#LAY-app-content-list',
                height: h1,
                id: 'LAY-app-content-list',
                page: false,
                limit: pageCnt,
                limits: pageLimits,
                even: true,
                cols:
                    [[
                        {
                            title: '序号', type: 'numbers', fixed: 'left', width: 65
                        },
                        {
                            field: 'Name', title: '任务名称', align: 'center', fixed: 'left', width: 100
                        },
                        {
                            field: 'JobType', title: '类型', align: 'center', fixed: 'left', width: 80, templet: function (d) {
                                if (d.JobType == 1) {
                                    return 'Http'
                                } else if (d.JobType == 2) {
                                    return '内置'
                                } else if (d.JobType == 3) {
                                    return '热加载'
                                }
                            }
                        },
                        {
                            field: 'RunNumber', title: '触发次数', align: 'center', width: 100
                        },
                        {
                            field: 'DisplayState', title: '状态', align: 'center', width: 80
                        },
                        // {
                        //     field: 'TriggerState', title: '状态', align: 'center', width: 80, templet: function (d) {
                        //         switch (d.TriggerState) {
                        //             case 0:
                        //                 return '正常'
                        //             case 1:
                        //                 return '暂停'
                        //             case 2:
                        //                 return '完成'
                        //             case 3:
                        //                 return '异常'
                        //             case 4:
                        //                 return '阻塞'
                        //             case 5:
                        //                 return '不存在'
                        //             default:
                        //                 return '未知';
                        //         }
                        //     }
                        // },
                        {
                            field: 'PreviousFireTime', title: '上次执行时间', align: 'center', width: 170, templet: function (d) {
                                return formatDateTime(d.PreviousFireTime)
                            }
                        },
                        {
                            field: 'NextFireTime', title: '下次执行时间', align: 'center', width: 170, templet: function (d) {
                                return formatDateTime(d.NextFireTime)
                            }
                        },
                        {
                            field: 'Description', title: '描述', align: 'center'
                        },
                        {
                            field: 'caozuo', title: '操作', fixed: 'right', width: 340, align: 'left', toolbar: "#toolBar"
                        }
                    ]]
            };
            table.on('tool(LAY-app-content-list)', function (obj) {
                var data = obj.data;
                switch (obj.event) {
                    case "execute":
                        sendData(IP + "/Job/TriggerJob", { Name: data.Name, Group: data.GroupName }, 'post', function (res) {
                            console.log(res);
                            if (res.code == 200) { //成功
                                layer.msg(res.msg, {
                                    icon: 1,
                                    time: 3000 //1秒关闭(如果不配置,默认是3秒)
                                }, function () {
                                    doing = true;
                                });
                            } else { //不成功
                                layer.msg(res.msg, {
                                    icon: 2,
                                    time: 3000 //2秒关闭(如果不配置,默认是3秒)
                                }, function () {
                                    doing = true;
                                });
                            }
                            layer.close(index);
                        });
                        break;
                    case "edit":
                        break;
                    case "del":
                        sendData(IP + "/Job/RemoveJob", { Name: data.Name, Group: data.GroupName }, 'post', function (res) {
                            console.log(res);
                            if (res.code == 200) { //成功
                                layer.msg(res.msg, {
                                    icon: 1,
                                    time: 3000 //1秒关闭(如果不配置,默认是3秒)
                                }, function () {
                                    refreshTable("", "", "", "", "");
                                    doing = true;
                                });
                            } else { //不成功
                                layer.msg(res.msg, {
                                    icon: 2,
                                    time: 3000 //2秒关闭(如果不配置,默认是3秒)
                                }, function () {
                                    refreshTable("", "", "", "", "");
                                    doing = true;
                                });
                            }
                            layer.close(index);
                        });
                        break;
                    case "detail":
                        sendData(IP + "/Job/GetJobLogs", { Name: data.Name, Group: data.GroupName }, 'post', function (res) {
                            console.log(res);
                            if (res.code == 200) { //成功
                                layer.open({
                                    type: 1,
                                    area: ['80%', '80%'], // 宽高
                                    content: res.data.join('\n')
                                });
                            } else { //不成功
                                layer.msg(res.msg, {
                                    icon: 2,
                                    time: 3000 //2秒关闭(如果不配置,默认是3秒)
                                }, function () {
                                    refreshTable("", "", "", "", "");
                                    doing = true;
                                });
                            }
                            layer.close(index);
                        });
                        break;
                    case "Play":
                        sendData(IP + "/Job/ResumeJob", { Name: data.Name, Group: data.GroupName }, 'post', function (res) {
                            console.log(res);
                            if (res.code == 200) { //成功
                                layer.msg(res.msg, {
                                    icon: 1,
                                    time: 3000 //1秒关闭(如果不配置,默认是3秒)
                                }, function () {
                                    refreshTable("", "", "", "", "");
                                    doing = true;
                                });
                            } else { //不成功
                                layer.msg(res.msg, {
                                    icon: 2,
                                    time: 3000 //2秒关闭(如果不配置,默认是3秒)
                                }, function () {
                                    refreshTable("", "", "", "", "");
                                    doing = true;
                                });
                            }
                            layer.close(index);
                        });
                        break;
                    case "Pause":
                        sendData(IP + "/Job/StopJob", { Name: data.Name, Group: data.GroupName }, 'post', function (res) {
                            console.log(res);
                            if (res.code == 200) { //成功
                                layer.msg(res.msg, {
                                    icon: 1,
                                    time: 3000 //1秒关闭(如果不配置,默认是3秒)
                                }, function () {
                                    refreshTable("", "", "", "", "");
                                    doing = true;
                                });
                            } else { //不成功
                                layer.msg(res.msg, {
                                    icon: 2,
                                    time: 3000 //2秒关闭(如果不配置,默认是3秒)
                                }, function () {
                                    refreshTable("", "", "", "", "");
                                    doing = true;
                                });
                            }
                            layer.close(index);
                        });
                        break;
                }
            });
            //监听搜索
            form.on('submit(LAY-app-contlist-search)', function (data) {
                // console.log(data)
                var MenuName = data.field.MenuName;
                var Type = data.field.Type;
                var Msg = data.field.Msg;
                var MenuNo = data.field.MenuNo;
                //MenuName, Type, Msg, MenuNo,ParentNo
                refreshTable(MenuName, Type, Msg, MenuNo);
            });
            var doing = true;
            // $('.layui-btn.layuiadmin-btn-list').on('click', function() {
            //     var type = $(this).data('type');
            //     active[type] ? active[type].call(this) : '';
            // });
        });
        function formatDateTime(inputDateTime) {
            // 创建一个日期对象,用于解析输入的日期时间字符串
            let date = new Date(inputDateTime);
            // 提取年、月、日、时、分、秒
            let year = date.getFullYear();
            let month = ('0' + (date.getMonth() + 1)).slice(-2);  // 月份从0开始,需要加1,并确保两位数
            let day = ('0' + date.getDate()).slice(-2);           // 日需要确保两位数
            let hours = ('0' + date.getHours()).slice(-2);        // 小时需要确保两位数
            let minutes = ('0' + date.getMinutes()).slice(-2);    // 分钟需要确保两位数
            let seconds = ('0' + date.getSeconds()).slice(-2);    // 秒钟需要确保两位数
            // 拼接成所需的格式
            let formattedDateTime = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
            return formattedDateTime;
        }
    </script>
</body>
</html>
Wms/Utility/Entity/JobInfoEntity.cs
@@ -26,6 +26,11 @@
        public string Name { get; set; }
        /// <summary>
        /// 任务组名
        /// </summary>
        public string GroupName { get; set; }
        /// <summary>
        /// 下次执行时间
        /// </summary>
        public DateTime? NextFireTime { get; set; }
Wms/Utility/Job/SchedulerCenter.cs
@@ -357,12 +357,38 @@
                        if (jobType == JobTypeEnum.Url)
                            triggerAddress = jobDetail.JobDataMap.GetString(Constant.REQUESTURL);
                        else if (jobType == JobTypeEnum.BuiltIn)
                            triggerAddress = jobDetail.JobDataMap.GetString(Constant.BuiltIn);
                            triggerAddress = jobDetail.JobDataMap.GetString(Constant.CLASSNAME);
                        var lastErrMsg = string.Empty;
                        try
                        {
                            lastErrMsg = jobDetail.JobDataMap.GetString(Constant.EXCEPTION);
                        }
                        catch (Exception)
                        {
                        }
                        var requestType = string.Empty;
                        try
                        {
                            requestType = jobDetail.JobDataMap.GetString(Constant.REQUESTTYPE);
                        }
                        catch (Exception)
                        {
                        }
                        long runNumber = 0;
                        try
                        {
                            runNumber = jobDetail.JobDataMap.GetLong(Constant.RUNNUMBER);
                        }
                        catch (Exception)
                        {
                        }
                        jobInfo.JobInfoList.Add(new JobInfo()
                        {
                            Name = jobKey.Name,
                            LastErrMsg = jobDetail.JobDataMap.GetString(Constant.EXCEPTION),
                            LastErrMsg = lastErrMsg,
                            TriggerAddress = triggerAddress,
                            TriggerState = await scheduler.GetTriggerState(triggers.Key),
                            PreviousFireTime = triggers.GetPreviousFireTimeUtc()?.LocalDateTime,
@@ -371,8 +397,8 @@
                            Interval = interval,
                            EndTime = triggers.EndTimeUtc?.LocalDateTime,
                            Description = jobDetail.Description,
                            RequestType = jobDetail.JobDataMap.GetString(Constant.REQUESTTYPE),
                            RunNumber = jobDetail.JobDataMap.GetLong(Constant.RUNNUMBER),
                            RequestType = requestType,
                            RunNumber = runNumber,
                            JobType = (long)jobType
                            //(triggers as SimpleTriggerImpl)?.TimesTriggered
                            //CronTriggerImpl 中没有 TimesTriggered 所以自己RUNNUMBER记录
Wms/Wms/Controllers/JobController.cs
@@ -7,14 +7,16 @@
using Utility.Entity;
using Utility;
using Model.ModelVm;
using Microsoft.AspNetCore.Authorization;
namespace Wms.Controllers
{
    /// <summary>
    /// 任务调度
    /// </summary>
    [Route("api/[controller]/[Action]")]
    [EnableCors("AllowSameDomain")] //允许跨域
    [Route("api/[controller]/[action]")]
    [ApiController]
    [Authorize]
    [ServiceFilter(typeof(ApiResponseActionFilter))]
    public class JobController : ControllerBase
    {
@@ -153,9 +155,16 @@
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<List<JobInfoEntity>> GetAllJob()
        public async Task<List<JobInfo>> GetAllJob()
        {
            return await scheduler.GetAllJobAsync();
            var list = await scheduler.GetAllJobAsync();
            var listJob = new List<JobInfo>();
            foreach (var mod in list)
            {
                mod.JobInfoList.ForEach(s => s.GroupName = mod.GroupName);
                listJob.AddRange(mod.JobInfoList);
            }
            return listJob;
        }
        /// <summary>