|
|
@@ -0,0 +1,292 @@
|
|
|
+<!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>
|
|
|
+ body {
|
|
|
+ font-family: Arial, sans-serif;
|
|
|
+ max-width: 1200px;
|
|
|
+ margin: 0 auto;
|
|
|
+ padding: 20px;
|
|
|
+ background: #f5f5f5;
|
|
|
+ }
|
|
|
+ .container {
|
|
|
+ background: white;
|
|
|
+ padding: 20px;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+ h1 {
|
|
|
+ color: #333;
|
|
|
+ border-bottom: 2px solid #409eff;
|
|
|
+ padding-bottom: 10px;
|
|
|
+ }
|
|
|
+ h2 {
|
|
|
+ color: #666;
|
|
|
+ margin-top: 20px;
|
|
|
+ }
|
|
|
+ button {
|
|
|
+ background: #409eff;
|
|
|
+ color: white;
|
|
|
+ border: none;
|
|
|
+ padding: 10px 20px;
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ margin: 5px;
|
|
|
+ }
|
|
|
+ button:hover {
|
|
|
+ background: #66b1ff;
|
|
|
+ }
|
|
|
+ .success {
|
|
|
+ background: #d4edda;
|
|
|
+ border-left: 4px solid #28a745;
|
|
|
+ padding: 15px;
|
|
|
+ margin: 10px 0;
|
|
|
+ }
|
|
|
+ .error {
|
|
|
+ background: #f8d7da;
|
|
|
+ border-left: 4px solid #dc3545;
|
|
|
+ padding: 15px;
|
|
|
+ margin: 10px 0;
|
|
|
+ }
|
|
|
+ #output {
|
|
|
+ background: #f9f9f9;
|
|
|
+ padding: 15px;
|
|
|
+ border-radius: 4px;
|
|
|
+ min-height: 100px;
|
|
|
+ white-space: pre-wrap;
|
|
|
+ font-family: monospace;
|
|
|
+ max-height: 600px;
|
|
|
+ overflow-y: auto;
|
|
|
+ }
|
|
|
+ table {
|
|
|
+ width: 100%;
|
|
|
+ border-collapse: collapse;
|
|
|
+ margin-top: 10px;
|
|
|
+ }
|
|
|
+ th, td {
|
|
|
+ border: 1px solid #ddd;
|
|
|
+ padding: 8px;
|
|
|
+ text-align: left;
|
|
|
+ }
|
|
|
+ th {
|
|
|
+ background-color: #409eff;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+ tr:nth-child(even) {
|
|
|
+ background-color: #f2f2f2;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+<body>
|
|
|
+ <div class="container">
|
|
|
+ <h1>🔍 前端API测试工具</h1>
|
|
|
+
|
|
|
+ <h2>步骤 1: 登录</h2>
|
|
|
+ <div>
|
|
|
+ <input type="text" id="username" placeholder="用户名" value="admin" style="padding: 8px; margin-right: 10px;">
|
|
|
+ <input type="password" id="password" placeholder="密码" value="admin123" style="padding: 8px; margin-right: 10px;">
|
|
|
+ <button onclick="testLogin()">登录</button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <h2>步骤 2: 测试API</h2>
|
|
|
+ <div>
|
|
|
+ <button onclick="testGetUsers()">获取用户列表</button>
|
|
|
+ <button onclick="testGetMenus()">获取菜单</button>
|
|
|
+ <button onclick="testGetRoles()">获取角色列表</button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <h2>输出:</h2>
|
|
|
+ <div id="output">等待操作...</div>
|
|
|
+
|
|
|
+ <div id="userTable"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <script>
|
|
|
+ let accessToken = localStorage.getItem('access_token');
|
|
|
+
|
|
|
+ function log(message, type = 'info') {
|
|
|
+ const output = document.getElementById('output');
|
|
|
+ const timestamp = new Date().toLocaleTimeString();
|
|
|
+ const prefix = type === 'error' ? '❌' : type === 'success' ? '✅' : 'ℹ️';
|
|
|
+ output.textContent += `[${timestamp}] ${prefix} ${message}\n`;
|
|
|
+ output.scrollTop = output.scrollHeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ function clearOutput() {
|
|
|
+ document.getElementById('output').textContent = '';
|
|
|
+ document.getElementById('userTable').innerHTML = '';
|
|
|
+ }
|
|
|
+
|
|
|
+ async function testLogin() {
|
|
|
+ clearOutput();
|
|
|
+ log('开始登录测试...');
|
|
|
+
|
|
|
+ const username = document.getElementById('username').value;
|
|
|
+ const password = document.getElementById('password').value;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await fetch('http://localhost:8000/api/v1/auth/login', {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ },
|
|
|
+ body: JSON.stringify({ username, password })
|
|
|
+ });
|
|
|
+
|
|
|
+ log(`状态码: ${response.status}`);
|
|
|
+
|
|
|
+ const data = await response.json();
|
|
|
+ log(`响应: ${JSON.stringify(data, null, 2)}`);
|
|
|
+
|
|
|
+ if (data.code === 0) {
|
|
|
+ accessToken = data.data.access_token;
|
|
|
+ localStorage.setItem('access_token', accessToken);
|
|
|
+ log('登录成功!Token已保存', 'success');
|
|
|
+ log(`Token: ${accessToken.substring(0, 50)}...`);
|
|
|
+ } else {
|
|
|
+ log(`登录失败: ${data.message}`, 'error');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ log(`请求失败: ${error.message}`, 'error');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async function testGetUsers() {
|
|
|
+ if (!accessToken) {
|
|
|
+ log('请先登录!', 'error');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ clearOutput();
|
|
|
+ log('开始获取用户列表...');
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await fetch('http://localhost:8000/api/v1/system/admin/users?page=1&page_size=20', {
|
|
|
+ method: 'GET',
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${accessToken}`,
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ log(`状态码: ${response.status}`);
|
|
|
+
|
|
|
+ const data = await response.json();
|
|
|
+
|
|
|
+ if (data.code === 0) {
|
|
|
+ log(`获取成功!总数: ${data.data.total}`, 'success');
|
|
|
+ log(`用户数据: ${JSON.stringify(data.data, null, 2)}`);
|
|
|
+
|
|
|
+ // 显示用户表格
|
|
|
+ displayUserTable(data.data.items);
|
|
|
+ } else {
|
|
|
+ log(`获取失败: ${data.message}`, 'error');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ log(`请求失败: ${error.message}`, 'error');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async function testGetMenus() {
|
|
|
+ if (!accessToken) {
|
|
|
+ log('请先登录!', 'error');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ clearOutput();
|
|
|
+ log('开始获取菜单...');
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await fetch('http://localhost:8000/api/v1/system/user/menus', {
|
|
|
+ method: 'GET',
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${accessToken}`,
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ log(`状态码: ${response.status}`);
|
|
|
+
|
|
|
+ const data = await response.json();
|
|
|
+
|
|
|
+ if (data.code === 0) {
|
|
|
+ log(`获取成功!菜单数: ${data.data.length}`, 'success');
|
|
|
+ log(`菜单数据: ${JSON.stringify(data.data, null, 2)}`);
|
|
|
+ } else {
|
|
|
+ log(`获取失败: ${data.message}`, 'error');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ log(`请求失败: ${error.message}`, 'error');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async function testGetRoles() {
|
|
|
+ if (!accessToken) {
|
|
|
+ log('请先登录!', 'error');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ clearOutput();
|
|
|
+ log('开始获取角色列表...');
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await fetch('http://localhost:8000/api/v1/system/roles/all', {
|
|
|
+ method: 'GET',
|
|
|
+ headers: {
|
|
|
+ 'Authorization': `Bearer ${accessToken}`,
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ log(`状态码: ${response.status}`);
|
|
|
+
|
|
|
+ const data = await response.json();
|
|
|
+
|
|
|
+ if (data.code === 0) {
|
|
|
+ log(`获取成功!角色数: ${data.data.length}`, 'success');
|
|
|
+ log(`角色数据: ${JSON.stringify(data.data, null, 2)}`);
|
|
|
+ } else {
|
|
|
+ log(`获取失败: ${data.message}`, 'error');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ log(`请求失败: ${error.message}`, 'error');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function displayUserTable(users) {
|
|
|
+ const tableDiv = document.getElementById('userTable');
|
|
|
+
|
|
|
+ let html = '<h2>用户列表</h2><table>';
|
|
|
+ html += '<tr><th>用户名</th><th>邮箱</th><th>手机</th><th>角色</th><th>状态</th><th>管理员</th></tr>';
|
|
|
+
|
|
|
+ users.forEach(user => {
|
|
|
+ html += '<tr>';
|
|
|
+ html += `<td>${user.username}</td>`;
|
|
|
+ html += `<td>${user.email}</td>`;
|
|
|
+ html += `<td>${user.phone || '-'}</td>`;
|
|
|
+ html += `<td>${user.roles || '未分配'}</td>`;
|
|
|
+ html += `<td>${user.is_active ? '激活' : '禁用'}</td>`;
|
|
|
+ html += `<td>${user.is_superuser ? '是' : '否'}</td>`;
|
|
|
+ html += '</tr>';
|
|
|
+ });
|
|
|
+
|
|
|
+ html += '</table>';
|
|
|
+ tableDiv.innerHTML = html;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 页面加载时检查token
|
|
|
+ window.onload = function() {
|
|
|
+ if (accessToken) {
|
|
|
+ log('检测到已保存的Token', 'success');
|
|
|
+ log(`Token: ${accessToken.substring(0, 50)}...`);
|
|
|
+ } else {
|
|
|
+ log('未检测到Token,请先登录');
|
|
|
+ }
|
|
|
+ };
|
|
|
+ </script>
|
|
|
+</body>
|
|
|
+</html>
|