Quartz Cron 表达式参考表

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Cron 表达式参考</title>
    <link rel="stylesheet" href="/lib/layui-v2.10.2/css/layui.css">
    <style>
        body {
            background: #f2f2f2;
            padding: 20px;
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
        }
        
        .header {
            background: white;
            padding: 5px 0px;
            border-radius: 10px;
            margin-bottom: 20px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.05);
            text-align: center;
        }
        
        .header h1 {
            color: #333;
            margin-bottom: 10px;
            font-size: 20px;
            font-weight: 600;
        }
        
        .header .desc {
            color: #666;
            font-size: 14px;
            line-height: 1.6;
        }
        
        .main-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
            gap: 18px;
            margin-top: 20px;
        }
        
        .expression-card {
            background: white;
            border-radius: 10px;
            padding: 10px;
            box-shadow: 0 3px 10px rgba(0,0,0,0.06);
            border: 1px solid #f0f0f0;
            transition: all 0.3s ease;
            position: relative;
        }
        
        .expression-card:hover {
            box-shadow: 0 5px 15px rgba(0,0,0,0.08);
            transform: translateY(-2px);
            border-color: #e6f7ff;
        }
        
        .cron-code {
            font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
            font-size: 16px;
            font-weight: 600;
            color: #1890ff;
            background: #f0f9ff;
            padding: 10px 10px;
            border-radius: 6px;
            /* border-left: 3px solid #1890ff; */
            margin-bottom: 12px;
            word-break: break-all;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .copy-btn {
            background: #1890ff;
            color: white;
            border: none;
            border-radius: 4px;
            padding: 5px 12px;
            font-size: 12px;
            cursor: pointer;
            transition: all 0.2s;
        }
        
        .copy-btn:hover {
            background: #40a9ff;
            transform: scale(1.05);
        }
        
        .copy-btn.copied {
            background: #52c41a;
        }
        
        .expression-info {
            /* margin-top: 8px; */
        }
        
        .expression-name {
            font-weight: 600;
            color: #333;
            font-size: 15px;
            margin-bottom: 5px;
        }
        
        .expression-desc {
            color: #666;
            font-size: 13px;
            line-height: 1.5;
        }
        
        .time-tag {
            position: absolute;
            top: 15px;
            right: 15px;
            background: #f6ffed;
            color: #52c41a;
            font-size: 11px;
            padding: 2px 8px;
            border-radius: 10px;
            border: 1px solid #b7eb8f;
        }
        
        .minute-tag {
            background: #f0f9ff;
            color: #1890ff;
            border-color: #91d5ff;
        }
        
        .stats-bar {
            background: white;
            padding: 15px 20px;
            border-radius: 10px;
            margin-top: 20px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: 0 2px 8px rgba(0,0,0,0.04);
        }
        
        .total-count {
            color: #666;
            font-size: 14px;
        }
        
        .total-count span {
            color: #1890ff;
            font-weight: bold;
            font-size: 18px;
        }
        
        .action-buttons {
            display: flex;
            gap: 10px;
        }
        
        .json-modal pre {
            background: #f8f9fa;
            padding: 20px;
            border-radius: 6px;
            max-height: 400px;
            overflow: auto;
            font-family: 'Consolas', 'Monaco', monospace;
            font-size: 13px;
        }
        
        .search-box {
            margin: 15px 0;
        }
        
        .search-box input {
            width: 80%;
            padding: 12px 15px;
            border: 1px solid #ddd;
            border-radius: 6px;
            font-size: 14px;
            transition: all 0.3s;
        }
        
        .search-box input:focus {
            outline: none;
            border-color: #1890ff;
            box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
        }

        
        /* 动画效果 */
        @keyframes copySuccess {
            0% { transform: scale(1); }
            50% { transform: scale(1.1); }
            100% { transform: scale(1); }
        }
        
        .copy-animation {
            animation: copySuccess 0.3s ease;
        }
        
        /* 加载动画 */
        .loading {
            text-align: center;
            padding: 40px;
            color: #999;
        }
        
        .empty-result {
            text-align: center;
            padding: 40px;
            color: #999;
            grid-column: 1 / -1;
        }
    </style>
</head>
<body>

<div class="container">
    <!-- 页面头部 -->
    <div class="header">
        <h1>📅 Quartz Cron 表达式参考表</h1>
        <!-- <div class="desc">
            包含每分钟执行和每天1-24点整点执行的表达式,点击复制按钮可直接使用
        </div> -->
        
        <!-- 搜索框 -->
        <div class="search-box">
            <input type="text" id="searchInput" placeholder="搜索表达式或说明... (支持模糊搜索)" 
                   onkeyup="searchExpressions()">
        </div>
    </div>
    
    <!-- 表达式网格 -->
    <div class="main-grid" id="expressionGrid">
        <!-- 这里通过JS动态生成 -->
        <div class="loading">加载中...</div>
    </div>
    
    <!-- 统计和操作栏 -->
    <div class="stats-bar">
        <div class="total-count">
            共 <span id="displayCount">0</span> 个表达式
        </div>
        <div class="action-buttons">
            <button class="layui-btn layui-btn-primary layui-btn-sm" onclick="copyAllExpressions()">
                <i class="layui-icon layui-icon-copy"></i> 复制全部
            </button>
            <button class="layui-btn layui-btn-sm" onclick="showJsonModal()">
                <i class="layui-icon layui-icon-template-1"></i> JSON数据
            </button>
            <button class="layui-btn layui-btn-sm layui-btn-normal" onclick="exportToFile()">
                <i class="layui-icon layui-icon-download-circle"></i> 导出
            </button>
        </div>
    </div>
</div>

<!-- 引入 LayUI -->
<script src="/lib/layui-v2.10.2/layui.js"></script>
<script>
// JSON 数据
const cronData = {
  "expressions": [
    {
      "id": "minute",
      "name": "每分钟执行",
      "cron": "0 */1 * * * ?",
      "description": "每分钟的第0秒执行一次",
      "type": "minute"
    },
    {
      "id": "hourly_1",
      "name": "凌晨1点",
      "cron": "0 0 1 * * ?",
      "description": "每天凌晨1点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_2",
      "name": "凌晨2点",
      "cron": "0 0 2 * * ?",
      "description": "每天凌晨2点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_3",
      "name": "凌晨3点",
      "cron": "0 0 3 * * ?",
      "description": "每天凌晨3点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_4",
      "name": "凌晨4点",
      "cron": "0 0 4 * * ?",
      "description": "每天凌晨4点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_5",
      "name": "凌晨5点",
      "cron": "0 0 5 * * ?",
      "description": "每天凌晨5点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_6",
      "name": "早上6点",
      "cron": "0 0 6 * * ?",
      "description": "每天早上6点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_7",
      "name": "早上7点",
      "cron": "0 0 7 * * ?",
      "description": "每天早上7点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_8",
      "name": "早上8点",
      "cron": "0 0 8 * * ?",
      "description": "每天早上8点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_9",
      "name": "上午9点",
      "cron": "0 0 9 * * ?",
      "description": "每天上午9点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_10",
      "name": "上午10点",
      "cron": "0 0 10 * * ?",
      "description": "每天上午10点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_11",
      "name": "上午11点",
      "cron": "0 0 11 * * ?",
      "description": "每天上午11点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_12",
      "name": "中午12点",
      "cron": "0 0 12 * * ?",
      "description": "每天中午12点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_13",
      "name": "下午1点",
      "cron": "0 0 13 * * ?",
      "description": "每天下午1点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_14",
      "name": "下午2点",
      "cron": "0 0 14 * * ?",
      "description": "每天下午2点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_15",
      "name": "下午3点",
      "cron": "0 0 15 * * ?",
      "description": "每天下午3点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_16",
      "name": "下午4点",
      "cron": "0 0 16 * * ?",
      "description": "每天下午4点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_17",
      "name": "下午5点",
      "cron": "0 0 17 * * ?",
      "description": "每天下午5点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_18",
      "name": "晚上6点",
      "cron": "0 0 18 * * ?",
      "description": "每天晚上6点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_19",
      "name": "晚上7点",
      "cron": "0 0 19 * * ?",
      "description": "每天晚上7点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_20",
      "name": "晚上8点",
      "cron": "0 0 20 * * ?",
      "description": "每天晚上8点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_21",
      "name": "晚上9点",
      "cron": "0 0 21 * * ?",
      "description": "每天晚上9点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_22",
      "name": "晚上10点",
      "cron": "0 0 22 * * ?",
      "description": "每天晚上10点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_23",
      "name": "晚上11点",
      "cron": "0 0 23 * * ?",
      "description": "每天晚上11点0分0秒执行",
      "type": "hourly"
    },
    {
      "id": "hourly_24",
      "name": "晚上12点",
      "cron": "0 0 24 * * ?",
      "description": "每天晚上12点0分0秒执行",
      "type": "hourly"
    }
  ]
};

// 全局变量
let currentExpressions = [...cronData.expressions];

// 初始化页面
layui.use(['layer', 'util'], function() {
    var layer = layui.layer;
    var util = layui.util;
    
    // 渲染表达式列表
    renderExpressionCards();
    
    // 初始化固定条
    util.fixbar({
        // bar1: '',
        // bar2: '',
        bgcolor: '#1890ff',
        click: function(type){
            // if(type === 'bar1'){
            //     copyAllExpressions();
            // } else if(type === 'bar2'){
            //     window.scrollTo(0, 0);
            // }
        }
    });
    
    // 设置搜索框焦点
    setTimeout(() => {
        document.getElementById('searchInput').focus();
    }, 300);
});

// 渲染表达式卡片
function renderExpressionCards() {
    const grid = document.getElementById('expressionGrid');
    
    if (currentExpressions.length === 0) {
        grid.innerHTML = '<div class="empty-result">未找到匹配的表达式</div>';
        updateCount();
        return;
    }
    
    let html = '';
    
    currentExpressions.forEach(expr => {
        const timeTag = expr.type === 'minute' ? 
            '<span class="time-tag minute-tag">每分钟</span>' : 
            `<span class="time-tag">${expr.name}</span>`;
        
        // html += `
        //     <div class="expression-card">
        //         ${timeTag}
        //         <div class="cron-code">
        //             <span>${expr.cron}</span>
        //             <button class="copy-btn" onclick="copyExpression('${expr.cron}', this)">
        //                 复制
        //             </button>
        //         </div>
        //         <div class="expression-info">
        //             <div class="expression-name">${expr.name}</div>
        //             <div class="expression-desc">${expr.description}</div>
        //         </div>
        //     </div>
        // `;
        html += `
            <div class="expression-card">
                <div class="cron-code">
                    <span>${expr.cron}</span>
                    <button class="copy-btn" onclick="copyExpression('${expr.cron}', this)">
                        复制
                    </button>
                </div>
                <div class="expression-info">
                    <div class="expression-name">${expr.name}</div>
                </div>
            </div>
        `;
    });
    
    grid.innerHTML = html;
    updateCount();
}

// 更新显示计数
function updateCount() {
    document.getElementById('displayCount').textContent = currentExpressions.length;
}

// 搜索表达式
function searchExpressions() {
    const searchTerm = document.getElementById('searchInput').value.toLowerCase().trim();
    
    if (!searchTerm) {
        currentExpressions = [...cronData.expressions];
    } else {
        currentExpressions = cronData.expressions.filter(expr => {
            return expr.cron.toLowerCase().includes(searchTerm) ||
                   expr.name.toLowerCase().includes(searchTerm) ||
                   expr.description.toLowerCase().includes(searchTerm);
        });
    }
    
    renderExpressionCards();
}

// 复制单个表达式
function copyExpression(cron, button) {
    // 创建临时输入框
    const textarea = document.createElement('textarea');
    textarea.value = cron;
    document.body.appendChild(textarea);
    textarea.select();
    
    try {
        const successful = document.execCommand('copy');
        if (successful) {
            // 添加动画效果
            button.classList.add('copy-animation');
            button.classList.add('copied');
            button.textContent = '已复制';
            
            setTimeout(() => {
                button.classList.remove('copy-animation');
                button.classList.remove('copied');
                button.textContent = '复制';
            }, 1500);
            
            // 显示小提示
            layui.use('layer', function() {
                layui.layer.msg(`已复制: ${cron}`, {
                    time: 1000,
                    offset: 't'
                });
            });
        }
    } catch (err) {
        console.error('复制失败:', err);
        layui.use('layer', function() {
            layui.layer.msg('复制失败,请手动复制', { icon: 2 });
        });
    }
    
    document.body.removeChild(textarea);
}

// 复制所有表达式
function copyAllExpressions() {
    let allText = '';
    
    currentExpressions.forEach(expr => {
        allText += `${expr.cron}\t${expr.name}\t${expr.description}\n`;
    });
    
    // 创建临时输入框
    const textarea = document.createElement('textarea');
    textarea.value = allText;
    document.body.appendChild(textarea);
    textarea.select();
    
    try {
        document.execCommand('copy');
        
        layui.use('layer', function() {
            layui.layer.msg(`已复制 ${currentExpressions.length} 个表达式到剪贴板`, { 
                icon: 1,
                time: 2000 
            });
        });
    } catch (err) {
        console.error('复制失败:', err);
        layui.use('layer', function() {
            layui.layer.msg('复制失败,请手动复制', { icon: 2 });
        });
    }
    
    document.body.removeChild(textarea);
}

// 显示JSON数据模态框
function showJsonModal() {
    const jsonStr = JSON.stringify(cronData, null, 2);
    
    layui.use('layer', function() {
        var layer = layui.layer;
        layer.open({
            type: 1,
            title: 'JSON 数据源',
            area: ['90%', '80%'],
            content: '<div class="json-modal"><pre>' + jsonStr + '</pre></div>',
            btn: ['复制JSON', '关闭'],
            yes: function(index, layero) {
                const textarea = document.createElement('textarea');
                textarea.value = jsonStr;
                document.body.appendChild(textarea);
                textarea.select();
                document.execCommand('copy');
                document.body.removeChild(textarea);
                
                layer.msg('JSON已复制到剪贴板', { icon: 1 });
            }
        });
    });
}

// 导出为文件
function exportToFile() {
    let content = 'Quartz Cron 表达式参考\n';
    content += '生成时间: ' + new Date().toLocaleString() + '\n';
    content += '========================================\n\n';
    
    currentExpressions.forEach(expr => {
        content += `表达式: ${expr.cron}\n`;
        content += `名称: ${expr.name}\n`;
        content += `说明: ${expr.description}\n`;
        content += `类型: ${expr.type === 'minute' ? '每分钟执行' : '整点执行'}\n`;
        content += '----------------------------------------\n';
    });
    
    const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    
    const link = document.createElement('a');
    link.href = url;
    link.download = `cron-expressions-${new Date().toISOString().slice(0,10)}.txt`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    
    layui.use('layer', function() {
        layui.layer.msg('文件导出成功', { icon: 1 });
    });
}
</script>
</body>
</html>
相关推荐
匠心网络科技2 小时前
前端学习手册-JavaScript条件判断语句全解析(十八)
开发语言·前端·javascript·学习·ecmascript
我只会写Bug啊2 小时前
一文读懂:cookie、localStorage与sessionStorage的区别与应用
前端
杨超越luckly2 小时前
HTML应用指南:利用GET请求获取全国新东方门店位置信息
前端·数据库·arcgis·html·门店数据
颜颜yan_2 小时前
DevUI零基础入门教程:5分钟快速上手Vue DevUI组件库
前端·javascript·vue.js
武藤一雄2 小时前
[WPF] 万字拆解依赖属性与附加属性
前端·microsoft·c#·.net·wpf
羊吖2 小时前
Vue文件预览组件实战:高性能懒加载
前端·javascript·vue.js
代码or搬砖2 小时前
如何创建一个vue项目(详细步骤)
前端·javascript·vue.js
赛贝维权申诉2 小时前
亚马逊爆款美国外观专利落地,家居/儿童/宠物等品类亚马逊卖家谨防侵权投诉!
前端·javascript·宠物
Howe~zZ2 小时前
mybatis 报错解决方案ORA-01795: maximum number of expressions in a list is 1000
java·服务器·前端