Files
xiaomubiao-master/api-test.html
2026-05-22 16:13:20 +08:00

524 lines
17 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">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>设备状态API测试</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', 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: 15px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 30px;
text-align: center;
}
.header h1 {
font-size: 2.5em;
margin-bottom: 10px;
}
.header p {
font-size: 1.1em;
opacity: 0.9;
}
.controls {
padding: 30px;
background: #f8f9fa;
border-bottom: 1px solid #e9ecef;
}
.control-group {
margin-bottom: 20px;
}
.control-group label {
display: block;
margin-bottom: 8px;
font-weight: bold;
color: #495057;
}
.control-group input {
width: 100%;
padding: 12px;
border: 2px solid #e9ecef;
border-radius: 8px;
font-size: 14px;
transition: border-color 0.3s;
}
.control-group input:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 12px 30px;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
.status {
padding: 15px 30px;
margin: 0;
color: white;
font-weight: bold;
}
.status.loading {
background: #17a2b8;
}
.status.success {
background: #28a745;
}
.status.error {
background: #dc3545;
}
.results {
padding: 30px;
}
.data-card {
background: #f8f9fa;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
border-left: 4px solid #667eea;
}
.data-card h3 {
color: #495057;
margin-bottom: 15px;
font-size: 1.2em;
}
.data-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 15px;
}
.data-item {
background: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.data-item .label {
font-weight: bold;
color: #667eea;
margin-bottom: 5px;
}
.data-item .value {
color: #495057;
font-size: 1.1em;
}
.json-viewer {
background: #2d3748;
color: #e2e8f0;
padding: 20px;
border-radius: 8px;
font-family: 'Courier New', monospace;
overflow-x: auto;
max-height: 400px;
overflow-y: auto;
}
.copy-btn {
float: right;
background: #4a5568;
color: white;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
.copy-btn:hover {
background: #2d3748;
}
@media (max-width: 768px) {
.container {
margin: 10px;
border-radius: 10px;
}
.header {
padding: 20px;
}
.header h1 {
font-size: 2em;
}
.controls, .results {
padding: 20px;
}
.data-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🚁 设备状态API测试</h1>
<p>测试无人机设备状态查询接口</p>
</div>
<div class="controls">
<div class="control-group">
<label for="requestMode">请求模式:</label>
<select id="requestMode" onchange="toggleRequestMode()" style="width: 100%; padding: 12px; border: 2px solid #e9ecef; border-radius: 8px; font-size: 14px;">
<option value="direct">直接请求 (需要后端支持CORS)</option>
<option value="proxy">代理模式 (通过当前域名代理)</option>
<option value="no-cors">No-CORS模式 (获取状态码)</option>
</select>
</div>
<div class="control-group">
<label for="apiUrl">API地址:</label>
<input type="text" id="apiUrl" value="http://27.11.11.30:6791/api/v1/qb3/devices/battle-unit/11010100/status">
</div>
<div class="control-group">
<label for="authorization">Authorization (Bearer Token):</label>
<input type="text" id="authorization" placeholder="请输入Bearer Token">
</div>
<div class="control-group">
<label for="xAuthToken">X-Auth-Token:</label>
<input type="text" id="xAuthToken" value="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9">
</div>
<div class="control-group">
<label for="tenantId">Tenant-Id:</label>
<input type="text" id="tenantId" value="325">
</div>
<button class="btn" onclick="fetchDeviceStatus()">📡 获取设备状态</button>
<button class="btn" onclick="refreshTokens()" style="margin-left: 10px; background: linear-gradient(135deg, #28a745 0%, #20c997 100%);">🔄 刷新认证信息</button>
</div>
<div id="status" class="status" style="display: none;"></div>
<div class="results">
<div id="parsed-data" style="display: none;">
<div class="data-card">
<h3>📊 设备基本信息</h3>
<div class="data-grid" id="basic-info">
</div>
</div>
<div class="data-card">
<h3>📍 位置信息</h3>
<div class="data-grid" id="location-info">
</div>
</div>
<div class="data-card">
<h3>✈️ 飞行状态</h3>
<div class="data-grid" id="flight-info">
</div>
</div>
</div>
<div class="data-card">
<h3>📋 原始JSON数据
<button class="copy-btn" onclick="copyToClipboard()">📋 复制</button>
</h3>
<div class="json-viewer" id="json-output">
暂无数据,请点击"获取设备状态"按钮
</div>
</div>
</div>
</div>
<script>
let currentData = null;
async function fetchDeviceStatus() {
const statusEl = document.getElementById('status');
const jsonOutputEl = document.getElementById('json-output');
const parsedDataEl = document.getElementById('parsed-data');
const btnEl = document.querySelector('.btn');
// 获取输入值
const apiUrl = document.getElementById('apiUrl').value.trim();
const authorization = document.getElementById('authorization').value.trim();
const xAuthToken = document.getElementById('xAuthToken').value.trim();
const tenantId = document.getElementById('tenantId').value.trim();
if (!apiUrl) {
showStatus('error', '❌ 请输入API地址');
return;
}
// 显示加载状态
showStatus('loading', '🔄 正在获取设备状态...');
btnEl.disabled = true;
parsedDataEl.style.display = 'none';
try {
// 构建请求头
const headers = {
'Content-Type': 'application/json',
};
if (authorization) {
headers['Authorization'] = authorization.startsWith('Bearer ') ? authorization : `Bearer ${authorization}`;
}
if (xAuthToken) {
headers['x-auth-token'] = xAuthToken;
}
if (tenantId) {
headers['Tenant-Id'] = tenantId;
}
console.log('发送请求:', { url: apiUrl, headers });
// 发送请求
const response = await fetch(apiUrl, {
method: 'GET',
headers: headers,
mode: 'cors', // 如果遇到跨域问题,可能需要后端支持
});
const responseText = await response.text();
console.log('响应状态:', response.status);
console.log('响应文本:', responseText);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}\n${responseText}`);
}
// 解析JSON
let data;
try {
data = JSON.parse(responseText);
} catch (parseError) {
throw new Error(`JSON解析失败: ${parseError.message}\n原始响应: ${responseText}`);
}
currentData = data;
// 显示成功状态
showStatus('success', '✅ 数据获取成功!');
// 显示格式化的JSON
jsonOutputEl.innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>`;
// 解析并显示结构化数据
if (data.data) {
parseAndDisplayData(data.data);
parsedDataEl.style.display = 'block';
}
} catch (error) {
console.error('请求失败:', error);
showStatus('error', `❌ 请求失败: ${error.message}`);
jsonOutputEl.innerHTML = `<pre style="color: #ff6b6b;">错误信息: ${error.message}</pre>`;
} finally {
btnEl.disabled = false;
}
}
function showStatus(type, message) {
const statusEl = document.getElementById('status');
statusEl.className = `status ${type}`;
statusEl.textContent = message;
statusEl.style.display = 'block';
// 3秒后自动隐藏状态
setTimeout(() => {
statusEl.style.display = 'none';
}, 3000);
}
function parseAndDisplayData(data) {
// 基本信息
const basicInfo = document.getElementById('basic-info');
basicInfo.innerHTML = `
<div class="data-item">
<div class="label">设备ID</div>
<div class="value">${data.id || 'N/A'}</div>
</div>
<div class="data-item">
<div class="label">作战单元代码</div>
<div class="value">${data.battle_unit_code || 'N/A'}</div>
</div>
<div class="data-item">
<div class="label">平台类型</div>
<div class="value">${data.platform_type || 'N/A'}</div>
</div>
<div class="data-item">
<div class="label">租户ID</div>
<div class="value">${data.tenant_id || 'N/A'}</div>
</div>
`;
// 位置信息
const locationInfo = document.getElementById('location-info');
locationInfo.innerHTML = `
<div class="data-item">
<div class="label">纬度</div>
<div class="value">${data.altitude ? data.altitude.toFixed(6) : 'N/A'}°</div>
</div>
<div class="data-item">
<div class="label">经度</div>
<div class="value">${data.latitude ? data.latitude.toFixed(6) : 'N/A'}°</div>
</div>
<div class="data-item">
<div class="label">海拔高度</div>
<div class="value">${data.longitude ? data.longitude.toFixed(2) : 'N/A'}m</div>
</div>
<div class="data-item">
<div class="label">飞行方向</div>
<div class="value">${data.trk_direction ? data.trk_direction.toFixed(2) : 'N/A'}°</div>
</div>
`;
// 飞行状态
const flightInfo = document.getElementById('flight-info');
flightInfo.innerHTML = `
<div class="data-item">
<div class="label">飞行速度</div>
<div class="value">${data.velocity ? data.velocity.toFixed(2) : 'N/A'} m/s</div>
</div>
<div class="data-item">
<div class="label">上报时间</div>
<div class="value">${data.report_time ? new Date(data.report_time).toLocaleString() : 'N/A'}</div>
</div>
<div class="data-item">
<div class="label">设备SN</div>
<div class="value">${data.sn || 'N/A'}</div>
</div>
<div class="data-item">
<div class="label">创建时间</div>
<div class="value">${data.create_time || 'N/A'}</div>
</div>
`;
}
function copyToClipboard() {
if (currentData) {
const jsonText = JSON.stringify(currentData, null, 2);
navigator.clipboard.writeText(jsonText).then(() => {
showStatus('success', '📋 JSON数据已复制到剪贴板');
}).catch(err => {
console.error('复制失败:', err);
showStatus('error', '❌ 复制失败,请手动选择文本复制');
});
}
}
// 从localStorage获取token的函数
function getAuthToken() {
return localStorage.getItem('x-auth-token') || localStorage.getItem('ws-auth-token') || '';
}
function getAuthTokenNew() {
return localStorage.getItem('Authorization') || '';
}
function getTenantId() {
return localStorage.getItem('tenantId') || localStorage.getItem('tenant_id') || '';
}
// 页面加载时自动填充认证信息
window.onload = function() {
// 从localStorage动态获取token
const xAuthToken = getAuthToken();
const authToken = getAuthTokenNew();
const tenantId = getTenantId();
if (xAuthToken) {
document.getElementById('xAuthToken').value = xAuthToken;
}
if (authToken) {
document.getElementById('authorization').value = authToken;
}
if (tenantId) {
document.getElementById('tenantId').value = tenantId;
}
// 显示获取到的token信息
if (xAuthToken || authToken) {
showStatus('success', `✅ 已自动获取认证信息 - x-auth-token: ${xAuthToken ? '已获取' : '未找到'}, Authorization: ${authToken ? '已获取' : '未找到'}`);
} else {
showStatus('error', '⚠️ 未找到认证信息请先登录系统或手动输入token');
}
};
// 添加刷新token按钮功能
function refreshTokens() {
const xAuthToken = getAuthToken();
const authToken = getAuthTokenNew();
const tenantId = getTenantId();
document.getElementById('xAuthToken').value = xAuthToken || '';
document.getElementById('authorization').value = authToken || '';
document.getElementById('tenantId').value = tenantId || '';
if (xAuthToken || authToken) {
showStatus('success', '🔄 认证信息已刷新');
} else {
showStatus('error', '⚠️ 仍未找到认证信息');
}
}
</script>
</body>
</html>