133 lines
5.9 KiB
HTML
133 lines
5.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<link href="https://cdn.staticfile.org/twitter-bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="https://cdn.staticfile.org/bootstrap-icons/1.10.0/font/bootstrap-icons.min.css" rel="stylesheet">
|
|
<style>
|
|
body { background: #1e1e1e; color: #d4d4d4; margin: 0; font-family: 'Consolas', monospace; font-size: 11px; height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
|
|
|
|
/* 头部样式 */
|
|
.header { background: #2d2d2d; padding: 5px 15px; display: flex; justify-content: space-between; align-items: center; cursor: pointer; border-bottom: 2px solid #444; height: 40px; flex-shrink: 0; }
|
|
.search-box { background: #3c3c3c; border: 1px solid #555; color: #fff; padding: 2px 8px; border-radius: 4px; font-size: 11px; width: 220px; }
|
|
|
|
/* 日志区域 */
|
|
.body { flex: 1; overflow-y: auto; padding: 5px 10px; background: #1e1e1e; }
|
|
.log-row { display: flex; gap: 12px; border-bottom: 1px solid #2a2a2a; padding: 4px 0; align-items: center; white-space: nowrap; }
|
|
.log-row:hover { background: #2a2a2a; }
|
|
|
|
/* 文字颜色定义 */
|
|
.t-time { color: #888; min-width: 75px; }
|
|
.t-method { font-weight: bold; min-width: 50px; color: #569cd6; }
|
|
.t-url { color: #9cdcfe; flex: 1; overflow: hidden; text-overflow: ellipsis; cursor: help; }
|
|
.status-ok { color: #4ec9b0; }
|
|
.status-err { color: #f44747; }
|
|
|
|
/* 复制按钮样式 */
|
|
.btn-copy {
|
|
color: #6a9955; cursor: pointer; padding: 0 5px;
|
|
border: 1px solid transparent; border-radius: 3px;
|
|
transition: 0.2s; visibility: hidden; /* 默认隐藏,悬停显示 */
|
|
}
|
|
.log-row:hover .btn-copy { visibility: visible; }
|
|
.btn-copy:hover { border-color: #6a9955; background: rgba(106, 153, 85, 0.1); }
|
|
|
|
/* 滚动条 */
|
|
::-webkit-scrollbar { width: 6px; }
|
|
::-webkit-scrollbar-thumb { background: #444; border-radius: 3px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="app" style="display: contents;">
|
|
<div class="header" @click="toggle">
|
|
<div>
|
|
<i class="bi bi-terminal-split me-2 text-warning"></i>
|
|
全路径诊断中控 ({{ filteredLogs.length }} 条)
|
|
</div>
|
|
<div class="d-flex align-items-center">
|
|
<input type="text" class="form-control form-control-sm search-box me-3"
|
|
v-model="searchText" @click.stop placeholder="检索 URL / 关键字...">
|
|
<span style="color:#ffca28; font-weight:bold; cursor:pointer" class="me-3">
|
|
{{ isExpanded ? '▼ 收起' : '▲ 展开' }}
|
|
</span>
|
|
<button class="btn btn-outline-danger btn-sm py-0 px-2" @click.stop="logs=[]">清空</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="body" id="log-container">
|
|
<div v-for="log in filteredLogs" :key="log.id" class="log-row">
|
|
<span class="t-time">[{{ log.time }}]</span>
|
|
<span class="t-method">{{ log.method }}</span>
|
|
<span class="t-url" :title="log.url">{{ log.url }}</span>
|
|
<span :class="log.ok ? 'status-ok' : 'status-err'">{{ log.status }}</span>
|
|
|
|
<span class="btn-copy" @click.stop="copyLog(log.url)" title="复制完整URL">
|
|
<i class="bi bi-clipboard-plus"></i> 复制
|
|
</span>
|
|
</div>
|
|
<div v-if="filteredLogs.length === 0" class="text-center text-muted mt-5">
|
|
<i class="bi bi-activity d-block fs-3 mb-2"></i>
|
|
等待数据请求...
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.staticfile.org/vue/3.3.4/vue.global.prod.min.js"></script>
|
|
<script>
|
|
const { createApp, ref, computed, nextTick } = Vue;
|
|
createApp({
|
|
setup() {
|
|
const logs = ref([]);
|
|
const isExpanded = ref(false);
|
|
const searchText = ref("");
|
|
|
|
// 监听母座转发的日志
|
|
window.addEventListener('message', (e) => {
|
|
if (e.data.type === 'PUSH_LOG') {
|
|
logs.value.push({
|
|
id: Date.now() + Math.random(),
|
|
time: new Date().toLocaleTimeString(),
|
|
...e.data.log,
|
|
ok: e.data.log.status === 200 || e.data.log.status === 'OK' || e.data.log.status === 'SEND'
|
|
});
|
|
|
|
// 自动清理,防止内存溢出
|
|
if (logs.value.length > 200) logs.value.shift();
|
|
|
|
// 如果没在搜索,自动滚动到底部
|
|
if(!searchText.value) {
|
|
nextTick(() => {
|
|
const c = document.getElementById('log-container');
|
|
c.scrollTop = c.scrollHeight;
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// 复制到剪贴板功能
|
|
const copyLog = (text) => {
|
|
navigator.clipboard.writeText(text).then(() => {
|
|
// 可以在这里加个简单的 Toast 提示,或者改变图标颜色
|
|
console.log('Copied:', text);
|
|
});
|
|
};
|
|
|
|
const toggle = () => {
|
|
isExpanded.value = !isExpanded.value;
|
|
window.parent.postMessage({ type: 'UI_RESIZE_DIAG', expanded: isExpanded.value }, '*');
|
|
};
|
|
|
|
const filteredLogs = computed(() => {
|
|
const kw = searchText.value.toLowerCase();
|
|
return logs.value.filter(l =>
|
|
l.url.toLowerCase().includes(kw) ||
|
|
(l.msg && l.msg.toLowerCase().includes(kw))
|
|
);
|
|
});
|
|
|
|
return { logs, isExpanded, searchText, filteredLogs, toggle, copyLog };
|
|
}
|
|
}).mount('#app');
|
|
</script>
|
|
</body>
|
|
</html> |