SOURCE

console 命令行工具 X clear

                    
>
console
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>微信公众号 AccessToken 管理系统</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 20px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
            overflow: hidden;
        }

        .header {
            background: linear-gradient(135deg, #2c3e50, #34495e);
            color: white;
            padding: 30px;
            text-align: center;
        }

        .header h1 {
            font-size: 2.2em;
            margin-bottom: 10px;
        }

        .header p {
            opacity: 0.8;
            font-size: 1.1em;
        }

        .main-content {
            padding: 30px;
        }

        .card {
            background: white;
            border-radius: 15px;
            padding: 25px;
            margin-bottom: 20px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.08);
            border: 1px solid #f0f0f0;
            transition: transform 0.3s ease, box-shadow 0.3s ease;
        }

        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 15px 40px rgba(0,0,0,0.15);
        }

        .card h3 {
            color: #2c3e50;
            margin-bottom: 20px;
            font-size: 1.4em;
            border-bottom: 2px solid #3498db;
            padding-bottom: 10px;
        }

        .form-group {
            margin-bottom: 20px;
        }

        .form-group label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: #34495e;
        }

        .form-group input, .form-group select {
            width: 100%;
            padding: 12px 15px;
            border: 2px solid #e0e0e0;
            border-radius: 10px;
            font-size: 16px;
            transition: border-color 0.3s ease;
        }

        .form-group input:focus, .form-group select:focus {
            outline: none;
            border-color: #3498db;
        }

        .btn {
            background: linear-gradient(135deg, #3498db, #2980b9);
            color: white;
            border: none;
            padding: 12px 25px;
            border-radius: 10px;
            cursor: pointer;
            font-size: 16px;
            font-weight: 600;
            transition: all 0.3s ease;
            margin-right: 10px;
            margin-bottom: 10px;
        }

        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(52, 152, 219, 0.4);
        }

        .btn-success {
            background: linear-gradient(135deg, #27ae60, #229954);
        }

        .btn-success:hover {
            box-shadow: 0 5px 15px rgba(39, 174, 96, 0.4);
        }

        .btn-danger {
            background: linear-gradient(135deg, #e74c3c, #c0392b);
        }

        .btn-danger:hover {
            box-shadow: 0 5px 15px rgba(231, 76, 60, 0.4);
        }

        .status {
            padding: 15px;
            border-radius: 10px;
            margin: 15px 0;
            font-weight: 600;
        }

        .status-active {
            background: linear-gradient(135deg, #d5f4e6, #c3f0d9);
            color: #27ae60;
            border: 1px solid #27ae60;
        }

        .status-inactive {
            background: linear-gradient(135deg, #ffeaa7, #fdcb6e);
            color: #e17055;
            border: 1px solid #e17055;
        }

        .token-display {
            background: #f8f9fa;
            border: 2px solid #e9ecef;
            border-radius: 10px;
            padding: 15px;
            font-family: 'Courier New', monospace;
            word-break: break-all;
            max-height: 200px;
            overflow-y: auto;
        }

        .logs {
            background: #2c3e50;
            color: #ecf0f1;
            border-radius: 10px;
            padding: 20px;
            max-height: 300px;
            overflow-y: auto;
            font-family: 'Courier New', monospace;
            font-size: 14px;
        }

        .log-entry {
            margin-bottom: 5px;
            padding: 5px;
            border-radius: 5px;
        }

        .log-success {
            background: rgba(39, 174, 96, 0.2);
        }

        .log-error {
            background: rgba(231, 76, 60, 0.2);
        }

        .log-info {
            background: rgba(52, 152, 219, 0.2);
        }

        .grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
        }

        @media (max-width: 768px) {
            .grid {
                grid-template-columns: 1fr;
            }
            
            .header h1 {
                font-size: 1.8em;
            }
            
            .main-content {
                padding: 20px;
            }
        }

        .pulse {
            animation: pulse 2s infinite;
        }

        @keyframes pulse {
            0% { opacity: 1; }
            50% { opacity: 0.7; }
            100% { opacity: 1; }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>�� 微信公众号 AccessToken 管理系统</h1>
            <p>智能获取、管理和推送微信公众号访问令牌</p>
        </div>

        <div class="main-content">
            <!-- 配置面板 -->
            <div class="card">
                <h3>�� 基础配置</h3>
                <div class="grid">
                    <div>
                        <div class="form-group">
                            <label for="appid">AppID *</label>
                            <input type="text" id="appid" placeholder="请输入微信公众号AppID">
                        </div>
                        <div class="form-group">
                            <label for="appsecret">AppSecret *</label>
                            <input type="password" id="appsecret" placeholder="请输入微信公众号AppSecret">
                        </div>
                    </div>
                    <div>
                        <div class="form-group">
                            <label for="interval">获取间隔(分钟)*</label>
                            <select id="interval">
                                <option value="30">30分钟</option>
                                <option value="60" selected>1小时</option>
                                <option value="90">1.5小时</option>
                                <option value="120">2小时</option>
                            </select>
                        </div>
                        <div class="form-group">
                            <label for="webhook">Webhook URL *</label>
                            <input type="url" id="webhook" placeholder="https://your-webhook-url.com/receive">
                        </div>
                    </div>
                </div>
                <button class="btn" onclick="saveConfig()">�� 保存配置</button>
                <button class="btn btn-success" onclick="testConfig()">�� 测试配置</button>
            </div>

            <!-- 控制面板 -->
            <div class="card">
                <h3>⚡ 服务控制</h3>
                <div id="serviceStatus" class="status status-inactive">
                    �� 服务未启动
                </div>
                <button class="btn btn-success" onclick="startService()">▶️ 启动服务</button>
                <button class="btn btn-danger" onclick="stopService()">⏹️ 停止服务</button>
                <button class="btn" onclick="manualRefresh()">�� 手动获取Token</button>
            </div>

            <!-- Token显示 -->
            <div class="card">
                <h3>�� 当前AccessToken</h3>
                <div class="form-group">
                    <label>Token值:</label>
                    <div id="tokenDisplay" class="token-display">暂无Token</div>
                </div>
                <div class="form-group">
                    <label>过期时间:</label>
                    <div id="expireTime" class="token-display">--</div>
                </div>
                <div class="form-group">
                    <label>上次更新:</label>
                    <div id="lastUpdate" class="token-display">--</div>
                </div>
            </div>

            <!-- 运行日志 -->
            <div class="card">
                <h3>�� 运行日志</h3>
                <div id="logs" class="logs">
                    <div class="log-entry log-info">[系统] 微信AccessToken管理系统已启动</div>
                </div>
                <button class="btn" onclick="clearLogs()">��️ 清空日志</button>
            </div>
        </div>
    </div>

    <script>
        // 全局变量
        let serviceInterval = null;
        let currentConfig = {};
        let isServiceRunning = false;

        // 初始化
        window.onload = function() {
            loadConfig();
            addLog('系统初始化完成', 'info');
        };

        // 保存配置
        function saveConfig() {
            const config = {
                appid: document.getElementById('appid').value,
                appsecret: document.getElementById('appsecret').value,
                interval: parseInt(document.getElementById('interval').value),
                webhook: document.getElementById('webhook').value
            };

            if (!config.appid || !config.appsecret || !config.webhook) {
                alert('请填写完整的配置信息!');
                return;
            }

            if (!isValidUrl(config.webhook)) {
                alert('请输入有效的Webhook URL!');
                return;
            }

            currentConfig = config;
            addLog('配置已保存', 'success');
            alert('配置保存成功!');
        }

        // 加载配置
        function loadConfig() {
            // 从内存中加载配置(在实际应用中可以从localStorage或服务器加载)
            if (currentConfig.appid) {
                document.getElementById('appid').value = currentConfig.appid;
                document.getElementById('appsecret').value = currentConfig.appsecret;
                document.getElementById('interval').value = currentConfig.interval;
                document.getElementById('webhook').value = currentConfig.webhook;
            }
        }

        // 测试配置
        async function testConfig() {
            if (!currentConfig.appid || !currentConfig.appsecret) {
                alert('请先保存配置!');
                return;
            }

            addLog('正在测试配置...', 'info');
            
            try {
                // 模拟测试微信API连接
                await simulateWeChatTest();
                addLog('微信API连接测试成功', 'success');
                
                // 测试Webhook连接
                await testWebhook();
                addLog('Webhook连接测试成功', 'success');
                
                alert('配置测试通过!');
            } catch (error) {
                addLog(`配置测试失败: ${error.message}`, 'error');
                alert('配置测试失败,请检查配置信息!');
            }
        }

        // 启动服务
        function startService() {
            if (!currentConfig.appid || !currentConfig.appsecret) {
                alert('请先保存配置!');
                return;
            }

            if (isServiceRunning) {
                alert('服务已在运行中!');
                return;
            }

            isServiceRunning = true;
            updateServiceStatus(true);
            
            // 立即获取一次Token
            getAccessToken();
            
            // 设置定时任务
            const intervalMs = currentConfig.interval * 60 * 1000;
            serviceInterval = setInterval(getAccessToken, intervalMs);
            
            addLog(`服务已启动,每${currentConfig.interval}分钟获取一次Token`, 'success');
        }

        // 停止服务
        function stopService() {
            if (!isServiceRunning) {
                alert('服务未在运行!');
                return;
            }

            isServiceRunning = false;
            updateServiceStatus(false);
            
            if (serviceInterval) {
                clearInterval(serviceInterval);
                serviceInterval = null;
            }
            
            addLog('服务已停止', 'info');
        }

        // 手动刷新Token
        function manualRefresh() {
            if (!currentConfig.appid || !currentConfig.appsecret) {
                alert('请先保存配置!');
                return;
            }

            addLog('手动获取AccessToken...', 'info');
            getAccessToken();
        }

        // 获取AccessToken
        async function getAccessToken() {
            try {
                addLog('正在获取AccessToken...', 'info');
                
                // 模拟获取微信AccessToken
                const tokenData = await simulateGetAccessToken();
                
                // 更新UI显示
                updateTokenDisplay(tokenData);
                
                // 推送到Webhook
                await pushToWebhook(tokenData);
                
                addLog('AccessToken获取成功并已推送', 'success');
                
            } catch (error) {
                addLog(`获取AccessToken失败: ${error.message}`, 'error');
            }
        }

        // 模拟获取微信AccessToken
        function simulateGetAccessToken() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    // 模拟微信API响应
                    const mockToken = generateMockToken();
                    const expireTime = new Date(Date.now() + 7200 * 1000); // 2小时后过期
                    
                    resolve({
                        access_token: mockToken,
                        expires_in: 7200,
                        expire_time: expireTime,
                        timestamp: new Date()
                    });
                }, 1000);
            });
        }

        // 生成模拟Token
        function generateMockToken() {
            const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
            let result = '';
            for (let i = 0; i < 120; i++) {
                result += chars.charAt(Math.floor(Math.random() * chars.length));
            }
            return result;
        }

        // 更新Token显示
        function updateTokenDisplay(tokenData) {
            document.getElementById('tokenDisplay').textContent = tokenData.access_token;
            document.getElementById('expireTime').textContent = tokenData.expire_time.toLocaleString();
            document.getElementById('lastUpdate').textContent = tokenData.timestamp.toLocaleString();
        }

        // 推送到Webhook
        async function pushToWebhook(tokenData) {
            if (!currentConfig.webhook) return;

            try {
                // 模拟Webhook推送
                await simulateWebhookPush(tokenData);
                addLog(`Token已推送到: ${currentConfig.webhook}`, 'success');
            } catch (error) {
                addLog(`Webhook推送失败: ${error.message}`, 'error');
                throw error;
            }
        }

        // 模拟Webhook推送
        function simulateWebhookPush(tokenData) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    // 模拟网络请求
                    const success = Math.random() > 0.1; // 90%成功率
                    if (success) {
                        resolve();
                    } else {
                        reject(new Error('网络连接失败'));
                    }
                }, 500);
            });
        }

        // 测试Webhook
        function testWebhook() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    const success = Math.random() > 0.2; // 80%成功率
                    if (success) {
                        resolve();
                    } else {
                        reject(new Error('Webhook无法访问'));
                    }
                }, 800);
            });
        }

        // 模拟微信API测试
        function simulateWeChatTest() {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    const success = Math.random() > 0.15; // 85%成功率
                    if (success) {
                        resolve();
                    } else {
                        reject(new Error('微信API连接失败'));
                    }
                }, 1200);
            });
        }

        // 更新服务状态
        function updateServiceStatus(running) {
            const statusElement = document.getElementById('serviceStatus');
            if (running) {
                statusElement.className = 'status status-active pulse';
                statusElement.innerHTML = '�� 服务运行中';
            } else {
                statusElement.className = 'status status-inactive';
                statusElement.innerHTML = '�� 服务未启动';
            }
        }

        // 添加日志
        function addLog(message, type = 'info') {
            const logsContainer = document.getElementById('logs');
            const timestamp = new Date().toLocaleTimeString();
            const logEntry = document.createElement('div');
            logEntry.className = `log-entry log-${type}`;
            logEntry.innerHTML = `[${timestamp}] ${message}`;
            
            logsContainer.appendChild(logEntry);
            logsContainer.scrollTop = logsContainer.scrollHeight;
            
            // 限制日志条数
            const logs = logsContainer.querySelectorAll('.log-entry');
            if (logs.length > 100) {
                logs[0].remove();
            }
        }

        // 清空日志
        function clearLogs() {
            const logsContainer = document.getElementById('logs');
            logsContainer.innerHTML = '<div class="log-entry log-info">[系统] 日志已清空</div>';
        }

        // 验证URL格式
        function isValidUrl(string) {
            try {
                new URL(string);
                return true;
            } catch (_) {
                return false;
            }
        }
    </script>
</body>
</html>