数据结构优化
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<div v-if="isOpen" class="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm" @click.self="close">
|
||||
<div class="bg-[#1a1a1a] border border-white/10 rounded-lg shadow-xl w-full max-w-4xl max-h-[90vh] overflow-hidden animate-reveal flex flex-col">
|
||||
<Transition name="modal">
|
||||
<div v-if="isOpen" class="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm" @click.self="close">
|
||||
<div class="bg-[#1a1a1a] border border-white/10 rounded-lg shadow-xl w-full max-w-4xl max-h-[90vh] overflow-hidden flex flex-col">
|
||||
<div class="p-4 border-b border-white/10 flex justify-between items-center shrink-0">
|
||||
<h3 class="text-lg font-serif italic text-white">访问记录 - {{ postTitle }}</h3>
|
||||
<button @click="close" class="text-white/50 hover:text-white">
|
||||
@@ -28,25 +29,20 @@
|
||||
<table class="w-full border-collapse">
|
||||
<thead>
|
||||
<tr class="border-b border-white/10">
|
||||
<th class="text-left py-2 px-3 text-sm font-medium text-white/80">用户ID</th>
|
||||
<th class="text-left py-2 px-3 text-sm font-medium text-white/80">IP地址</th>
|
||||
<th class="text-left py-2 px-3 text-sm font-medium text-white/80">归属地</th>
|
||||
<th class="text-left py-2 px-3 text-sm font-medium text-white/80">访问路径</th>
|
||||
<th class="text-left py-2 px-3 text-sm font-medium text-white/80">状态码</th>
|
||||
<th class="text-left py-2 px-3 text-sm font-medium text-white/80">响应时间</th>
|
||||
<th class="text-left py-2 px-3 text-sm font-medium text-white/80">访问时间</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="log in logs.list" :key="log.id" class="border-b border-white/5 hover:bg-white/5 transition-colors">
|
||||
<td class="py-2 px-3 text-sm text-white/90">
|
||||
<span v-if="log.userId && log.userId > 0" class="text-art-accent">用户 #{{ log.userId }}</span>
|
||||
<span v-else class="text-art-muted">游客</span>
|
||||
</td>
|
||||
<td class="py-2 px-3 text-sm text-white/90 font-mono">{{ log.ip }}</td>
|
||||
<td class="py-2 px-3 text-sm text-white/80">{{ log.region || 'Unknown' }}</td>
|
||||
<td class="py-2 px-3 text-sm text-white/80 font-mono">{{ log.path }}</td>
|
||||
<td class="py-2 px-3 text-sm">
|
||||
<span :class="getStatusClass(log.statusCode)">
|
||||
{{ log.statusCode }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="py-2 px-3 text-sm text-white/80">{{ log.responseTime }}ms</td>
|
||||
<td class="py-2 px-3 text-sm text-white/80">{{ log.createdAt }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -77,12 +73,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { getPostAccessLogs, AccessLog, PaginationResponse } from '../../services/api'
|
||||
import { getPostAccessLogs, PostAccessLog, PaginationResponse } from '../../services/api'
|
||||
import { useToast } from '../../composables/useToast'
|
||||
|
||||
interface Props {
|
||||
@@ -101,7 +98,7 @@ const emit = defineEmits<{
|
||||
|
||||
const toast = useToast()
|
||||
const loading = ref(false)
|
||||
const logs = ref<PaginationResponse<AccessLog>>({
|
||||
const logs = ref<PaginationResponse<PostAccessLog>>({
|
||||
list: [],
|
||||
total: 0,
|
||||
page: 1,
|
||||
@@ -138,16 +135,6 @@ const changePage = (page: number) => {
|
||||
fetchLogs()
|
||||
}
|
||||
|
||||
const getStatusClass = (status: number) => {
|
||||
if (status >= 200 && status < 300) {
|
||||
return 'text-green-400'
|
||||
} else if (status >= 400 && status < 500) {
|
||||
return 'text-yellow-400'
|
||||
} else if (status >= 500) {
|
||||
return 'text-red-400'
|
||||
}
|
||||
return 'text-white/60'
|
||||
}
|
||||
|
||||
watch(() => props.isOpen, (newVal) => {
|
||||
if (newVal && props.postId) {
|
||||
@@ -165,18 +152,24 @@ watch(() => props.postId, () => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.animate-reveal {
|
||||
animation: reveal 0.3s ease-out;
|
||||
/* Modal transition */
|
||||
.modal-enter-active,
|
||||
.modal-leave-active {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes reveal {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
.modal-enter-active .bg-\[#1a1a1a\] {
|
||||
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.modal-enter-from,
|
||||
.modal-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.modal-enter-from .bg-\[#1a1a1a\],
|
||||
.modal-leave-to .bg-\[#1a1a1a\] {
|
||||
transform: translateY(-20px);
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user