daShangDao_psiWebApp/move/demo/test.html
2026-06-03 10:53:47 +08:00

321 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>ServiceManager 测试</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: Consolas, monospace; background: #1a1a2e; color: #eee; padding: 20px; }
h1 { color: #00d4ff; margin-bottom: 20px; text-align: center; }
.panel { background: #16213e; border-radius: 8px; padding: 15px; margin-bottom: 15px; }
.panel-title { color: #00d4ff; font-size: 14px; margin-bottom: 10px; }
.row { display: flex; gap: 10px; align-items: center; margin-bottom: 10px; flex-wrap: wrap; }
label { color: #888; min-width: 80px; }
input { background: #0f3460; border: 1px solid #00d4ff; color: #fff; padding: 8px; border-radius: 4px; }
input[type="text"] { width: 300px; }
input[type="number"] { width: 100px; }
button { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; font-family: inherit; }
.btn-primary { background: #00d4ff; color: #1a1a2e; }
.btn-success { background: #28a745; color: #fff; }
.btn-danger { background: #dc3545; color: #fff; }
.btn-warning { background: #ffc107; color: #1a1a2e; }
.btn-purple { background: #9b59b6; color: #fff; }
button:disabled { opacity: 0.5; cursor: not-allowed; }
button:hover:not(:disabled) { opacity: 0.85; }
.log-box { background: #0d1b2a; border-radius: 4px; padding: 10px; height: 280px; overflow-y: auto; font-size: 12px; }
.log-entry { padding: 4px 0; border-bottom: 1px solid #1a1a2e; }
.log-entry:first-child { border-top: 1px solid #1a1a2e; }
.log-info .lv { color: #3498db; }
.log-success .lv { color: #27ae60; }
.log-error .lv { color: #e74c3c; }
.log-warn .lv { color: #f39c12; }
.log-debug .lv { color: #9b59b6; }
.log-data { background: #1a1a2e; padding: 4px; border-radius: 3px; margin-top: 3px; font-size: 11px; white-space: pre-wrap; word-break: break-all; color: #888; }
.info { color: #888; font-size: 12px; }
.status-card { background: #1a1a2e; padding: 15px; border-radius: 8px; text-align: center; margin: 10px 0; }
.status-card.running { border-left: 4px solid #27ae60; }
.status-card.stopped { border-left: 4px solid #e74c3c; }
.status-name { font-size: 18px; font-weight: bold; margin-bottom: 10px; }
.status-pid { color: #888; font-size: 14px; }
.big-btn { padding: 12px 30px; font-size: 14px; }
.console-hint { background: #0d1b2a; padding: 8px; border-radius: 4px; margin-top: 10px; font-size: 11px; color: #888; }
</style>
</head>
<body>
<h1>🔧 ServiceManager 测试</h1>
<!-- DEBUG 控制 -->
<div class="panel">
<div class="panel-title">🔧 DEBUG 控制</div>
<div class="row">
<button class="btn-purple" id="btnDebugOn">开启 DEBUG</button>
<button class="btn-purple" id="btnDebugOff">关闭 DEBUG</button>
<span class="info" id="debugStatus">DEBUG: 关闭</span>
</div>
<div class="console-hint">
💡 开启DEBUG后打开浏览器控制台(F12)可看到详细的请求/响应调试信息
</div>
</div>
<!-- 配置 -->
<div class="panel">
<div class="panel-title">⚙️ 配置</div>
<div class="row">
<label>API 地址:</label>
<input type="text" id="apiUrl" value="http://127.0.0.1:5000">
</div>
<div class="row">
<label>轮询间隔:</label>
<input type="number" id="pollMs" value="3000">
<span class="info">ms</span>
</div>
<div class="row">
<button class="btn-primary" id="btnCreate">创建实例</button>
<button class="btn-danger" id="btnDestroy" disabled>销毁实例</button>
</div>
</div>
<!-- 操作 -->
<div class="panel">
<div class="panel-title">🎮 操作</div>
<div class="row">
<button class="btn-success" id="btnGetStatus" disabled>查询状态</button>
<button class="btn-success big-btn" id="btnStart" disabled>启动</button>
<button class="btn-danger big-btn" id="btnStop" disabled>停止</button>
</div>
<div class="row">
<button class="btn-primary" id="btnAutoOn" disabled>开启自动刷新</button>
<button class="btn-warning" id="btnAutoOff" disabled>停止自动刷新</button>
</div>
<div class="info" id="autoInfo">自动刷新: 未启动</div>
</div>
<!-- 状态显示 -->
<div class="panel">
<div class="panel-title">📊 服务状态</div>
<div class="status-card stopped" id="statusCard">
<div class="status-name" id="statusName">未连接</div>
<div class="status-pid" id="statusPid">-</div>
</div>
</div>
<!-- 日志 -->
<div class="panel">
<div class="panel-title">📋 运行日志 <span id="logCount" style="color:#888;font-weight:normal">(0条)</span></div>
<div class="log-box" id="logBox"></div>
</div>
<!-- 引入编译后的类 -->
<script type="module">
import { ServiceManager } from './dist/ServiceManager.js';
// 全局变量
let sm = null;
// DOM 元素
const $ = id => document.getElementById(id);
const logBox = $('logBox');
const logCount = $('logCount');
const statusCard = $('statusCard');
const statusName = $('statusName');
const statusPid = $('statusPid');
const autoInfo = $('autoInfo');
const debugStatus = $('debugStatus');
// 日志显示
function addLog(entry) {
const div = document.createElement('div');
div.className = `log-entry log-${entry.level}`;
div.innerHTML = `
<span style="color:#666">${entry.time}</span>
<span class="lv">[${entry.level.toUpperCase()}]</span>
${entry.message}
`;
if (entry.data !== undefined) {
const data = document.createElement('div');
data.className = 'log-data';
data.textContent = typeof entry.data === 'object' ? JSON.stringify(entry.data, null, 2) : entry.data;
div.appendChild(data);
}
logBox.appendChild(div);
logBox.scrollTop = logBox.scrollHeight;
logCount.textContent = `(${logBox.children.length}条)`;
}
// 更新UI
function updateUI(service) {
if (!service) {
statusCard.className = 'status-card stopped';
statusName.textContent = '未连接';
statusPid.textContent = '-';
return;
}
statusCard.className = `status-card ${service.status}`;
statusName.textContent = service.status === 'running' ? '🟢 运行中' : '🔴 已停止';
statusPid.textContent = service.pid ? `PID: ${service.pid}` : 'PID: 无';
}
// 更新按钮状态
function updateBtns() {
const hasSm = sm !== null;
const autoOn = hasSm && sm.isAutoRefreshRunning();
$('btnDestroy').disabled = !hasSm;
$('btnGetStatus').disabled = !hasSm;
$('btnStart').disabled = !hasSm;
$('btnStop').disabled = !hasSm;
$('btnAutoOn').disabled = !hasSm || autoOn;
$('btnAutoOff').disabled = !hasSm || !autoOn;
autoInfo.textContent = `自动刷新: ${autoOn ? '开启 🟢' : '关闭'}`;
debugStatus.textContent = `DEBUG: ${ServiceManager.isDebugEnabled() ? '开启 🟢' : '关闭'}`;
}
// DEBUG 开关
$('btnDebugOn').onclick = () => {
ServiceManager.enableDebug();
debugStatus.textContent = 'DEBUG: 开启 🟢';
addLog({ time: new Date().toLocaleTimeString(), level: 'info', message: 'DEBUG 模式已开启,请在浏览器控制台查看详细日志' });
};
$('btnDebugOff').onclick = () => {
ServiceManager.disableDebug();
debugStatus.textContent = 'DEBUG: 关闭';
addLog({ time: new Date().toLocaleTimeString(), level: 'info', message: 'DEBUG 模式已关闭' });
};
// 创建实例
$('btnCreate').onclick = () => {
// 销毁旧实例
if (sm) {
sm.destroy();
sm = null;
}
const apiUrl = $('apiUrl').value;
const pollMs = parseInt($('pollMs').value) || 3000;
sm = new ServiceManager(apiUrl);
sm.setPollInterval(pollMs);
// 设置状态变化回调
sm.setOnStatusChange((service) => {
updateUI(service);
addLog({
time: new Date().toLocaleTimeString(),
level: service.running ? 'success' : 'warn',
message: `状态变化: ${service.name}${service.running ? '运行中' : '已停止'}`
});
});
addLog({ time: new Date().toLocaleTimeString(), level: 'success', message: `实例已创建 | API: ${apiUrl} | 轮询: ${pollMs}ms` });
updateBtns();
};
// 销毁实例
$('btnDestroy').onclick = () => {
if (sm) {
sm.destroy();
sm = null;
addLog({ time: new Date().toLocaleTimeString(), level: 'warn', message: '实例已销毁' });
updateUI(null);
updateBtns();
}
};
// 查询状态
$('btnGetStatus').onclick = async () => {
if (!sm) return;
addLog({ time: new Date().toLocaleTimeString(), level: 'info', message: '--- 查询状态 ---' });
// 打印所有日志
const logs1 = sm.getLogs();
logs1.forEach(log => addLog(log));
const services = await sm.getServicesStatus();
const logs2 = sm.getLogs();
// 只显示新的日志
logs2.slice(logs1.length).forEach(log => addLog(log));
if (services.length > 0) {
updateUI(services[0]);
}
};
// 启动
$('btnStart').onclick = async () => {
if (!sm) return;
addLog({ time: new Date().toLocaleTimeString(), level: 'info', message: '--- 启动服务 ---' });
const before = sm.getLogs().length;
await sm.startService('watchdog');
const logs = sm.getLogs();
logs.slice(before).forEach(log => addLog(log));
// 延迟刷新状态
setTimeout(async () => {
const before2 = sm.getLogs().length;
const services = await sm.getServicesStatus();
sm.getLogs().slice(before2).forEach(log => addLog(log));
updateUI(services[0]);
}, 1000);
};
// 停止
$('btnStop').onclick = async () => {
if (!sm) return;
addLog({ time: new Date().toLocaleTimeString(), level: 'info', message: '--- 停止服务 ---' });
const before = sm.getLogs().length;
await sm.stopService('watchdog');
const logs = sm.getLogs();
logs.slice(before).forEach(log => addLog(log));
// 延迟刷新状态
setTimeout(async () => {
const before2 = sm.getLogs().length;
const services = await sm.getServicesStatus();
sm.getLogs().slice(before2).forEach(log => addLog(log));
updateUI(services[0]);
}, 500);
};
// 开启自动刷新
$('btnAutoOn').onclick = () => {
if (!sm) return;
addLog({ time: new Date().toLocaleTimeString(), level: 'info', message: '--- 开启自动刷新 ---' });
sm.startAutoRefresh((services) => {
updateUI(services[0]);
const logs = sm.getLogs();
if (logs.length > 0) {
addLog(logs[logs.length - 1]);
}
});
updateBtns();
};
// 停止自动刷新
$('btnAutoOff').onclick = () => {
if (!sm) return;
addLog({ time: new Date().toLocaleTimeString(), level: 'warn', message: '--- 停止自动刷新 ---' });
sm.stopAutoRefresh();
updateBtns();
};
// 初始化提示
addLog({ time: new Date().toLocaleTimeString(), level: 'info', message: 'ServiceManager 测试页 | 点击"开启 DEBUG"查看详细日志' });
addLog({ time: new Date().toLocaleTimeString(), level: 'info', message: '请先开启 DEBUG 模式,然后点击"创建实例"' });
</script>
</body>
</html>