Download test.html from CatPtain/web_ppt: direct link, hf CLI and curl.
- Browser
- Download file 23.7 kB
-
https://huggingface.co/spaces/CatPtain/web_ppt/resolve/main/test.html
- Command line
-
hf download hf://spaces/CatPtain/web_ppt/test.html
-
curl -L -o test.html https://huggingface.co/spaces/CatPtain/web_ppt/resolve/main/test.html
23.7 kB
| <html lang="zh-CN"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>PPTist Huggingface - API 测试页面</title> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Microsoft YaHei', Arial, sans-serif; | |
| background: #f5f5f5; | |
| padding: 20px; | |
| line-height: 1.6; | |
| } | |
| .container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| background: white; | |
| padding: 30px; | |
| border-radius: 10px; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); | |
| } | |
| h1 { | |
| color: #333; | |
| text-align: center; | |
| margin-bottom: 30px; | |
| padding-bottom: 15px; | |
| border-bottom: 3px solid #5b9bd5; | |
| } | |
| .section { | |
| margin-bottom: 30px; | |
| padding: 20px; | |
| border: 1px solid #ddd; | |
| border-radius: 8px; | |
| background: #fafafa; | |
| } | |
| .section h2 { | |
| color: #5b9bd5; | |
| margin-bottom: 15px; | |
| font-size: 1.4em; | |
| } | |
| .test-group { | |
| margin-bottom: 20px; | |
| } | |
| .test-item { | |
| display: flex; | |
| align-items: center; | |
| margin: 10px 0; | |
| gap: 15px; | |
| } | |
| .test-button { | |
| background: #5b9bd5; | |
| color: white; | |
| border: none; | |
| padding: 8px 16px; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| min-width: 120px; | |
| font-size: 14px; | |
| } | |
| .test-button:hover { | |
| background: #4a8bc2; | |
| } | |
| .test-button:disabled { | |
| background: #ccc; | |
| cursor: not-allowed; | |
| } | |
| .endpoint-url { | |
| font-family: 'Courier New', monospace; | |
| background: #e8e8e8; | |
| padding: 5px 8px; | |
| border-radius: 3px; | |
| font-size: 12px; | |
| color: #666; | |
| flex: 1; | |
| } | |
| .status { | |
| padding: 4px 8px; | |
| border-radius: 3px; | |
| font-size: 12px; | |
| font-weight: bold; | |
| min-width: 80px; | |
| text-align: center; | |
| } | |
| .status.success { | |
| background: #d4edda; | |
| color: #155724; | |
| } | |
| .status.error { | |
| background: #f8d7da; | |
| color: #721c24; | |
| } | |
| .status.loading { | |
| background: #fff3cd; | |
| color: #856404; | |
| } | |
| .result-area { | |
| margin-top: 20px; | |
| background: white; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| } | |
| .result-content { | |
| padding: 15px; | |
| font-family: 'Courier New', monospace; | |
| font-size: 12px; | |
| white-space: pre-wrap; | |
| word-break: break-all; | |
| } | |
| .auth-section { | |
| background: #e3f2fd; | |
| border-color: #1976d2; | |
| } | |
| .github-section { | |
| background: #f3e5f5; | |
| border-color: #7b1fa2; | |
| } | |
| .ppt-section { | |
| background: #e8f5e8; | |
| border-color: #388e3c; | |
| } | |
| .public-section { | |
| background: #fff3e0; | |
| border-color: #f57c00; | |
| } | |
| .login-form { | |
| display: flex; | |
| gap: 10px; | |
| margin-bottom: 15px; | |
| align-items: center; | |
| } | |
| .login-form input { | |
| padding: 8px 12px; | |
| border: 1px solid #ddd; | |
| border-radius: 4px; | |
| font-size: 14px; | |
| } | |
| .token-display { | |
| font-family: 'Courier New', monospace; | |
| background: #f0f0f0; | |
| padding: 8px; | |
| border-radius: 4px; | |
| font-size: 12px; | |
| margin: 10px 0; | |
| word-break: break-all; | |
| } | |
| .clear-button { | |
| background: #dc3545; | |
| margin-left: 10px; | |
| } | |
| .clear-button:hover { | |
| background: #c82333; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>🚀 PPTist Huggingface Space - API 测试控制台</h1> | |
| <!-- GitHub 连接测试 --> | |
| <div class="section github-section"> | |
| <h2>🔗 GitHub 仓库连接测试</h2> | |
| <div class="test-group"> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testEndpoint('/api/health', 'GET')">健康检查</button> | |
| <span class="endpoint-url">GET /api/health</span> | |
| <span id="health-status" class="status">未测试</span> | |
| </div> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testEndpoint('/api/github/status', 'GET')">GitHub 状态</button> | |
| <span class="endpoint-url">GET /api/github/status</span> | |
| <span id="github-status-status" class="status">未测试</span> | |
| </div> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testEndpoint('/api/github/test', 'GET')">GitHub 连接测试</button> | |
| <span class="endpoint-url">GET /api/github/test</span> | |
| <span id="github-test-status" class="status">未测试</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 认证测试 --> | |
| <div class="section auth-section"> | |
| <h2>🔐 用户认证测试</h2> | |
| <div class="login-form"> | |
| <input type="text" id="username" placeholder="用户名" value="PS01"> | |
| <input type="password" id="password" placeholder="密码" value="admin_cybercity2025"> | |
| <button class="test-button" onclick="testLogin()">登录测试</button> | |
| <button class="test-button clear-button" onclick="clearToken()">清除Token</button> | |
| </div> | |
| <div class="token-display" id="token-display">当前Token: 未登录</div> | |
| <div class="test-group"> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testEndpoint('/api/auth/verify', 'GET', true)">验证Token</button> | |
| <span class="endpoint-url">GET /api/auth/verify</span> | |
| <span id="auth-verify-status" class="status">未测试</span> | |
| </div> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testEndpoint('/api/auth/user', 'GET', true)">获取用户信息</button> | |
| <span class="endpoint-url">GET /api/auth/user</span> | |
| <span id="auth-user-status" class="status">未测试</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- PPT 管理测试 --> | |
| <div class="section ppt-section"> | |
| <h2>📄 PPT 管理测试</h2> | |
| <div class="test-group"> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testEndpoint('/api/ppt/test', 'GET')">PPT 路由测试</button> | |
| <span class="endpoint-url">GET /api/ppt/test</span> | |
| <span id="ppt-test-status" class="status">未测试</span> | |
| </div> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testEndpoint('/api/ppt/list', 'GET', true)">获取PPT列表</button> | |
| <span class="endpoint-url">GET /api/ppt/list</span> | |
| <span id="ppt-list-status" class="status">未测试</span> | |
| </div> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testCreatePPT()">创建PPT</button> | |
| <span class="endpoint-url">POST /api/ppt/create</span> | |
| <span id="ppt-create-status" class="status">未测试</span> | |
| </div> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testSavePPT()">保存PPT</button> | |
| <span class="endpoint-url">POST /api/ppt/save</span> | |
| <span id="ppt-save-status" class="status">未测试</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 公共分享测试 --> | |
| <div class="section public-section"> | |
| <h2>🌐 公共分享测试</h2> | |
| <div class="test-group"> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testGenerateShareLink()">生成分享链接</button> | |
| <span class="endpoint-url">POST /api/public/generate-share-link</span> | |
| <span id="public-generate-status" class="status">未测试</span> | |
| </div> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testEndpoint('/api/public/ppt/PS01/test-ppt-id', 'GET')">获取公共PPT</button> | |
| <span class="endpoint-url">GET /api/public/ppt/:userId/:pptId</span> | |
| <span id="public-ppt-status" class="status">未测试</span> | |
| </div> | |
| <div class="test-item"> | |
| <button class="test-button" onclick="testEndpoint('/api/public/view/PS01/test-ppt-id/0', 'GET')">公开查看页面</button> | |
| <span class="endpoint-url">GET /api/public/view/:userId/:pptId/:slideIndex</span> | |
| <span id="public-view-status" class="status">未测试</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 结果显示区域 --> | |
| <div class="section"> | |
| <h2>📋 测试结果</h2> | |
| <div class="result-area"> | |
| <div class="result-content" id="result-content">点击上方按钮开始测试...</div> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| let currentToken = localStorage.getItem('test_token') || ''; | |
| let testPptId = ''; | |
| // 更新Token显示 | |
| function updateTokenDisplay() { | |
| const display = document.getElementById('token-display'); | |
| if (currentToken) { | |
| display.textContent = `当前Token: ${currentToken.substring(0, 20)}...`; | |
| } else { | |
| display.textContent = '当前Token: 未登录'; | |
| } | |
| } | |
| // 清除Token | |
| function clearToken() { | |
| currentToken = ''; | |
| localStorage.removeItem('test_token'); | |
| updateTokenDisplay(); | |
| logResult('Token已清除'); | |
| } | |
| // 初始化显示 | |
| updateTokenDisplay(); | |
| // 记录结果 | |
| function logResult(message) { | |
| const resultContent = document.getElementById('result-content'); | |
| const timestamp = new Date().toLocaleTimeString(); | |
| resultContent.textContent += `[${timestamp}] ${message}\n`; | |
| resultContent.scrollTop = resultContent.scrollHeight; | |
| } | |
| // 更新状态 | |
| function updateStatus(elementId, status, message = '') { | |
| const element = document.getElementById(elementId); | |
| element.className = `status ${status}`; | |
| element.textContent = status === 'success' ? '成功' : status === 'error' ? '失败' : status === 'loading' ? '测试中...' : '未测试'; | |
| if (message) { | |
| logResult(`${elementId}: ${message}`); | |
| } | |
| } | |
| // 登录测试 | |
| async function testLogin() { | |
| const username = document.getElementById('username').value; | |
| const password = document.getElementById('password').value; | |
| if (!username || !password) { | |
| alert('请输入用户名和密码'); | |
| return; | |
| } | |
| try { | |
| logResult(`尝试登录用户: ${username}`); | |
| const response = await fetch('/api/auth/login', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ username, password }), | |
| }); | |
| const data = await response.json(); | |
| if (response.ok && data.token) { | |
| currentToken = data.token; | |
| localStorage.setItem('test_token', currentToken); | |
| updateTokenDisplay(); | |
| logResult(`登录成功! 用户: ${data.user.username}, 角色: ${data.user.role}`); | |
| updateStatus('login-status', 'success'); | |
| } else { | |
| logResult(`登录失败: ${data.error || '未知错误'}`); | |
| updateStatus('login-status', 'error'); | |
| } | |
| } catch (error) { | |
| logResult(`登录请求失败: ${error.message}`); | |
| updateStatus('login-status', 'error'); | |
| } | |
| } | |
| // 通用测试端点 | |
| async function testEndpoint(url, method = 'GET', requireAuth = false, body = null) { | |
| // 修复状态ID生成逻辑 | |
| let statusId; | |
| if (url === '/api/health') { | |
| statusId = 'health-status'; | |
| } else if (url === '/api/github/status') { | |
| statusId = 'github-status-status'; | |
| } else if (url === '/api/github/test') { | |
| statusId = 'github-test-status'; | |
| } else if (url === '/api/auth/verify') { | |
| statusId = 'auth-verify-status'; | |
| } else if (url === '/api/auth/user') { | |
| statusId = 'auth-user-status'; | |
| } else if (url === '/api/ppt/test') { | |
| statusId = 'ppt-test-status'; | |
| } else if (url === '/api/ppt/list') { | |
| statusId = 'ppt-list-status'; | |
| } else if (url.includes('/api/public/ppt/')) { | |
| statusId = 'public-ppt-status'; | |
| } else if (url.includes('/api/public/view/')) { | |
| statusId = 'public-view-status'; | |
| } else { | |
| statusId = url.replace(/[^a-zA-Z0-9]/g, '-') + '-status'; | |
| } | |
| try { | |
| updateStatus(statusId, 'loading'); | |
| logResult(`测试端点: ${method} ${url}`); | |
| const headers = { | |
| 'Content-Type': 'application/json', | |
| }; | |
| if (requireAuth && currentToken) { | |
| headers.Authorization = `Bearer ${currentToken}`; | |
| } else if (requireAuth && !currentToken) { | |
| logResult(`错误: 需要登录才能访问 ${url}`); | |
| updateStatus(statusId, 'error'); | |
| return; | |
| } | |
| const options = { | |
| method, | |
| headers, | |
| }; | |
| if (body) { | |
| options.body = JSON.stringify(body); | |
| } | |
| const response = await fetch(url, options); | |
| const data = await response.text(); | |
| let jsonData; | |
| try { | |
| jsonData = JSON.parse(data); | |
| } catch { | |
| jsonData = data; | |
| } | |
| if (response.ok) { | |
| logResult(`✅ ${method} ${url} - 状态: ${response.status}`); | |
| logResult(`响应: ${JSON.stringify(jsonData, null, 2)}`); | |
| updateStatus(statusId, 'success'); | |
| return jsonData; | |
| } else { | |
| logResult(`❌ ${method} ${url} - 状态: ${response.status}`); | |
| logResult(`错误: ${JSON.stringify(jsonData, null, 2)}`); | |
| updateStatus(statusId, 'error'); | |
| } | |
| } catch (error) { | |
| logResult(`❌ ${method} ${url} - 网络错误: ${error.message}`); | |
| updateStatus(statusId, 'error'); | |
| } | |
| } | |
| // 创建PPT测试 | |
| async function testCreatePPT() { | |
| if (!currentToken) { | |
| alert('请先登录'); | |
| return; | |
| } | |
| const title = `测试PPT - ${new Date().toLocaleString()}`; | |
| const body = { title }; | |
| try { | |
| updateStatus('ppt-create-status', 'loading'); | |
| logResult(`创建PPT: ${title}`); | |
| const response = await fetch('/api/ppt/create', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'Authorization': `Bearer ${currentToken}`, | |
| }, | |
| body: JSON.stringify(body), | |
| }); | |
| const data = await response.json(); | |
| if (response.ok && data.pptId) { | |
| testPptId = data.pptId; | |
| logResult(`✅ PPT创建成功! ID: ${testPptId}`); | |
| logResult(`PPT数据: ${JSON.stringify(data, null, 2)}`); | |
| updateStatus('ppt-create-status', 'success'); | |
| } else { | |
| logResult(`❌ PPT创建失败: ${data.error || '未知错误'}`); | |
| updateStatus('ppt-create-status', 'error'); | |
| } | |
| } catch (error) { | |
| logResult(`❌ PPT创建请求失败: ${error.message}`); | |
| updateStatus('ppt-create-status', 'error'); | |
| } | |
| } | |
| // 保存PPT测试 | |
| async function testSavePPT() { | |
| if (!currentToken) { | |
| alert('请先登录'); | |
| return; | |
| } | |
| if (!testPptId) { | |
| alert('请先创建一个PPT'); | |
| return; | |
| } | |
| const pptData = { | |
| pptId: testPptId, | |
| title: '测试PPT - 已保存', | |
| slides: [ | |
| { | |
| id: 'slide-1', | |
| elements: [ | |
| { | |
| type: 'text', | |
| id: 'text-1', | |
| left: 100, | |
| top: 100, | |
| width: 300, | |
| height: 50, | |
| content: '这是一个测试文本', | |
| fontSize: 24, | |
| defaultColor: '#333333' | |
| } | |
| ], | |
| background: { type: 'solid', color: '#ffffff' } | |
| } | |
| ], | |
| theme: { | |
| backgroundColor: '#ffffff', | |
| themeColor: '#5b9bd5' | |
| } | |
| }; | |
| try { | |
| updateStatus('ppt-save-status', 'loading'); | |
| logResult(`保存PPT: ${testPptId}`); | |
| const response = await fetch('/api/ppt/save', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'Authorization': `Bearer ${currentToken}`, | |
| }, | |
| body: JSON.stringify(pptData), | |
| }); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| logResult(`✅ PPT保存成功!`); | |
| logResult(`响应: ${JSON.stringify(data, null, 2)}`); | |
| updateStatus('ppt-save-status', 'success'); | |
| } else { | |
| logResult(`❌ PPT保存失败: ${data.error || '未知错误'}`); | |
| updateStatus('ppt-save-status', 'error'); | |
| } | |
| } catch (error) { | |
| logResult(`❌ PPT保存请求失败: ${error.message}`); | |
| updateStatus('ppt-save-status', 'error'); | |
| } | |
| } | |
| // 生成分享链接测试 | |
| async function testGenerateShareLink() { | |
| if (!testPptId) { | |
| alert('请先创建并保存一个PPT'); | |
| return; | |
| } | |
| const body = { | |
| userId: 'PS01', | |
| pptId: testPptId, | |
| slideIndex: 0 | |
| }; | |
| try { | |
| updateStatus('public-generate-status', 'loading'); | |
| logResult(`生成分享链接 - PPT ID: ${testPptId}`); | |
| const response = await fetch('/api/public/generate-share-link', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify(body), | |
| }); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| logResult(`✅ 分享链接生成成功!`); | |
| logResult(`单页链接: ${data.slideUrl}`); | |
| logResult(`完整PPT链接: ${data.pptUrl}`); | |
| logResult(`前端查看链接: ${data.viewUrl}`); | |
| updateStatus('public-generate-status', 'success'); | |
| } else { | |
| logResult(`❌ 分享链接生成失败: ${data.error || '未知错误'}`); | |
| updateStatus('public-generate-status', 'error'); | |
| } | |
| } catch (error) { | |
| logResult(`❌ 分享链接生成请求失败: ${error.message}`); | |
| updateStatus('public-generate-status', 'error'); | |
| } | |
| } | |
| // 页面加载时运行初始测试 | |
| window.addEventListener('load', () => { | |
| logResult('🚀 PPTist API 测试控制台已就绪'); | |
| logResult('📌 建议测试顺序:'); | |
| logResult(' 1. 先测试健康检查和GitHub连接'); | |
| logResult(' 2. 进行用户登录测试'); | |
| logResult(' 3. 测试PPT管理功能'); | |
| logResult(' 4. 测试公共分享功能'); | |
| logResult(''); | |
| }); | |
| </script> | |
| </body> | |
| </html> |