Files
jiangmingzhao-daily-report/test_api.html
jiangmingzhao 9b9ee273fc 初始提交:企业级日报系统完整代码
功能特性:
-  JWT用户认证系统
-  日报CRUD管理
-  三级权限控制
-  多维度搜索过滤
-  统计分析功能
-  评论互动系统
-  响应式Cool Admin界面
-  暗色主题支持

 技术栈:
- 后端:Django 4.2.7 + DRF + SimpleJWT
- 前端:Vue 3 + Element Plus + Pinia
- 数据库:SQLite/PostgreSQL
- 部署:Docker + Nginx

 包含内容:
- 完整的后端API代码
- 现代化前端界面
- 数据库迁移文件
- 部署脚本和文档
- 演示页面和测试工具
2025-09-13 14:35:15 +08:00

378 lines
14 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>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 20px;
background: #f5f7fa;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
border-radius: 8px;
padding: 30px;
box-shadow: 0 2px 12px rgba(0,0,0,0.1);
}
h1 {
color: #303133;
text-align: center;
margin-bottom: 30px;
}
.test-section {
margin-bottom: 30px;
padding: 20px;
border: 1px solid #e4e7ed;
border-radius: 6px;
background: #fafafa;
}
.test-title {
font-size: 18px;
font-weight: 600;
color: #409eff;
margin-bottom: 15px;
}
.test-button {
background: #409eff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
margin-right: 10px;
margin-bottom: 10px;
}
.test-button:hover {
background: #66b1ff;
}
.test-button.success {
background: #67c23a;
}
.test-button.success:hover {
background: #85ce61;
}
.result {
margin-top: 15px;
padding: 15px;
border-radius: 4px;
font-family: monospace;
font-size: 14px;
white-space: pre-wrap;
max-height: 200px;
overflow-y: auto;
}
.result.success {
background: #f0f9ff;
border: 1px solid #b3d8ff;
color: #0066cc;
}
.result.error {
background: #fef0f0;
border: 1px solid #fbc4c4;
color: #f56c6c;
}
.status {
display: inline-block;
padding: 4px 8px;
border-radius: 3px;
font-size: 12px;
font-weight: 600;
margin-left: 10px;
}
.status.online {
background: #67c23a;
color: white;
}
.status.offline {
background: #f56c6c;
color: white;
}
.login-form {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
margin-bottom: 15px;
}
.form-group {
display: flex;
flex-direction: column;
}
.form-group label {
margin-bottom: 5px;
font-weight: 500;
}
.form-group input {
padding: 8px;
border: 1px solid #dcdfe6;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="container">
<h1>🧪 API测试页面</h1>
<!-- 服务状态检查 -->
<div class="test-section">
<div class="test-title">🔍 服务状态检查</div>
<button class="test-button" onclick="checkBackendStatus()">检查后端服务</button>
<button class="test-button" onclick="checkFrontendStatus()">检查前端服务</button>
<div id="statusResult" class="result" style="display: none;"></div>
</div>
<!-- API测试 -->
<div class="test-section">
<div class="test-title">🔐 用户认证测试</div>
<div class="login-form">
<div class="form-group">
<label>用户名:</label>
<input type="text" id="username" value="admin" />
</div>
<div class="form-group">
<label>密码:</label>
<input type="password" id="password" value="admin123456" />
</div>
</div>
<button class="test-button" onclick="testLogin()">测试登录</button>
<button class="test-button success" onclick="testGetProfile()">获取用户信息</button>
<div id="authResult" class="result" style="display: none;"></div>
</div>
<!-- 日报API测试 -->
<div class="test-section">
<div class="test-title">📝 日报API测试</div>
<button class="test-button" onclick="testGetReports()">获取日报列表</button>
<button class="test-button" onclick="testCreateReport()">创建测试日报</button>
<button class="test-button" onclick="testGetStats()">获取统计数据</button>
<div id="reportsResult" class="result" style="display: none;"></div>
</div>
<!-- 快速链接 -->
<div class="test-section">
<div class="test-title">🔗 快速链接</div>
<a href="http://localhost:8000/admin/" target="_blank">
<button class="test-button">Django管理后台</button>
</a>
<a href="http://localhost:8000/api/" target="_blank">
<button class="test-button">API根目录</button>
</a>
<a href="http://localhost:3000" target="_blank">
<button class="test-button success">前端应用</button>
</a>
</div>
</div>
<script>
let authToken = null;
// 显示结果
function showResult(elementId, content, isSuccess = true) {
const element = document.getElementById(elementId);
element.style.display = 'block';
element.className = `result ${isSuccess ? 'success' : 'error'}`;
element.textContent = content;
}
// 检查后端服务状态
async function checkBackendStatus() {
try {
const response = await fetch('http://localhost:8000/api/auth/login/', {
method: 'OPTIONS'
});
showResult('statusResult', '✅ 后端服务运行正常\n状态码: ' + response.status + '\n地址: http://localhost:8000');
} catch (error) {
showResult('statusResult', '❌ 后端服务连接失败\n错误: ' + error.message + '\n\n请确保Django服务器已启动\ncd backend && python manage.py runserver', false);
}
}
// 检查前端服务状态
async function checkFrontendStatus() {
try {
const response = await fetch('http://localhost:3000/', {
method: 'GET',
mode: 'no-cors'
});
showResult('statusResult', '✅ 前端服务运行正常\n地址: http://localhost:3000');
} catch (error) {
showResult('statusResult', '❌ 前端服务连接失败\n错误: ' + error.message + '\n\n请确保Vue服务器已启动\ncd frontend && npm run serve', false);
}
}
// 测试登录
async function testLogin() {
const username = document.getElementById('username').value;
const password = document.getElementById('password').value;
try {
const response = await fetch('http://localhost:8000/api/auth/login/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password })
});
const data = await response.json();
if (response.ok) {
authToken = data.tokens.access;
showResult('authResult',
'✅ 登录成功!\n' +
'用户: ' + data.user.username + '\n' +
'姓名: ' + (data.user.full_name || '未设置') + '\n' +
'权限: ' + (data.user.is_staff ? '管理员' : '普通用户') + '\n' +
'Token: ' + data.tokens.access.substring(0, 50) + '...'
);
} else {
showResult('authResult', '❌ 登录失败\n' + JSON.stringify(data, null, 2), false);
}
} catch (error) {
showResult('authResult', '❌ 登录请求失败\n错误: ' + error.message, false);
}
}
// 测试获取用户信息
async function testGetProfile() {
if (!authToken) {
showResult('authResult', '❌ 请先登录获取Token', false);
return;
}
try {
const response = await fetch('http://localhost:8000/api/auth/profile/', {
headers: {
'Authorization': 'Bearer ' + authToken
}
});
const data = await response.json();
if (response.ok) {
showResult('authResult',
'✅ 获取用户信息成功!\n' +
JSON.stringify(data, null, 2)
);
} else {
showResult('authResult', '❌ 获取用户信息失败\n' + JSON.stringify(data, null, 2), false);
}
} catch (error) {
showResult('authResult', '❌ 请求失败\n错误: ' + error.message, false);
}
}
// 测试获取日报列表
async function testGetReports() {
if (!authToken) {
showResult('reportsResult', '❌ 请先登录获取Token', false);
return;
}
try {
const response = await fetch('http://localhost:8000/api/reports/', {
headers: {
'Authorization': 'Bearer ' + authToken
}
});
const data = await response.json();
if (response.ok) {
showResult('reportsResult',
'✅ 获取日报列表成功!\n' +
'总数: ' + (data.count || 0) + '\n' +
'结果: ' + JSON.stringify(data, null, 2).substring(0, 500) + '...'
);
} else {
showResult('reportsResult', '❌ 获取日报列表失败\n' + JSON.stringify(data, null, 2), false);
}
} catch (error) {
showResult('reportsResult', '❌ 请求失败\n错误: ' + error.message, false);
}
}
// 测试创建日报
async function testCreateReport() {
if (!authToken) {
showResult('reportsResult', '❌ 请先登录获取Token', false);
return;
}
const reportData = {
report_date: new Date().toISOString().split('T')[0],
work_summary: '今天完成了API测试功能的开发包括前端界面和后端接口的测试。',
next_day_plan: '明天将继续优化系统性能,添加更多的测试用例。',
is_draft: false
};
try {
const response = await fetch('http://localhost:8000/api/reports/', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + authToken,
'Content-Type': 'application/json'
},
body: JSON.stringify(reportData)
});
const data = await response.json();
if (response.ok) {
showResult('reportsResult',
'✅ 创建日报成功!\n' +
'ID: ' + data.id + '\n' +
'日期: ' + data.report_date + '\n' +
'状态: ' + (data.is_draft ? '草稿' : '已发布')
);
} else {
showResult('reportsResult', '❌ 创建日报失败\n' + JSON.stringify(data, null, 2), false);
}
} catch (error) {
showResult('reportsResult', '❌ 请求失败\n错误: ' + error.message, false);
}
}
// 测试获取统计数据
async function testGetStats() {
if (!authToken) {
showResult('reportsResult', '❌ 请先登录获取Token', false);
return;
}
try {
const response = await fetch('http://localhost:8000/api/stats/', {
headers: {
'Authorization': 'Bearer ' + authToken
}
});
const data = await response.json();
if (response.ok) {
showResult('reportsResult',
'✅ 获取统计数据成功!\n' +
'总日报数: ' + data.total_reports + '\n' +
'本月日报: ' + data.this_month_reports + '\n' +
'本周日报: ' + data.this_week_reports + '\n' +
'完成率: ' + data.completion_rate + '%'
);
} else {
showResult('reportsResult', '❌ 获取统计数据失败\n' + JSON.stringify(data, null, 2), false);
}
} catch (error) {
showResult('reportsResult', '❌ 请求失败\n错误: ' + error.message, false);
}
}
// 页面加载完成后自动检查服务状态
window.onload = function() {
setTimeout(checkBackendStatus, 1000);
};
</script>
</body>
</html>