<template>
    <ap-container>
        <ap-aside margin="1111" width="180px" class="type-tree">
            <ap-aside-tree :options.sync="treeOptions">
                <el-form slot="form" ref="tSysTaskPlanType" :inline="true" label-width="80px"
                         :model="tSysTaskPlanTypeForm" :rules="tSysTaskPlanTypeRules">
                    <el-form-item label="父节点">
                        <el-select v-model="tSysTaskPlanTypeForm.fdParentId" filterable placeholder="请选择父节点">
                            <el-option label="无" value=""></el-option>
                            <el-option
                                v-for="item in typeList"
                                :key="item.fdId"
                                :label="item.fdName"
                                :value="item.fdId">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label='名称' prop='fdName'>
                        <el-input v-model='tSysTaskPlanTypeForm.fdName'></el-input>
                    </el-form-item>
                    <el-form-item label='排序' prop='fdSort'>
                        <el-input v-model='tSysTaskPlanTypeForm.fdSort'></el-input>
                    </el-form-item>
                </el-form>
                <span slot="tree" slot-scope="scope" style="font-size: 14px">
                    {{ scope.data.fdName }}
                </span>
            </ap-aside-tree>
        </ap-aside>
        <ap-split-panel></ap-split-panel>
        <ap-container>
            <ap-header margin="1110">
                <el-form ref="tSysTaskPlanSearchForm" :model="tSysTaskPlanSearchForm"
                         :rules="tSysTaskPlanSearchFormRules"
                         :inline="true" class="layout-header-form" @submit.native.prevent="searchEvent">
                    <el-form-item label="搜索:" class="layout-header-form-item" prop="likeStr">
                        <el-input v-model="tSysTaskPlanSearchForm.likeStr" placeholder="计划名/任务名/负责人/编码/邮箱/备注"
                                  style="width: 300px"></el-input>
                    </el-form-item>
                </el-form>
                <el-button type="primary" @click="searchEvent">查询</el-button>
            </ap-header>
            <ap-main margin="0110">
                <ap-table ref="tSysTaskPlanTableRef" :options.sync="tSysTaskPlanTable"></ap-table>
            </ap-main>
        </ap-container>
        <el-dialog title="Cron运行时间模拟" :visible.sync="showCronDialog" width="500px" :append-to-body="true">
            <div>
                Cron表达式：
                <span class="ap-color-blue">{{selectedCron}}</span>
            </div>
            <div>
                模拟最近运行次数：
                <el-input-number v-model="cronCount" :min=1></el-input-number>
            </div>
            <div style="height: 250px;overflow-y: auto;border: 1px solid #dfe4ed;padding: 5px;margin-top: 5px">
                <div v-for="(item, index) in cronExeList">
                    <span class="ap-color-blue">{{index + 1 }}. </span><span>{{item}}</span>
                </div>
            </div>
            <span slot="footer">
                <el-button @click="showCronDialog = false">取 消</el-button>
                <el-button type="primary" @click="cronTest"><i class="el-icon-bug"/> 模拟运行</el-button>
            </span>
        </el-dialog>
    </ap-container>
</template>

<script>
import {getHrefParams} from "ap-util/util/WindowUtil";

export default {
    name: 'SysTaskPlan',
    data() {
        let tSysTaskPlanCols = [
            {
                prop: 'fdName',
                label: '名称',
                minWidth: "120",
                type: 'input',
                html: function (value, row) {
                    if (row.loadStatus != 1 || row.fdDisabled == 1) {
                        return `<div class="ap-color-red">${value}</div>`;
                    }
                    return value;
                }
            }, {
                prop: 'fdCode',
                label: '编码',
                width: "80",
                type: 'input',
                help: "其他模块手动触发调度任务<br>this.$request({<br>" +
                    "    url: '/apt/sys/TSysTaskPlan/doTaskByCode',<br>" +
                    "    method: 'post',<br>" +
                    "    data:{code:'xxxx', comment: '备注'}<br>" +
                    "}).then(response => {<br>" +
                    "});"
            }, {
                prop: 'fdTypeId',
                label: '计划类型',
                type: 'select',
                width: "80",
                showOverflowTooltip: true,
                selectOptionsRemote: 'typeList',
                selectOptionsKey: {label: "fdName", value: "fdId"},
                addDefaultValue: () => {
                    return this.selectedId;
                }
            }, {
                prop: 'taskName',
                label: '调度任务',
                minWidth: "80",
                type: "searchPicker",
                showOverflowTooltip: true,
                searchPickerTitle: "选择调度任务",
                searchPickerUrl: "/apt/sys/TSysTaskType/getTSysTaskTypeList",
                searchPickerUrlMain: "/apt/sys/TSysTask/getTSysTaskList",
                searchPickerParamsMain: (row, col, selectedNode) => {
                    return {typeId: selectedNode.fdId}
                },
                searchPickerRenderKey: {idKey: "fdTypeId"},
                searchPickerConfirm: (row, selectedRows) => {
                    if (selectedRows.length < 1) {
                        this.$message.error("请选择调度任务");
                        return false;
                    }
                    row.fdTaskId = selectedRows[0].fdId;
                    row.taskName = selectedRows[0].fdName;
                    return true;
                },
                searchPickerClear: (row) => {
                    return true;
                },
                renderKey: {label: "fdName", value: "fdId", key: "fdTaskId"},
                renderOptionsRemote: "taskList",
            }, {
                prop: 'taskPath',
                label: '任务路径',
                width: "60px",
                type: 'input',
                showOverflowTooltip: true,
                add: false,
                edit: false
            },{
                prop: 'fdPersonName',
                label: '负责人',
                width: "50",
                type: 'input',
                add: false,
                edit: false
            }, {
                prop: 'fdCron',
                label: 'cron表达式',
                width: "90px",
                type: 'input',
                showOverflowTooltip: true,
                help: this.getCronHelp()
            }, {
                prop: 'cronCHN',
                label: 'cron中文',
                width: "100px",
                type: 'input',
                showOverflowTooltip: true,
                add: false,
                edit: false
            }, {
                prop: 'fdCount',
                label: '次/天',
                width: "40px",
                align: "center",
                type: 'input',
                add: false,
                edit: false,
                html: function (value, row) {
                    if (value == null) {
                        return `<div class="ap-color-red">无</el-tag>`;
                    }
                    if (value <= 24) {
                        return `<div class="ap-color-green">${value}</el-tag>`;
                    } else if (value <= 48) {
                        return `<div class="ap-color-yellow">${value}</el-tag>`;
                    } else {
                        return `<div class="ap-color-red">${value}</el-tag>`;
                    }
                }
            }, {
                prop: 'fdAvgConsume',
                label: '耗时/秒',
                width: "60px",
                align: "center",
                type: 'input',
                add: false,
                edit: false,
                help: '最近10次执行平均用时',
                html: function (value, row) {
                    if (value == null) {
                        return `<div class="ap-color-gray">-</el-tag>`;
                    }
                    if (value <= 1) {
                        return `<div class="ap-color-green">${value}</el-tag>`;
                    }
                    let newValue = Math.round(value);
                    if (value <= 30) {
                        return `<div class="ap-color-green">${newValue}</el-tag>`;
                    } else if (value <= 60)  {
                        return `<div class="ap-color-yellow">${value}</el-tag>`;
                    } else{
                        return `<div class="ap-color-red">${value}</el-tag>`;
                    }
                }
            }, {
                prop: 'env',
                label: '环境',
                width: "45px",
                type: "select",
                align: "center",
                selectMultiple: true,
                selectOptionsKey: {label: "fdComment", value: "fdId"},
                selectOptionsRemote: "taskEnvList",
                showOverflowTooltip: true,
                help: '调度计划可执行的环境，避免多次调用。'
            }, {
                prop: 'fdStartTime',
                label: '开始时间',
                width: "60",
                type: 'datePicker',
                hide:true
            }, {
                prop: 'fdEndTime',
                label: '结束时间',
                width: "60",
                type: 'datePicker',
                hide:true
            }, {
                prop: 'fdComment',
                label: '备注',
                minWidth: "50",
                showOverflowTooltip: true,
                type: 'input'
            }, {
                prop: 'fdEmail',
                label: '邮箱',
                minWidth: "60",
                type: 'input',
                showOverflowTooltip: true,
                help: '任务执行失败时，推送失败信息到指定的邮箱。<br>多个邮箱使用","拼接。'
            }, {
                prop: 'fdNo',
                label: '工号',
                minWidth: "60",
                type: 'input',
                showOverflowTooltip: true,
                help: '任务执行失败时，推送失败信息到企业微信。<br>多个工号使用","拼接。'
            },{
                prop: 'fdLogLevel',
                label: '日志',
                type: 'select',
                align: "center",
                width: "50px",
                addDefaultValue: 2,
                selectOptions: [
                    {label: "全部", value: 1},
                    {label: "错误", value: 2},
                    {label: "不显示", value: 3},
                ],
                help: '【调度日志】显示级别配置。<br>全部：失败或成功的任务都显示<br>错误：只显示失败任务'
            }, {
                prop: 'fdCallback',
                label: '回调请求',
                width: "70px",
                type: 'input',
                showOverflowTooltip: true,
                help: '调度任务执行成功后，发起新的任务。详细说明参考文档'
            }, {
                prop: 'fdAutoCall',
                label: '重调',
                type: 'select',
                align: "center",
                width: "60px",
                addDefaultValue: 1,
                selectOptions: [
                    {label: "跳过", value: 0},
                    {label: "重调", value: 1}
                ],
                help: `[未执行调度重调]发起时，是否跳过该计划。<br>跳过表示不会被重新执行！<br>注1：“未执行调度”不是执行失败的任务，而是出现未知异常导致任务没有按计划执行。<br>注2：每天执行次数超过10次，建议选择跳过`,
                html: function (value, row) {
                    if (value == 1) {
                        return '<div class="ap-color-green">重调</div>'
                    } else{
                        return '<div class="ap-color-gray">跳过</el-tag>';
                    }
                },
                change: (row) => {
                    if (row.fdCount > 10 && row.fdAutoCall ==1) {
                        this.$message.error("每日执行" + row.fdCount + "次，无需自动重调。【重调】字段自动改为[跳过]");
                        row.fdAutoCall = 0;
                    }
                }
            }, {
                prop: 'fdDisabled',
                label: '生效',
                type: 'select',
                align: "center",
                width: "50px",
                addDefaultValue: 0,
                selectOptions: [
                    {label: "有效", value: 0},
                    {label: "无效", value: 1}
                ],
                html: function (value, row) {
                    if (value == 0) {
                        return '<div class="ap-tag-success" style="padding: 0 5px;">有效</div>'
                    } else if (value == 1) {
                        return '<div class="ap-tag-danger" style="padding: 0 5px;">无效</el-tag>';
                    }
                }
            }, {
                prop: 'loadStatus',
                label: '加载',
                type: 'input',
                width: "50px",
                add: false,
                edit: false,
                align: "center",
                html: function (value, row) {
                    if (value == 1) {
                        return `<div class="ap-tag-success" style="padding: 0 5px;">已载</div>`;
                    }
                    return `<div class="ap-tag-danger" style="padding: 0 5px;">未载</el-tag>`;
                },
                help: "判断是否加载到spring定时任务容器。<br>已加载：定时任务正常执行。<br>未加载：定时任务无法自动执行！"
            }, {
                prop: 'fdSort',
                label: '排序',
                width: "40",
                type: 'input'
            }
        ];
        let toolbar = [
            {
                btnType: "primary",
                text: "立即执行",
                icon: "el-icon-guide",
                onClick: () => {
                    this.doTask();
                }
            }, {
                btnType: "primary",
                text: "配置检查",
                icon: "el-icon-peizhi3",
                onClick: () => {
                    this.checkTask();
                }
            }, "separator", {
                btnType: "primary",
                text: "Cron模拟",
                icon: "el-icon-workTime",
                onClick: () => {
                    this.showCronTest();
                }
            }, {
                btnType: "primary",
                text: "刷新次数/耗时",
                icon: "el-icon-refresh",
                onClick: () => {
                    this.refreshCount();
                }
            }, "separator",
            // {
            //     btnType: "primary",
            //     text: "加载",
            //     icon: "el-icon-connection",
            //     onClick: () => {
            //         this.addTask();
            //     }
            // }, {
            //     btnType: "primary",
            //     text: "移除",
            //     icon: "el-icon-delete",
            //     onClick: () => {
            //         this.removeTask();
            //     }
            // },
            "separator",
            "sortAuto","sortDown","sortUp","separator",
            {
                btnType: "primary",
                text: "复制",
                icon: "el-icon-copy",
                onClick: this.copyTask
            },
            "separator",
            "add", "edit", "del", "refresh", "save"];
        let tSysTaskPlanTable = {
            title: "调度计划",
            columns: tSysTaskPlanCols,
            dataUrl: "/apt/sys/TSysTaskPlan/getTSysTaskPlanGridList",
            saveUrl: "/apt/sys/TSysTaskPlan/saveSysTaskPlanGridData",
            editPk: "fdId,fdName,fdCron", //默认fdId
            deletePk: "fdId", // 默认fdId
            deleteUrl: "/apt/sys/TSysTaskPlan/deleteTSysTaskPlanGridData",
            sortUrl: "/apt/sys/TSysTaskPlan/updateTSysTaskPlanSortList",
            toolbarBtn: toolbar,
            initData: true,
            params: () => {
                return {
                    likeStr: this.tSysTaskPlanSearchForm.likeStr,
                    typeIds: this.treeSelectedValues
                }
            }
        };

        return {
            // ----- 左侧树 -----
            treeOptions: this.getTreeOption(),
            tSysTaskPlanTypeForm: {},
            tSysTaskPlanTypeRules: {},
            treeSelectedValues: "",
            selectedId: "",
            typeList: [],
            // ----- 右侧 -----
            tSysTaskPlanTable: tSysTaskPlanTable,
            oldId: "",
            tSysTaskPlanSearchForm: {
                likeStr: ""
            },
            tSysTaskPlanSearchFormRules: {
            },
            selectedPlanId: "",
            // dialog
            selectedCron: "",
            showCronDialog: false,
            cronCount: 10,
            cronExeList: []
        }
    },
    watch: {
        $route(to, from) {
            let params = getHrefParams();
            let newId = params.id;
            if (newId == null) {
                return;
            }
            if (this.oldId != newId) {
                this.tSysTaskPlanSearchForm.likeStr = newId;
                this.searchEvent();
            }
        }
    },
    methods: {
        // 左侧树：配置
        getTreeOption() {
            let treeOptions = {
                title: "计划分组",
                toolbarBtn: ["add", "edit", "del", "sort"],
                dialogTitle: "调度计划分组",
                showCheckbox: true,
                sortByDrag: true,
                onCheck: (data, node, comp, halfCheckedKeys, checkedKeys) => {
                    this.selectedId = data.fdId;
                    this.treeSelectedValues = halfCheckedKeys.concat(checkedKeys).join(",");
                    if (this.treeSelectedValues == null || this.treeSelectedValues == "") {
                        return;
                    }
                    this.$refs.tSysTaskPlanTableRef.refresh();
                },
                loadOptions: {
                    url: "/apt/sys/TSysTaskPlanType/getTSysTaskPlanTypeList",
                    treeKey: {
                        idKey: "fdId",
                        parentKey: "fdParentId",
                        childrenKey: "children",
                        label: "fdName"
                    },
                    success: (response) => {
                        this.typeList = response.data;
                    },
                },
                editOptions: {
                    url: "/apt/sys/TSysTaskPlanType/getTSysTaskPlanTypeByFdId",
                    data: (node) => {
                        return {
                            fdId: node.fdId
                        }
                    },
                    success: (response) => {
                        this.tSysTaskPlanTypeForm = response.data;
                    },
                    error() {
                    },
                },
                insertUrl: "/apt/sys/TSysTaskPlanType/insertTSysTaskPlanType",
                insertData: () => {
                    return this.tSysTaskPlanTypeForm
                },
                updateUrl: "/apt/sys/TSysTaskPlanType/updateTSysTaskPlanType",
                updateData: () => {
                    return this.tSysTaskPlanTypeForm
                },
                deleteUrl: "/apt/sys/TSysTaskPlanType/deleteTSysTaskPlanTypeByFdId",
                deleteData: (node) => {
                    return {
                        fdId: node.fdId
                    }
                },
                sortByTree: true,
                updateSortUrl: '/apt/sys/TSysTaskPlanType/updateTSysTaskPlanTypeSort',
                updateSortListUrl: '/apt/sys/TSysTaskPlanType/updateTSysTaskPlanTypeSortList',
                resetForm: () => {
                    this.tSysTaskPlanTypeForm = {
                        fdParentId: '',
                        fdName: '',
                        fdSort: '',
                    };
                },
                afterOpenAddDialog: (node) => {
                    this.tSysTaskPlanTypeForm.fdParentId = node.fdId;
                },
            };

            return treeOptions;
        },
        // 右侧：查询事件
        searchEvent() {
            // 表单rules认证
            this.$refs.tSysTaskPlanSearchForm.validate((valid) => {
                if (!valid) {
                    this.$message.error('搜索条件格式不正确！');
                    return false;
                }
                this.$refs.tSysTaskPlanTableRef.refresh();
            });
        },
        addTask() {
            let selects = this.$refs.tSysTaskPlanTableRef.getSelection();
            if (selects == null || selects.length < 1) {
                this.$message.error("请选择需要操作的行")
                return;
            }
            let plans = [];
            for (let i = 0; i < selects.length; i++) {
                plans.push({
                    fdId: selects[i].fdId,
                    fdName: selects[i].fdName,
                    fdCron: selects[i].fdCron,
                })
            }

            this.$request({
                url: '/apt/sys/TSysTaskPlan/addTask',
                method: 'post',
                data: {
                    plans: JSON.stringify(plans)
                }
            }).then(response => {
                this.$message.success("加载成功");
                this.$refs.tSysTaskPlanTableRef.refresh();
            })
        },
        showCronTest() {
            let selects = this.$refs.tSysTaskPlanTableRef.getSelection();
            if (selects == null || selects.length < 1) {
                this.$message.error("请选择需要操作的行")
                return;
            }
            if (selects.length != 1) {
                this.$message.error("只能选择单行操作！")
                return;
            }
            this.selectedCron = selects[0].fdCron;
            this.showCronDialog = true;
            this.cronExeList = [];
        },
        cronTest() {
            // cron模拟执行时间
            this.$request({
                url: '/apt/sys/TSysTaskPlan/cronTest',
                method: 'post',
                data: {
                    cron: this.selectedCron,
                    count: this.cronCount,
                }
            }).then(response => {
                this.cronExeList = response.data;
            })
        },
        refreshCount() {
            // 刷新每天执行次数
            this.$request({
                url: '/apt/sys/TSysTaskPlan/refreshCount',
                method: 'post',
                data: {}
            }).then(response => {
                this.$message.success("调度计划的[次/天]和[用时]，刷新成功！");
            })
        },
        checkTask() {
            let selects = this.$refs.tSysTaskPlanTableRef.getSelection();
            if (selects == null || selects.length < 1) {
                this.$message.error("请选择需要操作的行")
                return;
            }
            if (selects.length != 1) {
                this.$message.error("只能选择单行操作！")
                return;
            }
            this.$request({
                url: '/apt/sys/TSysTaskPlan/checkTask',
                method: 'post',
                data: {
                    planId: selects[0].fdId,
                }
            }).then(response => {
                this.$message.success(response.data);
            })
        },
        removeTask() {
            let ids = this.$refs.tSysTaskPlanTableRef.getSelectionKeys().join();
            if (ids == null || ids == "") {
                this.$message.error("请选择需要操作的行")
                return;
            }
            this.$request({
                url: '/apt/sys/TSysTaskPlan/removeTask',
                method: 'post',
                data: {
                    planIds: ids
                }
            }).then(response => {
                this.$message.success("移除成功");
                this.$refs.tSysTaskPlanTableRef.refresh();
            })
        },
        doTask() {
            let selects = this.$refs.tSysTaskPlanTableRef.getSelection();
            if (selects == null || selects.length < 1) {
                this.$message.error("请选择需要操作的行")
                return;
            }
            if (selects.length != 1) {
                this.$message.error("只能选择单行操作！")
                return;
            }
            this.$message.warning("调度计划开始执行...");
            this.$request({
                url: '/apt/sys/TSysTaskPlan/doTask',
                method: 'post',
                data: {
                    planId: selects[0].fdId,
                    comment: "手动【调度计划】"
                }
            }).then(response => {
                this.$message.success(response.data);
            })

        },
        copyTask() {
            let selectedRows = this.$refs.tSysTaskPlanTableRef.getSelection();
            if (selectedRows.length < 1) {
                this.$message.error("请选择需要编辑的行！");
                return;
            }
            if (selectedRows.length > 1) {
                this.$message.error("只能选择单行数据进行编辑！");
                return;
            }
            this.$request({
                url: '/apt/sys/TSysTaskPlan/copyTask',
                method: 'post',
                data: {
                    fdId: selectedRows[0].fdId
                }
            }).then(response => {
                this.$message.success(`复制成功！`)
                this.$refs.tSysTaskPlanTableRef.refresh();
            })
        },
        getCronHelp() {

            let list = [
                {cron: "0/2 * * * * ?", name: "每2秒"},
                {cron: "0 0/2 * * * ?", name: "每2分钟"},
                {cron: "0 0 10 * * ?", name: "每天10点"},
                {cron: "0 15 10 * * ?", name: " 每天10点15分"},
                {cron: "0 0 10,14,16 * * ?", name: "每天10点、14点、16点"},
                {cron: "0 0/30 9-17 * * ?", name: "每天9点到17点间，每半小时"},
                {cron: "0 * 14 * * ?", name: "  每天14点到14:59期间的每1分钟"},
                {cron: "0 0/5 14 * * ?", name: " 每天14点到14:55期间的每5分钟"},
                {cron: "0 0/5 14,18 * * ?", name: "  每天14点到14:55期间和18点到18:55期间的每5分钟"},
                {cron: "0 0-5 14 * * ?", name: " 每天14点到14:05期间的每1分钟"},
                {cron: "0 0 12 ? * WED", name: " 每周三的12点"},
                {cron: "0 15 10 ? * MON-FRI", name: "每周一到周五的10:15"},
                {cron: "0 0 2 1 * ?", name: "每月1日的2点"},
                {cron: "0 15 10 15 * ?", name: " 每月15日上午10:15"},
                {cron: "0 15 10 L * ?", name: " 每月最后一日的上午10:15"},
                {cron: "0 15 10 ? * 6L", name: " 每月的最后一个星期五上午10:15"},
                {cron: "0 15 10 ? * 6#3", name: "每月的第三个星期五上午10:15"},
                {cron: "0 10,44 14 ? 3 WED", name: " 每年三月的星期三的14:10和14:44"},
                {cron: "0 15 10 ? 6L 2002-2006", name: "2002-2006年的每个月的最后一个星期五上午10:15"},
                {cron: "0 15 10 * * ? 2005", name: " 2005年的每天上午10:15"},
                {cron: "0 15 10 ? * 6L 2002-2005", name: "2002年至2005年的每月的最后一个星期五上午10:15"},
            ];
            let str = "<div style='font-weight: bold'>常用cron表达式：</div>";
            for (let i = 0; i < list.length; i++) {
                str += `<div ><span style="color: #1890FF;margin-right: 20px;">${list[i].cron}</span><span>${list[i].name}</span></div>`;
            }
            return str;
        }
    }
}
</script>

<style scoped>

.type-tree /deep/ .el-tree-node__content {
    height: 22px;
}
.type-tree /deep/ .el-tree-node__content > .el-tree-node__expand-icon {
    padding: 2px;
}
.type-tree /deep/ .el-tree-node__content > label.el-checkbox {
    margin-right: 2px;
}
</style>
