This commit is contained in:
2025-03-18 07:43:46 +08:00
commit d2e93a2736
26 changed files with 918 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
<template>
<div class="blacklist">
<h2>黑名单管理</h2>
<div v-if="blacklist.length > 0">
<ul>
<li v-for="item in blacklist" :key="item.id">
{{ item.target }} - {{ item.type }}
<button @click="removeFromBlacklist(item.id)">移除</button>
</li>
</ul>
</div>
<div>
<input v-model="newTarget" placeholder="输入IP或用户名">
<button @click="addToBlacklist">加入黑名单</button>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const blacklist = ref([])
const newTarget = ref('')
const fetchBlacklist = async () => {
const response = await axios.get('/api/admin/blacklist')
blacklist.value = response.data
}
const addToBlacklist = async () => {
await axios.post('/api/admin/blacklist', { target: newTarget.value })
newTarget.value = ''
await fetchBlacklist()
}
const removeFromBlacklist = async (id) => {
await axios.delete(`/api/admin/blacklist/${id}`)
await fetchBlacklist()
}
onMounted(fetchBlacklist)
</script>

View File

@@ -0,0 +1,139 @@
<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>

View File

@@ -0,0 +1,32 @@
<template>
<div class="dashboard">
<h2>用户面板</h2>
<div v-if="requests.length > 0">
<h3>我的请求</h3>
<ul>
<li v-for="req in requests" :key="req.id">
{{ req.ip }} - {{ req.status }}
</li>
</ul>
</div>
<button @click="requestNewIP">申请新IP</button>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useRequestsStore } from '../stores/requests'
const requestsStore = useRequestsStore()
const requests = ref([])
const requestNewIP = async () => {
await axios.post('/api/user/request')
await requestsStore.fetchApprovedRequests()
}
onMounted(async () => {
await requestsStore.fetchApprovedRequests()
requests.value = requestsStore.approvedRequests
})
</script>

View File

@@ -0,0 +1,26 @@
<template>
<div class="request-form">
<h3>申请新IP</h3>
<form @submit.prevent="submitRequest">
<CfTurnstile @verify="setToken" />
<button type="submit" :disabled="!token">提交申请</button>
</form>
</div>
</template>
<script setup>
import { ref } from 'vue'
import axios from 'axios'
import CfTurnstile from '../components/CfTurnstile.vue'
const token = ref('')
const setToken = (newToken) => {
token.value = newToken
}
const submitRequest = async () => {
await axios.post('/api/user/request', { token: token.value })
alert('申请已提交')
}
</script>