Compare commits
3 Commits
d908fe776f
...
4cc8379d97
Author | SHA1 | Date |
---|---|---|
|
4cc8379d97 | 1 week ago |
|
cceb30aaba | 1 week ago |
|
a3fc5c4d4f | 1 week ago |
5 changed files with 775 additions and 195 deletions
@ -0,0 +1,548 @@
@@ -0,0 +1,548 @@
|
||||
<template> |
||||
<div class="role-api-test"> |
||||
<div class="page-header"> |
||||
<h2>角色管理API测试</h2> |
||||
<div class="header-actions"> |
||||
<button |
||||
class="btn btn-secondary" |
||||
@click="toggleTestMode" |
||||
:title="testMode ? '当前为测试模式(无需认证)' : '当前为正式模式(需要认证)'" |
||||
> |
||||
<i class="fas fa-flask"></i> |
||||
{{ testMode ? '测试模式' : '正式模式' }} |
||||
</button> |
||||
<button class="btn btn-primary" @click="runAllTests"> |
||||
<i class="fas fa-play"></i> 运行所有测试 |
||||
</button> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="test-content"> |
||||
<!-- API配置信息 --> |
||||
<div class="test-section"> |
||||
<h3>API配置信息</h3> |
||||
<div class="config-info"> |
||||
<div class="config-item"> |
||||
<label>API基础地址:</label> |
||||
<span>{{ apiBaseUrl }}</span> |
||||
</div> |
||||
<div class="config-item"> |
||||
<label>当前模式:</label> |
||||
<span :class="testMode ? 'test-mode' : 'prod-mode'"> |
||||
{{ testMode ? '测试模式' : '正式模式' }} |
||||
</span> |
||||
</div> |
||||
<div class="config-item"> |
||||
<label>API路径:</label> |
||||
<span>{{ currentApiPath }}</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<!-- 测试结果 --> |
||||
<div class="test-section"> |
||||
<h3>测试结果</h3> |
||||
<div class="test-results"> |
||||
<div |
||||
v-for="(result, index) in testResults" |
||||
:key="index" |
||||
class="test-result-item" |
||||
:class="result.status" |
||||
> |
||||
<div class="test-header"> |
||||
<span class="test-name">{{ result.name }}</span> |
||||
<span class="test-status">{{ getStatusText(result.status) }}</span> |
||||
</div> |
||||
<div v-if="result.message" class="test-message"> |
||||
{{ result.message }} |
||||
</div> |
||||
<div v-if="result.data" class="test-data"> |
||||
<pre>{{ JSON.stringify(result.data, null, 2) }}</pre> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<!-- 手动测试 --> |
||||
<div class="test-section"> |
||||
<h3>手动测试</h3> |
||||
<div class="manual-tests"> |
||||
<div class="test-group"> |
||||
<h4>获取角色列表</h4> |
||||
<button @click="testGetRoles" :disabled="testing"> |
||||
{{ testing ? '测试中...' : '测试获取角色列表' }} |
||||
</button> |
||||
</div> |
||||
|
||||
<div class="test-group"> |
||||
<h4>创建角色</h4> |
||||
<div class="form-group"> |
||||
<label>角色名称:</label> |
||||
<input v-model="testRole.name" type="text" placeholder="测试角色" /> |
||||
</div> |
||||
<div class="form-group"> |
||||
<label>角色代码:</label> |
||||
<input v-model="testRole.code" type="text" placeholder="TEST_ROLE" /> |
||||
</div> |
||||
<div class="form-group"> |
||||
<label>描述:</label> |
||||
<input v-model="testRole.description" type="text" placeholder="测试角色描述" /> |
||||
</div> |
||||
<button @click="testCreateRole" :disabled="testing"> |
||||
{{ testing ? '测试中...' : '测试创建角色' }} |
||||
</button> |
||||
</div> |
||||
|
||||
<div class="test-group"> |
||||
<h4>更新角色</h4> |
||||
<div class="form-group"> |
||||
<label>角色ID:</label> |
||||
<input v-model="updateRoleId" type="number" placeholder="输入角色ID" /> |
||||
</div> |
||||
<button @click="testUpdateRole" :disabled="testing || !updateRoleId"> |
||||
{{ testing ? '测试中...' : '测试更新角色' }} |
||||
</button> |
||||
</div> |
||||
|
||||
<div class="test-group"> |
||||
<h4>删除角色</h4> |
||||
<div class="form-group"> |
||||
<label>角色ID:</label> |
||||
<input v-model="deleteRoleId" type="number" placeholder="输入角色ID" /> |
||||
</div> |
||||
<button @click="testDeleteRole" :disabled="testing || !deleteRoleId"> |
||||
{{ testing ? '测试中...' : '测试删除角色' }} |
||||
</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { ref, reactive, computed, onMounted } from 'vue' |
||||
import { roleService } from '../services/roleService.js' |
||||
import { getFinalConfig } from '../../../../config/app.config.js' |
||||
|
||||
export default { |
||||
name: 'RoleApiTest', |
||||
setup() { |
||||
const testing = ref(false) |
||||
const testMode = ref(false) |
||||
const testResults = ref([]) |
||||
|
||||
const updateRoleId = ref('') |
||||
const deleteRoleId = ref('') |
||||
|
||||
const testRole = reactive({ |
||||
name: '测试角色', |
||||
code: 'TEST_ROLE', |
||||
description: '这是一个测试角色' |
||||
}) |
||||
|
||||
const apiBaseUrl = computed(() => getFinalConfig().apiBaseUrl) |
||||
const currentApiPath = computed(() => testMode.value ? '/auth/roles/test' : '/auth/roles') |
||||
|
||||
// 切换测试模式 |
||||
const toggleTestMode = () => { |
||||
testMode.value = roleService.toggleTestMode() |
||||
addTestResult('模式切换', 'success', `已切换到${testMode.value ? '测试' : '正式'}模式`) |
||||
} |
||||
|
||||
// 添加测试结果 |
||||
const addTestResult = (name, status, message, data = null) => { |
||||
testResults.value.unshift({ |
||||
name, |
||||
status, |
||||
message, |
||||
data, |
||||
timestamp: new Date().toLocaleString() |
||||
}) |
||||
} |
||||
|
||||
// 获取状态文本 |
||||
const getStatusText = (status) => { |
||||
const statusMap = { |
||||
'success': '成功', |
||||
'error': '失败', |
||||
'warning': '警告' |
||||
} |
||||
return statusMap[status] || status |
||||
} |
||||
|
||||
// 测试获取角色列表 |
||||
const testGetRoles = async () => { |
||||
testing.value = true |
||||
try { |
||||
const response = await roleService.getRoles(1, 10) |
||||
if (response.code === 200) { |
||||
addTestResult('获取角色列表', 'success', '获取角色列表成功', response.data) |
||||
} else { |
||||
addTestResult('获取角色列表', 'error', `获取失败: ${response.message}`, response) |
||||
} |
||||
} catch (error) { |
||||
addTestResult('获取角色列表', 'error', `请求失败: ${error.message || error.error}`, error) |
||||
} finally { |
||||
testing.value = false |
||||
} |
||||
} |
||||
|
||||
// 测试创建角色 |
||||
const testCreateRole = async () => { |
||||
testing.value = true |
||||
try { |
||||
const response = await roleService.createRole(testRole) |
||||
if (response.code === 200) { |
||||
addTestResult('创建角色', 'success', '创建角色成功', response.data) |
||||
} else { |
||||
addTestResult('创建角色', 'error', `创建失败: ${response.message}`, response) |
||||
} |
||||
} catch (error) { |
||||
addTestResult('创建角色', 'error', `请求失败: ${error.message || error.error}`, error) |
||||
} finally { |
||||
testing.value = false |
||||
} |
||||
} |
||||
|
||||
// 测试更新角色 |
||||
const testUpdateRole = async () => { |
||||
if (!updateRoleId.value) { |
||||
addTestResult('更新角色', 'warning', '请输入角色ID') |
||||
return |
||||
} |
||||
|
||||
testing.value = true |
||||
try { |
||||
const updateData = { |
||||
name: `${testRole.name}_更新`, |
||||
code: `${testRole.code}_UPDATED`, |
||||
description: `${testRole.description}_更新` |
||||
} |
||||
const response = await roleService.updateRole(updateRoleId.value, updateData) |
||||
if (response.code === 200) { |
||||
addTestResult('更新角色', 'success', '更新角色成功', response.data) |
||||
} else { |
||||
addTestResult('更新角色', 'error', `更新失败: ${response.message}`, response) |
||||
} |
||||
} catch (error) { |
||||
addTestResult('更新角色', 'error', `请求失败: ${error.message || error.error}`, error) |
||||
} finally { |
||||
testing.value = false |
||||
} |
||||
} |
||||
|
||||
// 测试删除角色 |
||||
const testDeleteRole = async () => { |
||||
if (!deleteRoleId.value) { |
||||
addTestResult('删除角色', 'warning', '请输入角色ID') |
||||
return |
||||
} |
||||
|
||||
testing.value = true |
||||
try { |
||||
const response = await roleService.deleteRole(deleteRoleId.value) |
||||
if (response.code === 200) { |
||||
addTestResult('删除角色', 'success', '删除角色成功', response.data) |
||||
} else { |
||||
addTestResult('删除角色', 'error', `删除失败: ${response.message}`, response) |
||||
} |
||||
} catch (error) { |
||||
addTestResult('删除角色', 'error', `请求失败: ${error.message || error.error}`, error) |
||||
} finally { |
||||
testing.value = false |
||||
} |
||||
} |
||||
|
||||
// 运行所有测试 |
||||
const runAllTests = async () => { |
||||
addTestResult('测试开始', 'success', '开始运行所有API测试') |
||||
|
||||
await testGetRoles() |
||||
await new Promise(resolve => setTimeout(resolve, 1000)) // 等待1秒 |
||||
await testCreateRole() |
||||
await new Promise(resolve => setTimeout(resolve, 1000)) // 等待1秒 |
||||
|
||||
addTestResult('测试完成', 'success', '所有API测试已完成') |
||||
} |
||||
|
||||
onMounted(() => { |
||||
testMode.value = roleService.getTestModeStatus() |
||||
addTestResult('页面加载', 'success', '角色管理API测试页面已加载') |
||||
}) |
||||
|
||||
return { |
||||
testing, |
||||
testMode, |
||||
testResults, |
||||
updateRoleId, |
||||
deleteRoleId, |
||||
testRole, |
||||
apiBaseUrl, |
||||
currentApiPath, |
||||
toggleTestMode, |
||||
testGetRoles, |
||||
testCreateRole, |
||||
testUpdateRole, |
||||
testDeleteRole, |
||||
runAllTests, |
||||
getStatusText |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.role-api-test { |
||||
padding: 20px; |
||||
height: 100%; |
||||
overflow-y: auto; |
||||
} |
||||
|
||||
.page-header { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
margin-bottom: 20px; |
||||
} |
||||
|
||||
.page-header h2 { |
||||
margin: 0; |
||||
color: var(--text-primary); |
||||
} |
||||
|
||||
.header-actions { |
||||
display: flex; |
||||
gap: 12px; |
||||
align-items: center; |
||||
} |
||||
|
||||
.test-content { |
||||
max-width: 1200px; |
||||
} |
||||
|
||||
.test-section { |
||||
background: var(--card-bg); |
||||
border-radius: 8px; |
||||
padding: 24px; |
||||
margin-bottom: 24px; |
||||
box-shadow: 0 2px 8px var(--shadow-color); |
||||
} |
||||
|
||||
.test-section h3 { |
||||
margin: 0 0 20px 0; |
||||
color: var(--text-primary); |
||||
font-size: 18px; |
||||
border-bottom: 2px solid var(--border-color); |
||||
padding-bottom: 8px; |
||||
} |
||||
|
||||
.config-info { |
||||
display: grid; |
||||
gap: 12px; |
||||
} |
||||
|
||||
.config-item { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
padding: 12px; |
||||
background: var(--bg-secondary); |
||||
border-radius: 4px; |
||||
} |
||||
|
||||
.config-item label { |
||||
font-weight: 500; |
||||
color: var(--text-primary); |
||||
} |
||||
|
||||
.config-item span { |
||||
color: var(--text-secondary); |
||||
font-family: monospace; |
||||
} |
||||
|
||||
.test-mode { |
||||
color: #ff9800 !important; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.prod-mode { |
||||
color: #4caf50 !important; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.test-results { |
||||
max-height: 400px; |
||||
overflow-y: auto; |
||||
} |
||||
|
||||
.test-result-item { |
||||
margin-bottom: 16px; |
||||
padding: 16px; |
||||
border-radius: 6px; |
||||
border-left: 4px solid; |
||||
} |
||||
|
||||
.test-result-item.success { |
||||
background: rgba(76, 175, 80, 0.1); |
||||
border-left-color: #4caf50; |
||||
} |
||||
|
||||
.test-result-item.error { |
||||
background: rgba(244, 67, 54, 0.1); |
||||
border-left-color: #f44336; |
||||
} |
||||
|
||||
.test-result-item.warning { |
||||
background: rgba(255, 152, 0, 0.1); |
||||
border-left-color: #ff9800; |
||||
} |
||||
|
||||
.test-header { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
margin-bottom: 8px; |
||||
} |
||||
|
||||
.test-name { |
||||
font-weight: 500; |
||||
color: var(--text-primary); |
||||
} |
||||
|
||||
.test-status { |
||||
font-size: 12px; |
||||
padding: 4px 8px; |
||||
border-radius: 4px; |
||||
font-weight: 500; |
||||
} |
||||
|
||||
.test-result-item.success .test-status { |
||||
background: #4caf50; |
||||
color: white; |
||||
} |
||||
|
||||
.test-result-item.error .test-status { |
||||
background: #f44336; |
||||
color: white; |
||||
} |
||||
|
||||
.test-result-item.warning .test-status { |
||||
background: #ff9800; |
||||
color: white; |
||||
} |
||||
|
||||
.test-message { |
||||
color: var(--text-secondary); |
||||
margin-bottom: 8px; |
||||
} |
||||
|
||||
.test-data { |
||||
background: var(--bg-secondary); |
||||
padding: 12px; |
||||
border-radius: 4px; |
||||
overflow-x: auto; |
||||
} |
||||
|
||||
.test-data pre { |
||||
margin: 0; |
||||
font-size: 12px; |
||||
color: var(--text-secondary); |
||||
} |
||||
|
||||
.manual-tests { |
||||
display: grid; |
||||
gap: 24px; |
||||
} |
||||
|
||||
.test-group { |
||||
padding: 16px; |
||||
background: var(--bg-secondary); |
||||
border-radius: 6px; |
||||
} |
||||
|
||||
.test-group h4 { |
||||
margin: 0 0 16px 0; |
||||
color: var(--text-primary); |
||||
} |
||||
|
||||
.form-group { |
||||
margin-bottom: 12px; |
||||
} |
||||
|
||||
.form-group label { |
||||
display: block; |
||||
margin-bottom: 4px; |
||||
font-weight: 500; |
||||
color: var(--text-primary); |
||||
} |
||||
|
||||
.form-group input { |
||||
width: 100%; |
||||
padding: 8px 12px; |
||||
border: 1px solid var(--border-color); |
||||
border-radius: 4px; |
||||
background: var(--input-bg); |
||||
color: var(--input-text); |
||||
box-sizing: border-box; |
||||
} |
||||
|
||||
.btn { |
||||
padding: 8px 16px; |
||||
border: none; |
||||
border-radius: 4px; |
||||
cursor: pointer; |
||||
font-size: 14px; |
||||
display: inline-flex; |
||||
align-items: center; |
||||
gap: 6px; |
||||
transition: all 0.2s; |
||||
} |
||||
|
||||
.btn-primary { |
||||
background: var(--accent-color); |
||||
color: white; |
||||
} |
||||
|
||||
.btn-primary:hover { |
||||
background: var(--accent-hover); |
||||
} |
||||
|
||||
.btn-secondary { |
||||
background: #757575; |
||||
color: white; |
||||
} |
||||
|
||||
.btn-secondary:hover { |
||||
background: #616161; |
||||
} |
||||
|
||||
.btn:hover { |
||||
opacity: 0.9; |
||||
} |
||||
|
||||
.btn:disabled { |
||||
opacity: 0.5; |
||||
cursor: not-allowed; |
||||
} |
||||
|
||||
button { |
||||
background: var(--accent-color); |
||||
color: white; |
||||
border: none; |
||||
padding: 8px 16px; |
||||
border-radius: 4px; |
||||
cursor: pointer; |
||||
font-size: 14px; |
||||
transition: all 0.2s; |
||||
} |
||||
|
||||
button:hover:not(:disabled) { |
||||
background: var(--accent-hover); |
||||
} |
||||
|
||||
button:disabled { |
||||
opacity: 0.5; |
||||
cursor: not-allowed; |
||||
} |
||||
</style> |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 |
Binary file not shown.
Loading…
Reference in new issue