|
这个是我自己做的一个用来监测网站是否可以正常访问,单文件双击 网站监测工具.html 运行。
可以快速知道自己网站运行状态。
1. 网址管理功能
添加网址:用户可以在输入框中输入要监测的网页地址,点击 “添加网址” 按钮,工具会对输入的网址进行格式验证。验证通过后,网址会被添加到左侧面板的列表中,并且列表项后有 “删除” 按钮。
删除网址:在左侧面板的网址列表中,每个网址后面都有一个 “删除” 按钮,点击该按钮可以将对应的网址从监测列表中移除,同时也会从筛选下拉框中移除该网址选项。
筛选网址:右侧面板有一个 “筛选网址” 的下拉框,用户可以选择具体的网址进行筛选,只显示该网址的监测日志,也可以选择 “全部” 来显示所有网址的监测日志。
2. 监测功能
设置监测间隔:用户可以在输入框中设置监测间隔时间(单位为秒),默认值为 60 秒。
开始 / 停止监测:点击 “开始监测” 按钮,工具会立即对所有已添加的网址进行一次检测,之后按照设置的监测间隔时间循环检测。点击 “停止监测” 按钮可停止监测。
重试机制:在进行网址检测时,如果请求失败,会进行最多 3 次重试,若重试后仍失败,则记录错误日志。
3. 日志记录与显示功能
日志记录:每次对网址进行检测后,会记录网址的状态(正常或异常)、响应时间、时间戳以及错误信息(若有)。日志记录会存储在 logs 数组中,当日志数量超过 1000 条时,会移除最早的日志记录。
日志显示:右侧面板的日志容器会显示所有或筛选后的监测日志,正常状态的日志为黑色,异常状态的日志为红色。日志会自动滚动到最底部以显示最新信息。
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>网站监测工具</title>
- <style>
- body {
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
- background-color: #f9f9f9;
- display: flex;
- margin: 0;
- padding: 0;
- height: 100vh;
- }
-
- /* 调整左右面板的高度,减去一行日志的大致高度(假设为 30px) */
- .left-panel,
- .right-panel {
- flex: 1;
- padding: 20px;
- background-color: #fff;
- border-radius: 8px;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
- margin: 20px;
- height: calc(100vh - 40px - 30px);
- overflow-y: auto;
- display: flex;
- flex-direction: column;
- }
-
- .right-panel {
- flex: 2;
- }
-
- h1 {
- color: #333;
- margin-bottom: 20px;
- text-align: center;
- }
-
- .input-container {
- margin-bottom: 15px;
- display: flex;
- align-items: center;
- }
-
- input {
- padding: 10px;
- margin-right: 10px;
- border: 1px solid #ccc;
- border-radius: 4px;
- flex: 1;
- transition: all 0.3s ease;
- }
-
- input.invalid {
- color: red;
- animation: shake 0.5s ease-in-out 3;
- }
-
- @keyframes shake {
- 0% {
- transform: translateX(0);
- }
- 25% {
- transform: translateX(-5px);
- }
- 50% {
- transform: translateX(5px);
- }
- 75% {
- transform: translateX(-5px);
- }
- 100% {
- transform: translateX(0);
- }
- }
-
- button {
- padding: 10px 15px;
- background-color: #007BFF;
- color: white;
- border: none;
- border-radius: 4px;
- cursor: pointer;
- transition: background-color 0.3s ease;
- }
-
- button:hover {
- background-color: #0056b3;
- }
-
- #monitor-button.started {
- background-color: #dc3545;
- }
-
- ul {
- list-style-type: none;
- padding: 0;
- margin-top: 10px;
- /* 假设每个网址高度约 30px,显示 5 个网址的高度 */
- height: calc(5 * (30px + 5px));
- overflow-y: auto;
- flex: 1;
- }
-
- li {
- background-color: #f4f4f9;
- padding: 10px;
- margin-bottom: 5px;
- border-radius: 4px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
-
- #log-container {
- margin-top: 10px;
- height: calc(11 * (30px + 5px));
- overflow-y: auto;
- border: 1px solid #ccc;
- padding: 10px;
- border-radius: 4px;
- }
-
- #filter-container {
- margin-bottom: 10px;
- }
-
- #filter-url {
- padding: 8px;
- border: 1px solid #ccc;
- border-radius: 4px;
- width: 100%;
- }
- </style>
- </head>
-
- <body>
- <div class="left-panel">
- <h1>网站监测工具</h1>
- <div class="input-container">
- <input type="text" id="url-input" placeholder="输入要监测的网页地址">
- <button id="add-url">添加网址</button>
- </div>
- <div class="input-container">
- <label for="interval">监测间隔 (秒):</label>
- <input type="number" id="interval" value="60">
- <button id="monitor-button">开始监测</button>
- </div>
- <ul id="url-list"></ul>
- </div>
- <div class="right-panel">
- <div id="filter-container">
- <label for="filter-url">筛选网址:</label>
- <select id="filter-url">
- <option value="">全部</option>
- </select>
- </div>
- <div id="log-container"></div>
- </div>
- <script>
- const urlInput = document.getElementById('url-input');
- const addUrlButton = document.getElementById('add-url');
- const intervalInput = document.getElementById('interval');
- const monitorButton = document.getElementById('monitor-button');
- const urlList = document.getElementById('url-list');
- const logContainer = document.getElementById('log-container');
- const filterUrlSelect = document.getElementById('filter-url');
-
- let urls = [];
- let logs = [];
- let intervalId;
- let isMonitoring = false;
- const MAX_RETRIES = 3;
- const MAX_LOGS = 1000;
- let isNetworkConnected = true;
-
- addUrlButton.addEventListener('click', () => {
- let url = urlInput.value.trim();
- if (!url) {
- urlInput.classList.add('invalid');
- setTimeout(() => {
- urlInput.classList.remove('invalid');
- }, 1500);
- alert('请输入有效的网址');
- return;
- }
- if (!url.startsWith('http://') && !url.startsWith('https://') && !url.startsWith('www.')) {
- url = 'https://' + url;
- } else if (url.startsWith('www.')) {
- url = 'https://' + url;
- }
- if (!/^https?:\/\/.+/i.test(url)) {
- urlInput.classList.add('invalid');
- setTimeout(() => {
- urlInput.classList.remove('invalid');
- }, 1500);
- alert('请输入以 http://、https:// 或 www. 开头的有效网址');
- return;
- }
- urlInput.classList.remove('invalid');
- urls.push(url);
- const li = document.createElement('li');
- li.textContent = url;
- const deleteButton = document.createElement('button');
- deleteButton.textContent = '删除';
- deleteButton.addEventListener('click', () => {
- const index = urls.indexOf(url);
- if (index > -1) {
- urls.splice(index, 1);
- urlList.removeChild(li);
- const options = Array.from(filterUrlSelect.options);
- const optionToRemove = options.find(option => option.value === url);
- if (optionToRemove) {
- filterUrlSelect.removeChild(optionToRemove);
- }
- }
- });
- li.appendChild(deleteButton);
- urlList.appendChild(li);
- urlInput.value = '';
-
- const option = document.createElement('option');
- option.value = url;
- option.textContent = url;
- filterUrlSelect.appendChild(option);
- });
-
- monitorButton.addEventListener('click', () => {
- if (!isMonitoring) {
- const interval = parseInt(intervalInput.value) * 1000;
- // 立即检测一次所有添加的网址
- urls.forEach(url => {
- checkUrl(url, 0);
- });
- // 按间隔时间循环检测
- intervalId = setInterval(() => {
- const newInterval = parseInt(intervalInput.value) * 1000;
- if (newInterval!== interval) {
- clearInterval(intervalId);
- intervalId = setInterval(() => {
- urls.forEach(url => {
- checkUrl(url, 0);
- });
- }, newInterval);
- }
- if (isNetworkConnected) {
- urls.forEach(url => {
- checkUrl(url, 0);
- });
- }
- }, interval);
- monitorButton.classList.add('started');
- monitorButton.textContent = '停止监测';
- isMonitoring = true;
- } else {
- clearInterval(intervalId);
- monitorButton.classList.remove('started');
- monitorButton.textContent = '开始监测';
- isMonitoring = false;
- }
- });
-
- filterUrlSelect.addEventListener('change', () => {
- const selectedUrl = filterUrlSelect.value;
- displayLogs(selectedUrl);
- });
-
- function monitorUrlsImmediately(urls, interval) {
- // 先立即执行一次监测
- urls.forEach(url => {
- checkUrl(url, 0);
- });
- // 再按间隔时间循环监测
- intervalId = setInterval(() => {
- urls.forEach(url => {
- checkUrl(url, 0);
- });
- }, interval);
- }
-
- function checkUrl(url, retryCount) {
- if (!isNetworkConnected) {
- handleLog(url, null, '电脑网络连接异常');
- return;
- }
- const startTime = performance.now();
- const controller = new AbortController();
- const signal = controller.signal;
- const timeoutId = setTimeout(() => {
- controller.abort();
- }, 5000);
-
- const requestOptions = {
- mode: 'cors',
- signal: signal,
- headers: {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
- }
- };
-
- fetch(url, requestOptions)
- .then(() => {
- clearTimeout(timeoutId);
- const endTime = performance.now();
- const responseTime = endTime - startTime;
- handleLog(url, responseTime, null);
- isNetworkConnected = true;
- })
- .catch(error => {
- clearTimeout(timeoutId);
- const endTime = performance.now();
- const responseTime = endTime - startTime;
- if (retryCount < MAX_RETRIES) {
- setTimeout(() => {
- checkUrl(url, retryCount + 1);
- }, 1000);
- } else {
- let errorMessage = error.message;
- if (error.name === 'AbortError') {
- errorMessage = '请求超时';
- } else if (error.message.includes('NetworkError')) {
- errorMessage = '网络错误,请检查网络连接或代理设置';
- isNetworkConnected = false;
- }
- handleLog(url, responseTime, errorMessage);
- }
- });
- }
-
- function handleLog(url, responseTime, errorMessage) {
- let status;
- if (errorMessage === '电脑网络连接异常') {
- status = '异常';
- } else if (responseTime!== null && responseTime < 800) {
- status = '正常';
- errorMessage = null;
- } else {
- status = '异常';
- if (!errorMessage) {
- errorMessage = `响应时间过长: ${responseTime} 毫秒`;
- }
- }
- const log = {
- url,
- status,
- responseTime: responseTime!== null? Math.round(responseTime) : null,
- timestamp: new Date().toLocaleString(),
- error: errorMessage
- };
- logs.push(log);
- if (logs.length > MAX_LOGS) {
- logs.shift();
- }
- displayLogs(filterUrlSelect.value);
- updateUrlColor(url, status === '正常');
- }
-
- function updateUrlColor(url, isNormal) {
- const listItems = urlList.getElementsByTagName('li');
- for (let i = 0; i < listItems.length; i++) {
- if (listItems[i].textContent.includes(url)) {
- if (isNormal) {
- listItems[i].style.color = 'black';
- } else {
- listItems[i].style.color = 'red';
- }
- break;
- }
- }
- }
-
- function displayLogs(filterUrl) {
- logContainer.innerHTML = '';
- const filteredLogs = filterUrl? logs.filter(log => log.url === filterUrl) : logs;
- filteredLogs.forEach(log => {
- const logEntry = document.createElement('p');
- let statusColor;
- if (log.status === '正常') {
- statusColor = 'black';
- } else {
- statusColor = 'red';
- }
- logEntry.style.color = statusColor;
- logEntry.textContent = `${log.timestamp} - ${log.url} - 状态: ${log.status}`;
- if (log.responseTime!== null) {
- logEntry.textContent += ` - 响应时间: ${log.responseTime} 毫秒`;
- }
- if (log.error) {
- logEntry.textContent += ` - 错误信息: ${log.error}`;
- }
- logContainer.appendChild(logEntry);
- });
- // 自动滚动到最底部显示最新信息
- logContainer.scrollTop = logContainer.scrollHeight;
- }
- </script>
- </body>
-
- </html>
复制代码

|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|