refactor(frontend): 优化功能模块组件

- 更新 api-keys 模块: StandaloneKeyFormDialog
- 改进 auth 模块: LoginDialog
- 优化 models 模块: AliasDialog, GlobalModelFormDialog, ModelDetailDrawer, TieredPricingEditor
- 重构 providers 模块: 多个表单和对话框组件
- 更新 usage 模块: 时间线、表格和详情组件
- 调整 users 模块: UserFormDialog
This commit is contained in:
fawney19
2025-12-12 16:15:36 +08:00
parent e9a6233655
commit 06c0a47b21
29 changed files with 2572 additions and 1051 deletions

View File

@@ -1,16 +1,25 @@
<template>
<div>
<div v-if="!data || (typeof data === 'object' && Object.keys(data).length === 0)" class="text-sm text-muted-foreground">
<div
v-if="!data || (typeof data === 'object' && Object.keys(data).length === 0)"
class="text-sm text-muted-foreground"
>
{{ emptyMessage }}
</div>
<!-- 纯字符串数据 JSON 对象 -->
<Card v-else-if="typeof data === 'string'" class="bg-muted/30 overflow-hidden">
<Card
v-else-if="typeof data === 'string'"
class="bg-muted/30 overflow-hidden"
>
<div class="p-4 overflow-x-auto max-h-[500px] overflow-y-auto">
<pre class="text-xs font-mono whitespace-pre-wrap">{{ data }}</pre>
</div>
</Card>
<!-- JSON 响应 HTML 错误页面 -->
<Card v-else-if="data.raw_response && data.metadata?.parse_error" class="bg-muted/30 overflow-hidden">
<Card
v-else-if="data.raw_response && data.metadata?.parse_error"
class="bg-muted/30 overflow-hidden"
>
<div class="p-3 bg-amber-50 dark:bg-amber-900/20 border-b border-amber-200 dark:border-amber-800">
<div class="flex items-start gap-2">
<span class="text-amber-600 dark:text-amber-400 text-sm font-medium">Warning: 响应解析失败</span>
@@ -21,12 +30,24 @@
<pre class="text-xs font-mono whitespace-pre-wrap text-muted-foreground">{{ data.raw_response }}</pre>
</div>
</Card>
<Card v-else class="bg-muted/30 overflow-hidden">
<Card
v-else
class="bg-muted/30 overflow-hidden"
>
<!-- JSON 查看器 -->
<div class="json-viewer" :class="{ 'theme-dark': isDark }">
<div
class="json-viewer"
:class="{ 'theme-dark': isDark }"
>
<div class="json-lines">
<template v-for="line in visibleLines" :key="line.displayId">
<div class="json-line" :class="{ 'has-fold': line.canFold }">
<template
v-for="line in visibleLines"
:key="line.displayId"
>
<div
class="json-line"
:class="{ 'has-fold': line.canFold }"
>
<!-- 行号区域包含折叠按钮 -->
<div class="line-number-area">
<span
@@ -34,22 +55,31 @@
class="fold-button"
@click="toggleFold(line.blockId)"
>
<ChevronRight v-if="collapsedBlocks.has(line.blockId)" class="fold-icon" />
<ChevronDown v-else class="fold-icon" />
<ChevronRight
v-if="collapsedBlocks.has(line.blockId)"
class="fold-icon"
/>
<ChevronDown
v-else
class="fold-icon"
/>
</span>
<span class="line-number">{{ line.displayLineNumber }}</span>
</div>
<!-- 内容区域 -->
<div class="line-content-area">
<!-- 缩进 -->
<span class="indent" :style="{ width: `${line.indent * 16}px` }"></span>
<span
class="indent"
:style="{ width: `${line.indent * 16}px` }"
/>
<!-- 内容 -->
<span
class="line-content"
:class="{ 'clickable-collapsed': line.canFold && collapsedBlocks.has(line.blockId) }"
@click="line.canFold && collapsedBlocks.has(line.blockId) && toggleFold(line.blockId)"
v-html="getDisplayHtml(line)"
></span>
/>
</div>
</div>
</template>

View File

@@ -2,10 +2,16 @@
<div>
<!-- 对比模式 - 并排 Diff -->
<div v-show="viewMode === 'compare'">
<div v-if="!detail.request_headers && !detail.provider_request_headers" class="text-sm text-muted-foreground">
<div
v-if="!detail.request_headers && !detail.provider_request_headers"
class="text-sm text-muted-foreground"
>
无请求头信息
</div>
<Card v-else class="bg-muted/30 overflow-hidden">
<Card
v-else
class="bg-muted/30 overflow-hidden"
>
<!-- Diff 头部 -->
<div class="flex border-b bg-muted/50">
<div class="flex-1 px-3 py-2 text-xs text-muted-foreground border-r flex items-center justify-between">
@@ -23,25 +29,40 @@
<div class="flex font-mono text-xs">
<!-- 左侧客户端 -->
<div class="flex-1 border-r">
<template v-for="entry in sortedEntries" :key="'left-' + entry.key">
<template
v-for="entry in sortedEntries"
:key="'left-' + entry.key"
>
<!-- 删除的行 -->
<div v-if="entry.status === 'removed'" class="flex items-start bg-destructive/10 px-3 py-0.5">
<div
v-if="entry.status === 'removed'"
class="flex items-start bg-destructive/10 px-3 py-0.5"
>
<span class="text-destructive">
"{{ entry.key }}": "{{ entry.clientValue }}"
</span>
</div>
<!-- 修改的行 - 旧值 -->
<div v-else-if="entry.status === 'modified'" class="flex items-start bg-amber-500/10 px-3 py-0.5">
<div
v-else-if="entry.status === 'modified'"
class="flex items-start bg-amber-500/10 px-3 py-0.5"
>
<span class="text-amber-600 dark:text-amber-400">
"{{ entry.key }}": "{{ entry.clientValue }}"
</span>
</div>
<!-- 新增的行 - 左侧空白占位 -->
<div v-else-if="entry.status === 'added'" class="flex items-start bg-muted/30 px-3 py-0.5">
<div
v-else-if="entry.status === 'added'"
class="flex items-start bg-muted/30 px-3 py-0.5"
>
<span class="text-muted-foreground/30 italic"></span>
</div>
<!-- 未变化的行 -->
<div v-else class="flex items-start px-3 py-0.5 hover:bg-muted/50">
<div
v-else
class="flex items-start px-3 py-0.5 hover:bg-muted/50"
>
<span class="text-muted-foreground">
"{{ entry.key }}": "{{ entry.clientValue }}"
</span>
@@ -50,27 +71,42 @@
</div>
<!-- 右侧提供商 -->
<div class="flex-1">
<template v-for="entry in sortedEntries" :key="'right-' + entry.key">
<template
v-for="entry in sortedEntries"
:key="'right-' + entry.key"
>
<!-- 删除的行 - 右侧空白占位 -->
<div v-if="entry.status === 'removed'" class="flex items-start bg-muted/30 px-3 py-0.5">
<div
v-if="entry.status === 'removed'"
class="flex items-start bg-muted/30 px-3 py-0.5"
>
<span class="text-muted-foreground/50 line-through">
"{{ entry.key }}": "{{ entry.clientValue }}"
</span>
</div>
<!-- 修改的行 - 新值 -->
<div v-else-if="entry.status === 'modified'" class="flex items-start bg-amber-500/10 px-3 py-0.5">
<div
v-else-if="entry.status === 'modified'"
class="flex items-start bg-amber-500/10 px-3 py-0.5"
>
<span class="text-amber-600 dark:text-amber-400">
"{{ entry.key }}": "{{ entry.providerValue }}"
</span>
</div>
<!-- 新增的行 -->
<div v-else-if="entry.status === 'added'" class="flex items-start bg-green-500/10 px-3 py-0.5">
<div
v-else-if="entry.status === 'added'"
class="flex items-start bg-green-500/10 px-3 py-0.5"
>
<span class="text-green-600 dark:text-green-400">
"{{ entry.key }}": "{{ entry.providerValue }}"
</span>
</div>
<!-- 未变化的行 -->
<div v-else class="flex items-start px-3 py-0.5 hover:bg-muted/50">
<div
v-else
class="flex items-start px-3 py-0.5 hover:bg-muted/50"
>
<span class="text-muted-foreground">
"{{ entry.key }}": "{{ entry.providerValue }}"
</span>
@@ -95,10 +131,16 @@
<!-- 原始模式 -->
<div v-show="viewMode === 'raw'">
<div v-if="!currentHeaderData || Object.keys(currentHeaderData).length === 0" class="text-sm text-muted-foreground">
<div
v-if="!currentHeaderData || Object.keys(currentHeaderData).length === 0"
class="text-sm text-muted-foreground"
>
无请求头信息
</div>
<Card v-else class="bg-muted/30">
<Card
v-else
class="bg-muted/30"
>
<div class="p-4 overflow-x-auto">
<pre class="text-xs font-mono whitespace-pre-wrap">{{ JSON.stringify(currentHeaderData, null, 2) }}</pre>
</div>