139 lines
2.9 KiB
Vue
139 lines
2.9 KiB
Vue
<template>
|
|
<div class="admin-dashboard">
|
|
<h2>管理员面板</h2>
|
|
<div v-if="pendingRequests.length > 0">
|
|
<h3>待审批请求</h3>
|
|
<table class="requests-table">
|
|
<thead>
|
|
<tr>
|
|
<th>用户</th>
|
|
<th>IP 地址</th>
|
|
<th>申请时间</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="req in pendingRequests" :key="req.id">
|
|
<td>{{ req.username }}</td>
|
|
<td>{{ req.ip }}</td>
|
|
<td>{{ formatDate(req.created_at) }}</td>
|
|
<td>
|
|
<button @click="approveRequest(req.id)" class="approve-btn">批准</button>
|
|
<button @click="rejectRequest(req.id)" class="reject-btn">拒绝</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div v-else>
|
|
<p>没有待审批的请求。</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted } from 'vue'
|
|
import axios from 'axios'
|
|
|
|
// 待审批请求列表
|
|
const pendingRequests = ref([])
|
|
|
|
// 获取待审批请求
|
|
const fetchPendingRequests = async () => {
|
|
try {
|
|
const response = await axios.get('/api/admin/requests')
|
|
pendingRequests.value = response.data
|
|
} catch (error) {
|
|
console.error('获取待审批请求失败:', error)
|
|
}
|
|
}
|
|
|
|
// 批准请求
|
|
const approveRequest = async (requestId) => {
|
|
try {
|
|
await axios.post('/api/admin/approve', { request_id: requestId })
|
|
await fetchPendingRequests()
|
|
alert('请求已批准')
|
|
} catch (error) {
|
|
console.error('批准请求失败:', error)
|
|
alert('操作失败,请重试')
|
|
}
|
|
}
|
|
|
|
// 拒绝请求
|
|
const rejectRequest = async (requestId) => {
|
|
try {
|
|
await axios.post('/api/admin/reject', { request_id: requestId })
|
|
await fetchPendingRequests()
|
|
alert('请求已拒绝')
|
|
} catch (error) {
|
|
console.error('拒绝请求失败:', error)
|
|
alert('操作失败,请重试')
|
|
}
|
|
}
|
|
|
|
// 格式化日期
|
|
const formatDate = (dateString) => {
|
|
return new Date(dateString).toLocaleString()
|
|
}
|
|
|
|
// 组件加载时获取数据
|
|
onMounted(fetchPendingRequests)
|
|
</script>
|
|
|
|
<style scoped>
|
|
.admin-dashboard {
|
|
padding: 20px;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.requests-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.requests-table th,
|
|
.requests-table td {
|
|
padding: 12px;
|
|
border: 1px solid #ddd;
|
|
text-align: left;
|
|
}
|
|
|
|
.requests-table th {
|
|
background-color: #f5f5f5;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.requests-table tr:hover {
|
|
background-color: #f9f9f9;
|
|
}
|
|
|
|
.approve-btn {
|
|
background-color: #4caf50;
|
|
color: white;
|
|
border: none;
|
|
padding: 8px 12px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.approve-btn:hover {
|
|
background-color: #45a049;
|
|
}
|
|
|
|
.reject-btn {
|
|
background-color: #f44336;
|
|
color: white;
|
|
border: none;
|
|
padding: 8px 12px;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.reject-btn:hover {
|
|
background-color: #e53935;
|
|
}
|
|
</style> |