237 lines
8.2 KiB
HTML
237 lines
8.2 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>购物车请求调试工具</title>
|
||
<style>
|
||
body {
|
||
font-family: Arial, sans-serif;
|
||
max-width: 1200px;
|
||
margin: 20px auto;
|
||
padding: 20px;
|
||
}
|
||
.section {
|
||
margin: 20px 0;
|
||
padding: 15px;
|
||
border: 1px solid #ddd;
|
||
border-radius: 5px;
|
||
}
|
||
button {
|
||
padding: 10px 20px;
|
||
margin: 5px;
|
||
cursor: pointer;
|
||
background: #4CAF50;
|
||
color: white;
|
||
border: none;
|
||
border-radius: 4px;
|
||
}
|
||
button:hover {
|
||
background: #45a049;
|
||
}
|
||
.log {
|
||
background: #f5f5f5;
|
||
padding: 10px;
|
||
margin: 10px 0;
|
||
border-radius: 4px;
|
||
font-family: monospace;
|
||
white-space: pre-wrap;
|
||
max-height: 400px;
|
||
overflow-y: auto;
|
||
}
|
||
.success { color: green; }
|
||
.error { color: red; }
|
||
.info { color: blue; }
|
||
input {
|
||
width: 100%;
|
||
padding: 8px;
|
||
margin: 5px 0;
|
||
border: 1px solid #ddd;
|
||
border-radius: 4px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>🔧 购物车请求调试工具</h1>
|
||
|
||
<div class="section">
|
||
<h2>1. 环境信息</h2>
|
||
<div id="envInfo" class="log"></div>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>2. 配置 API 地址</h2>
|
||
<input type="text" id="apiUrl" placeholder="输入 API 地址,例如:http://104.244.91.212:8060/api/v1" value="http://104.244.91.212:8060/api/v1">
|
||
<input type="text" id="token" placeholder="输入 Token(从 localStorage 获取)">
|
||
<button onclick="loadToken()">从 localStorage 加载 Token</button>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>3. 测试接口</h2>
|
||
<button onclick="testHealth()">测试健康检查</button>
|
||
<button onclick="testBanners()">测试轮播图(无需认证)</button>
|
||
<button onclick="testCart()">测试购物车(需要认证)</button>
|
||
<button onclick="testCORS()">测试 CORS 预检</button>
|
||
</div>
|
||
|
||
<div class="section">
|
||
<h2>4. 请求日志</h2>
|
||
<button onclick="clearLog()">清空日志</button>
|
||
<div id="log" class="log"></div>
|
||
</div>
|
||
|
||
<script>
|
||
// 显示环境信息
|
||
function showEnvInfo() {
|
||
const info = {
|
||
'当前页面': window.location.href,
|
||
'协议': window.location.protocol,
|
||
'主机名': window.location.hostname,
|
||
'端口': window.location.port,
|
||
'用户代理': navigator.userAgent,
|
||
'localStorage Token': localStorage.getItem('currentUser') ? '已存在' : '不存在'
|
||
};
|
||
|
||
let html = '';
|
||
for (let [key, value] of Object.entries(info)) {
|
||
html += `<div><strong>${key}:</strong> ${value}</div>`;
|
||
}
|
||
document.getElementById('envInfo').innerHTML = html;
|
||
}
|
||
|
||
// 加载 Token
|
||
function loadToken() {
|
||
try {
|
||
const user = localStorage.getItem('currentUser');
|
||
if (user) {
|
||
const userData = JSON.parse(user);
|
||
document.getElementById('token').value = userData.token || '';
|
||
log('✓ Token 已加载', 'success');
|
||
} else {
|
||
log('✗ localStorage 中没有找到用户信息', 'error');
|
||
}
|
||
} catch (e) {
|
||
log('✗ 加载 Token 失败: ' + e.message, 'error');
|
||
}
|
||
}
|
||
|
||
// 日志函数
|
||
function log(message, type = 'info') {
|
||
const logDiv = document.getElementById('log');
|
||
const time = new Date().toLocaleTimeString();
|
||
logDiv.innerHTML += `<div class="${type}">[${time}] ${message}</div>`;
|
||
logDiv.scrollTop = logDiv.scrollHeight;
|
||
}
|
||
|
||
function clearLog() {
|
||
document.getElementById('log').innerHTML = '';
|
||
}
|
||
|
||
// 通用请求函数
|
||
async function makeRequest(url, options = {}) {
|
||
log(`\n========== 开始请求 ==========`, 'info');
|
||
log(`URL: ${url}`, 'info');
|
||
log(`Method: ${options.method || 'GET'}`, 'info');
|
||
|
||
if (options.headers) {
|
||
log(`Headers: ${JSON.stringify(options.headers, null, 2)}`, 'info');
|
||
}
|
||
|
||
try {
|
||
const startTime = Date.now();
|
||
const response = await fetch(url, options);
|
||
const duration = Date.now() - startTime;
|
||
|
||
log(`\n响应状态: ${response.status} ${response.statusText}`,
|
||
response.ok ? 'success' : 'error');
|
||
log(`响应时间: ${duration}ms`, 'info');
|
||
|
||
// 显示响应头
|
||
log(`\n响应头:`, 'info');
|
||
response.headers.forEach((value, key) => {
|
||
log(` ${key}: ${value}`, 'info');
|
||
});
|
||
|
||
// 获取响应体
|
||
const contentType = response.headers.get('content-type');
|
||
let data;
|
||
if (contentType && contentType.includes('application/json')) {
|
||
data = await response.json();
|
||
log(`\n响应数据:\n${JSON.stringify(data, null, 2)}`, 'success');
|
||
} else {
|
||
data = await response.text();
|
||
log(`\n响应数据:\n${data}`, 'info');
|
||
}
|
||
|
||
log(`========== 请求完成 ==========\n`, 'info');
|
||
return { ok: response.ok, status: response.status, data };
|
||
} catch (error) {
|
||
log(`\n✗ 请求失败: ${error.message}`, 'error');
|
||
log(`错误类型: ${error.name}`, 'error');
|
||
log(`错误堆栈: ${error.stack}`, 'error');
|
||
log(`========== 请求失败 ==========\n`, 'error');
|
||
return { ok: false, error: error.message };
|
||
}
|
||
}
|
||
|
||
// 测试健康检查
|
||
async function testHealth() {
|
||
const apiUrl = document.getElementById('apiUrl').value;
|
||
const baseUrl = apiUrl.replace('/api/v1', '');
|
||
await makeRequest(`${baseUrl}/health`);
|
||
}
|
||
|
||
// 测试轮播图
|
||
async function testBanners() {
|
||
const apiUrl = document.getElementById('apiUrl').value;
|
||
await makeRequest(`${apiUrl}/banners`);
|
||
}
|
||
|
||
// 测试购物车
|
||
async function testCart() {
|
||
const apiUrl = document.getElementById('apiUrl').value;
|
||
const token = document.getElementById('token').value;
|
||
|
||
if (!token) {
|
||
log('✗ 请先输入或加载 Token', 'error');
|
||
return;
|
||
}
|
||
|
||
await makeRequest(`${apiUrl}/cart`, {
|
||
method: 'GET',
|
||
headers: {
|
||
'Authorization': `Bearer ${token}`,
|
||
'Content-Type': 'application/json'
|
||
},
|
||
credentials: 'include'
|
||
});
|
||
}
|
||
|
||
// 测试 CORS 预检
|
||
async function testCORS() {
|
||
const apiUrl = document.getElementById('apiUrl').value;
|
||
|
||
log(`\n========== CORS 预检测试 ==========`, 'info');
|
||
log(`这个测试会发送 OPTIONS 请求`, 'info');
|
||
|
||
await makeRequest(`${apiUrl}/cart`, {
|
||
method: 'OPTIONS',
|
||
headers: {
|
||
'Origin': window.location.origin,
|
||
'Access-Control-Request-Method': 'GET',
|
||
'Access-Control-Request-Headers': 'authorization,content-type'
|
||
}
|
||
});
|
||
}
|
||
|
||
// 页面加载时执行
|
||
window.onload = function() {
|
||
showEnvInfo();
|
||
loadToken();
|
||
log('调试工具已就绪', 'success');
|
||
log('请按顺序测试各个接口,观察错误信息', 'info');
|
||
};
|
||
</script>
|
||
</body>
|
||
</html>
|