Files
ocdp-go/frontend/public/api-test.html
mangomqy c5e51ed069 ocdp v1
2025-11-13 02:54:06 +00:00

432 lines
14 KiB
HTML
Raw Permalink 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>OCDP API camelCase 测试</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 20px;
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 10px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 30px;
text-align: center;
}
.header h1 {
font-size: 2em;
margin-bottom: 10px;
}
.header p {
opacity: 0.9;
}
.content {
padding: 30px;
}
.section {
margin-bottom: 30px;
}
.section h2 {
color: #333;
margin-bottom: 15px;
border-bottom: 2px solid #667eea;
padding-bottom: 10px;
}
.input-group {
margin-bottom: 15px;
}
.input-group label {
display: block;
margin-bottom: 5px;
color: #555;
font-weight: bold;
}
.input-group input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
}
.buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-bottom: 20px;
}
button {
padding: 12px 24px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
transition: all 0.3s;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.btn-success {
background: #4CAF50;
color: white;
}
.btn-info {
background: #2196F3;
color: white;
}
.btn-warning {
background: #FF9800;
color: white;
}
.btn-danger {
background: #f44336;
color: white;
}
.log-container {
background: #1e1e1e;
color: #d4d4d4;
padding: 20px;
border-radius: 5px;
min-height: 400px;
max-height: 600px;
overflow-y: auto;
font-size: 13px;
line-height: 1.6;
white-space: pre-wrap;
word-wrap: break-word;
}
.log-success {
color: #4CAF50;
}
.log-error {
color: #f44336;
}
.log-warning {
color: #FF9800;
}
.log-info {
color: #2196F3;
}
.status {
padding: 10px;
margin-bottom: 20px;
border-radius: 5px;
text-align: center;
font-weight: bold;
}
.status.loading {
background: #FFF3CD;
color: #856404;
}
.status.success {
background: #D4EDDA;
color: #155724;
}
.status.error {
background: #F8D7DA;
color: #721C24;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🧪 OCDP API camelCase 测试</h1>
<p>测试前后端 camelCase 通信是否正常</p>
</div>
<div class="content">
<div class="section">
<h2>⚙️ 配置</h2>
<div class="input-group">
<label for="apiUrl">API 地址:</label>
<input type="text" id="apiUrl" value="http://localhost:8080/api/v1" />
</div>
<div class="input-group">
<label for="token">Token (登录后自动填充):</label>
<input type="text" id="token" placeholder="JWT Token" />
</div>
</div>
<div class="section">
<h2>🎮 测试操作</h2>
<div class="buttons">
<button class="btn-success" onclick="testLogin()">1. 测试登录</button>
<button class="btn-info" onclick="testListClusters()">2. 获取集群列表</button>
<button class="btn-warning" onclick="testCreateCluster()">3. 创建集群</button>
<button class="btn-primary" onclick="testFullFlow()">🚀 完整测试</button>
<button class="btn-danger" onclick="clearLog()">清除日志</button>
</div>
</div>
<div id="status" class="status hidden"></div>
<div class="section">
<h2>📋 测试日志</h2>
<div id="log" class="log-container">点击按钮开始测试...</div>
</div>
</div>
</div>
<script>
const logEl = document.getElementById('log');
const statusEl = document.getElementById('status');
const tokenInput = document.getElementById('token');
const apiUrlInput = document.getElementById('apiUrl');
function getApiUrl() {
return apiUrlInput.value;
}
function getToken() {
return tokenInput.value;
}
function setStatus(message, type = 'loading') {
statusEl.textContent = message;
statusEl.className = `status ${type}`;
statusEl.classList.remove('hidden');
}
function hideStatus() {
statusEl.classList.add('hidden');
}
function log(message, type = 'info') {
const timestamp = new Date().toLocaleTimeString();
const className = `log-${type}`;
logEl.innerHTML += `<span class="${className}">[${timestamp}] ${message}</span>\n`;
logEl.scrollTop = logEl.scrollHeight;
}
function clearLog() {
logEl.innerHTML = '';
hideStatus();
log('日志已清除', 'info');
}
async function testLogin() {
clearLog();
log('🔐 开始测试登录...', 'info');
setStatus('正在登录...', 'loading');
try {
const response = await fetch(`${getApiUrl()}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: 'admin',
password: 'admin123'
})
});
const data = await response.json();
log('响应数据:\n' + JSON.stringify(data, null, 2), 'info');
if (data.accessToken) {
log('✅ 登录成功!', 'success');
tokenInput.value = data.accessToken;
// 验证 camelCase
if ('accessToken' in data) log(' ✓ accessToken 字段存在 (camelCase)', 'success');
if ('refreshToken' in data) log(' ✓ refreshToken 字段存在 (camelCase)', 'success');
if ('userId' in data) log(' ✓ userId 字段存在 (camelCase)', 'success');
setStatus('✅ 登录成功!', 'success');
} else {
log('❌ 登录失败: 未找到 accessToken', 'error');
setStatus('❌ 登录失败', 'error');
}
} catch (error) {
log(`❌ 请求失败: ${error.message}`, 'error');
setStatus('❌ 请求失败', 'error');
}
}
async function testListClusters() {
log('\n📋 开始获取集群列表...', 'info');
const token = getToken();
if (!token) {
log('❌ 请先登录获取 Token', 'error');
return;
}
setStatus('正在获取集群列表...', 'loading');
try {
const response = await fetch(`${getApiUrl()}/clusters`, {
headers: { 'Authorization': `Bearer ${token}` }
});
const data = await response.json();
log(`响应数据 (共 ${Array.isArray(data) ? data.length : 0} 个集群):\n` +
JSON.stringify(data, null, 2), 'info');
if (Array.isArray(data)) {
log('✅ 获取集群列表成功!', 'success');
// 验证 camelCase
if (data.length > 0) {
const cluster = data[0];
if ('createdAt' in cluster) log(' ✓ createdAt 字段存在 (camelCase)', 'success');
if ('updatedAt' in cluster) log(' ✓ updatedAt 字段存在 (camelCase)', 'success');
if ('hasCaData' in cluster) log(' ✓ hasCaData 字段存在 (camelCase)', 'success');
}
setStatus(`✅ 获取成功!共 ${data.length} 个集群`, 'success');
} else {
log('❌ 响应格式错误', 'error');
setStatus('❌ 响应格式错误', 'error');
}
} catch (error) {
log(`❌ 请求失败: ${error.message}`, 'error');
setStatus('❌ 请求失败', 'error');
}
}
async function testCreateCluster() {
log('\n🚀 开始创建集群 (使用 camelCase)...', 'info');
const token = getToken();
if (!token) {
log('❌ 请先登录获取 Token', 'error');
return;
}
setStatus('正在创建集群...', 'loading');
const clusterData = {
name: `test-cluster-${Date.now()}`,
host: 'https://k8s.test.example.com:6443',
description: '测试集群 - camelCase 验证',
caData: 'LS0tLS1CRUdJTi1DRVJUSUZJQ0FURS0tLS0t',
certData: 'LS0tLS1CRUdJTi1DRVJUSUZJQ0FURS0tLS0t',
keyData: 'LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVkt'
};
log('请求数据 (camelCase):\n' + JSON.stringify(clusterData, null, 2), 'info');
try {
const response = await fetch(`${getApiUrl()}/clusters`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(clusterData)
});
const data = await response.json();
log('响应数据:\n' + JSON.stringify(data, null, 2), 'info');
if (data.id) {
log('✅ 创建集群成功!', 'success');
log(` 集群 ID: ${data.id}`, 'info');
// 验证 camelCase
if ('hasCaData' in data) log(' ✓ hasCaData 字段存在 (camelCase)', 'success');
if ('hasCertData' in data) log(' ✓ hasCertData 字段存在 (camelCase)', 'success');
if ('createdAt' in data) log(' ✓ createdAt 字段存在 (camelCase)', 'success');
setStatus('✅ 创建成功!', 'success');
} else {
log('❌ 创建失败或响应格式错误', 'error');
setStatus('❌ 创建失败', 'error');
}
} catch (error) {
log(`❌ 请求失败: ${error.message}`, 'error');
setStatus('❌ 请求失败', 'error');
}
}
async function testFullFlow() {
clearLog();
log('🧪 开始完整测试流程...\n', 'info');
setStatus('正在执行完整测试...', 'loading');
// 步骤 1: 登录
await testLogin();
await new Promise(resolve => setTimeout(resolve, 1000));
// 步骤 2: 获取集群列表
await testListClusters();
await new Promise(resolve => setTimeout(resolve, 1000));
// 步骤 3: 创建集群
await testCreateCluster();
log('\n🎉 完整测试流程完成!', 'success');
log('所有 API 调用成功camelCase 工作正常!', 'success');
setStatus('🎉 完整测试通过!', 'success');
}
// 页面加载完成后的初始化
window.addEventListener('load', () => {
log('🌐 页面已加载,可以开始测试', 'info');
log('提示: 点击 "🚀 完整测试" 运行所有测试\n', 'info');
});
</script>
</body>
</html>