mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 00:53:33 +00:00
feat: keep API key stats modal and add timeline entry point
This commit is contained in:
@@ -231,6 +231,9 @@
|
|||||||
|
|
||||||
<!-- 底部按钮 -->
|
<!-- 底部按钮 -->
|
||||||
<div class="mt-4 flex justify-end gap-2 sm:mt-6 sm:gap-3">
|
<div class="mt-4 flex justify-end gap-2 sm:mt-6 sm:gap-3">
|
||||||
|
<button class="btn btn-primary px-4 py-2 text-sm" type="button" @click="openTimeline">
|
||||||
|
查看请求时间线
|
||||||
|
</button>
|
||||||
<button class="btn btn-secondary px-4 py-2 text-sm" type="button" @click="close">
|
<button class="btn btn-secondary px-4 py-2 text-sm" type="button" @click="close">
|
||||||
关闭
|
关闭
|
||||||
</button>
|
</button>
|
||||||
@@ -256,7 +259,7 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['close'])
|
const emit = defineEmits(['close', 'open-timeline'])
|
||||||
|
|
||||||
// 计算属性
|
// 计算属性
|
||||||
const totalRequests = computed(() => props.apiKey.usage?.total?.requests || 0)
|
const totalRequests = computed(() => props.apiKey.usage?.total?.requests || 0)
|
||||||
@@ -320,6 +323,10 @@ const formatTokenCount = (count) => {
|
|||||||
const close = () => {
|
const close = () => {
|
||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const openTimeline = () => {
|
||||||
|
emit('open-timeline', props.apiKey?.id)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -2084,6 +2084,13 @@
|
|||||||
@close="closeExpiryEdit"
|
@close="closeExpiryEdit"
|
||||||
@save="handleSaveExpiry"
|
@save="handleSaveExpiry"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<UsageDetailModal
|
||||||
|
:api-key="selectedApiKeyForDetail || {}"
|
||||||
|
:show="showUsageDetailModal"
|
||||||
|
@close="showUsageDetailModal = false"
|
||||||
|
@open-timeline="openTimeline"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -2102,6 +2109,7 @@ import NewApiKeyModal from '@/components/apikeys/NewApiKeyModal.vue'
|
|||||||
import BatchApiKeyModal from '@/components/apikeys/BatchApiKeyModal.vue'
|
import BatchApiKeyModal from '@/components/apikeys/BatchApiKeyModal.vue'
|
||||||
import BatchEditApiKeyModal from '@/components/apikeys/BatchEditApiKeyModal.vue'
|
import BatchEditApiKeyModal from '@/components/apikeys/BatchEditApiKeyModal.vue'
|
||||||
import ExpiryEditModal from '@/components/apikeys/ExpiryEditModal.vue'
|
import ExpiryEditModal from '@/components/apikeys/ExpiryEditModal.vue'
|
||||||
|
import UsageDetailModal from '@/components/apikeys/UsageDetailModal.vue'
|
||||||
import LimitProgressBar from '@/components/apikeys/LimitProgressBar.vue'
|
import LimitProgressBar from '@/components/apikeys/LimitProgressBar.vue'
|
||||||
import CustomDropdown from '@/components/common/CustomDropdown.vue'
|
import CustomDropdown from '@/components/common/CustomDropdown.vue'
|
||||||
import ActionDropdown from '@/components/common/ActionDropdown.vue'
|
import ActionDropdown from '@/components/common/ActionDropdown.vue'
|
||||||
@@ -2205,6 +2213,8 @@ const accountsLoading = ref(false)
|
|||||||
const accountsLoaded = ref(false)
|
const accountsLoaded = ref(false)
|
||||||
const editingExpiryKey = ref(null)
|
const editingExpiryKey = ref(null)
|
||||||
const expiryEditModalRef = ref(null)
|
const expiryEditModalRef = ref(null)
|
||||||
|
const showUsageDetailModal = ref(false)
|
||||||
|
const selectedApiKeyForDetail = ref(null)
|
||||||
|
|
||||||
// 标签相关
|
// 标签相关
|
||||||
const selectedTagFilter = ref('')
|
const selectedTagFilter = ref('')
|
||||||
@@ -4185,7 +4195,40 @@ const formatWindowTime = (seconds) => {
|
|||||||
|
|
||||||
// 显示使用详情
|
// 显示使用详情
|
||||||
const showUsageDetails = (apiKey) => {
|
const showUsageDetails = (apiKey) => {
|
||||||
router.push(`/api-keys/${apiKey.id}/usage-records`)
|
const cachedStats = getCachedStats(apiKey.id)
|
||||||
|
|
||||||
|
const enrichedApiKey = {
|
||||||
|
...apiKey,
|
||||||
|
dailyCost: cachedStats?.dailyCost ?? apiKey.dailyCost ?? 0,
|
||||||
|
currentWindowCost: cachedStats?.currentWindowCost ?? apiKey.currentWindowCost ?? 0,
|
||||||
|
windowRemainingSeconds: cachedStats?.windowRemainingSeconds ?? apiKey.windowRemainingSeconds,
|
||||||
|
windowStartTime: cachedStats?.windowStartTime ?? apiKey.windowStartTime ?? null,
|
||||||
|
windowEndTime: cachedStats?.windowEndTime ?? apiKey.windowEndTime ?? null,
|
||||||
|
usage: {
|
||||||
|
...apiKey.usage,
|
||||||
|
total: {
|
||||||
|
...apiKey.usage?.total,
|
||||||
|
requests: cachedStats?.requests ?? apiKey.usage?.total?.requests ?? 0,
|
||||||
|
tokens: cachedStats?.tokens ?? apiKey.usage?.total?.tokens ?? 0,
|
||||||
|
cost: cachedStats?.allTimeCost ?? apiKey.usage?.total?.cost ?? 0,
|
||||||
|
inputTokens: cachedStats?.inputTokens ?? apiKey.usage?.total?.inputTokens ?? 0,
|
||||||
|
outputTokens: cachedStats?.outputTokens ?? apiKey.usage?.total?.outputTokens ?? 0,
|
||||||
|
cacheCreateTokens:
|
||||||
|
cachedStats?.cacheCreateTokens ?? apiKey.usage?.total?.cacheCreateTokens ?? 0,
|
||||||
|
cacheReadTokens: cachedStats?.cacheReadTokens ?? apiKey.usage?.total?.cacheReadTokens ?? 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedApiKeyForDetail.value = enrichedApiKey
|
||||||
|
showUsageDetailModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const openTimeline = (keyId) => {
|
||||||
|
const id = keyId || selectedApiKeyForDetail.value?.id
|
||||||
|
if (!id) return
|
||||||
|
showUsageDetailModal.value = false
|
||||||
|
router.push(`/api-keys/${id}/usage-records`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 格式化时间(秒转换为可读格式) - 已移到 WindowLimitBar 组件中
|
// 格式化时间(秒转换为可读格式) - 已移到 WindowLimitBar 组件中
|
||||||
|
|||||||
Reference in New Issue
Block a user