mirror of
https://github.com/fawney19/Aether.git
synced 2026-01-12 12:38:31 +08:00
refactor(frontend): 优化功能模块组件
- 更新 api-keys 模块: StandaloneKeyFormDialog - 改进 auth 模块: LoginDialog - 优化 models 模块: AliasDialog, GlobalModelFormDialog, ModelDetailDrawer, TieredPricingEditor - 重构 providers 模块: 多个表单和对话框组件 - 更新 usage 模块: 时间线、表格和详情组件 - 调整 users 模块: UserFormDialog
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user