This commit is contained in:
2025-12-06 16:46:48 +08:00
parent 6269482a43
commit 8d1899dd69

View File

@@ -13,9 +13,49 @@
<p class="text-red-600 mb-4">{{ error }}</p> <p class="text-red-600 mb-4">{{ error }}</p>
<el-button @click="loadSystemStatistics" class="mt-4">重试</el-button> <el-button @click="loadSystemStatistics" class="mt-4">重试</el-button>
</div> </div>
<!-- 最近API调用记录 -->
<div v-if="!loading && !error" class="mb-3">
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-2">
<div class="flex items-center justify-end mb-1">
<el-icon
:class="{ 'animate-spin': recentApiCallsLoading }"
class="text-gray-400 cursor-pointer hover:text-gray-600"
@click="loadRecentApiCalls"
size="12"
>
<Refresh />
</el-icon>
</div>
<div v-if="recentApiCallsLoading && recentApiCalls.length === 0" class="text-center py-1">
<el-icon size="14" class="animate-spin text-gray-400">
<Loading />
</el-icon>
<p class="text-sm text-gray-500 mt-1">加载中...</p>
</div>
<div v-else-if="recentApiCalls.length === 0" class="text-sm text-gray-500 py-1 text-center">
暂无成功调用记录
</div>
<div v-else class="flex flex-col gap-1.5 max-h-32 overflow-y-auto">
<div
v-for="(item, index) in recentApiCalls"
:key="item.id || index"
class="text-sm border border-gray-200 rounded px-2 py-1 hover:bg-gray-50 transition-colors text-center"
>
<span class="text-gray-900 font-medium">{{ getCompanyName(item) }}</span>
<span class="text-gray-400 mx-1">·</span>
<span class="text-blue-600">{{ getProductName(item) }}</span>
<span class="text-gray-400 mx-1">·</span>
<span class="text-gray-500">{{ formatRecentTime(item.created_at || item.start_at) }}</span>
</div>
</div>
</div>
</div>
<!-- 统计内容 --> <!-- 统计内容 -->
<div v-else-if="systemStats" class="space-y-4"> <div v-if="systemStats" class="space-y-4">
<!-- 概览卡片 --> <!-- 概览卡片 -->
<div class="grid grid-cols-2 lg:grid-cols-5 gap-3 mb-4"> <div class="grid grid-cols-2 lg:grid-cols-5 gap-3 mb-4">
<!-- 总用户数卡片 --> <!-- 总用户数卡片 -->
@@ -467,6 +507,7 @@
</template> </template>
<script setup> <script setup>
import { apiCallApi } from '@/api'
import { import {
adminGetApiDomainStatistics, adminGetApiDomainStatistics,
adminGetApiPopularityRanking, adminGetApiPopularityRanking,
@@ -525,6 +566,11 @@ const apiPopularityData = ref([])
// 今日认证企业数据 // 今日认证企业数据
const todayCertifiedEnterprises = ref([]) const todayCertifiedEnterprises = ref([])
// 最近API调用记录队列最多10条
const recentApiCalls = ref([])
const recentApiCallsLoading = ref(false)
const MAX_RECENT_CALLS = 10
// 快捷选择配置 // 快捷选择配置
const shortcuts = [ const shortcuts = [
{ {
@@ -657,13 +703,26 @@ const formatTime = (() => {
// 初始化默认时间范围 // 初始化默认时间范围
const initDefaultDateRange = () => { const initDefaultDateRange = () => {
const today = new Date() const today = new Date()
const thirtyDaysAgo = new Date(today.getTime() - 30 * 24 * 60 * 60 * 1000)
// 获取当月第一天1号 00:00:00
const firstDayOfMonth = new Date(today.getFullYear(), today.getMonth(), 1)
// 格式化日期为 YYYY-MM-DD使用本地时间避免时区问题
const formatDateLocal = (date) => {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
// 结束日期使用今天(后端会将结束日期+1天查询时使用 < endTime这样可以包含今天的所有数据
// 左区间:>= 当月1日右区间< 明天(即包含今天)
const defaultRange = [ const defaultRange = [
thirtyDaysAgo.toISOString().split('T')[0], formatDateLocal(firstDayOfMonth), // 当月1日
today.toISOString().split('T')[0] formatDateLocal(today) // 今天
] ]
// 为所有图表设置默认时间范围(近一个月 // 为所有图表设置默认时间范围(当月1日到今天
userDateRange.value = [...defaultRange] userDateRange.value = [...defaultRange]
apiCallsDateRange.value = [...defaultRange] apiCallsDateRange.value = [...defaultRange]
consumptionDateRange.value = [...defaultRange] consumptionDateRange.value = [...defaultRange]
@@ -1303,9 +1362,133 @@ const getNoDataMessage = (periodRef) => {
} }
} }
// 加载最近API调用记录只显示成功的使用队列机制最多10条
const loadRecentApiCalls = async () => {
recentApiCallsLoading.value = true
try {
const response = await apiCallApi.getAdminApiCalls({
page: 1,
page_size: 1, // 只获取最新1条
status: 'success'
})
const newItems = response?.data?.items || []
if (newItems.length > 0) {
const newItem = newItems[0]
// 检查是否已存在根据ID判断
const exists = recentApiCalls.value.some(item => item.id === newItem.id)
if (!exists) {
// 新数据入队(添加到前面)
recentApiCalls.value.unshift(newItem)
// 如果超过最大数量,移除最旧的(队尾出队)
if (recentApiCalls.value.length > MAX_RECENT_CALLS) {
recentApiCalls.value = recentApiCalls.value.slice(0, MAX_RECENT_CALLS)
}
}
}
} catch (err) {
console.error('加载最近API调用记录失败:', err)
} finally {
recentApiCallsLoading.value = false
}
}
// 初始化时加载最近10条记录
const initRecentApiCalls = async () => {
recentApiCallsLoading.value = true
try {
console.log('开始加载最近API调用记录...')
const response = await apiCallApi.getAdminApiCalls({
page: 1,
page_size: MAX_RECENT_CALLS,
status: 'success'
})
console.log('API调用记录响应:', response)
console.log('响应数据:', response?.data)
console.log('items:', response?.data?.items)
const items = response?.data?.items || []
console.log('解析到的items数量:', items.length)
if (items.length > 0) {
console.log('第一条记录:', items[0])
}
recentApiCalls.value = items.slice(0, MAX_RECENT_CALLS)
console.log('最终设置的recentApiCalls:', recentApiCalls.value)
} catch (err) {
console.error('初始化最近API调用记录失败:', err)
console.error('错误详情:', err.response || err.message)
recentApiCalls.value = []
} finally {
recentApiCallsLoading.value = false
}
}
// 获取企业名称
const getCompanyName = (item) => {
if (item?.company_name) {
return item.company_name
}
if (item?.user?.company_name) {
return item.user.company_name
}
return '未知企业'
}
// 获取产品名称
const getProductName = (item) => {
if (item?.product_name) {
return item.product_name
}
return '未知接口'
}
// 格式化最近时间(显示相对时间或具体时间)
const formatRecentTime = (timeStr) => {
if (!timeStr) return '-'
try {
const time = new Date(timeStr)
const now = new Date()
const diff = now - time // 毫秒差
// 小于1分钟显示"刚刚"
if (diff < 60000) {
return '刚刚'
}
// 小于1小时显示分钟数
if (diff < 3600000) {
const minutes = Math.floor(diff / 60000)
return `${minutes}分钟前`
}
// 小于24小时显示小时数
if (diff < 86400000) {
const hours = Math.floor(diff / 3600000)
return `${hours}小时前`
}
// 大于24小时显示具体日期时间
return time.toLocaleString('zh-CN', {
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
})
} catch (e) {
return timeStr
}
}
onMounted(() => { onMounted(() => {
initDefaultDateRange() initDefaultDateRange()
loadSystemStatistics() loadSystemStatistics()
// 初始化加载最近10条API调用记录
initRecentApiCalls()
}) })
// 组件卸载时清理 // 组件卸载时清理