feat: API Keys图标系统和UI优化

主要功能增强:
- 实现API Key自定义图标功能,支持图片上传、裁剪和智能压缩
- 新增IconPicker组件,提供内置图标选择和图片上传功能
- 支持固定尺寸裁剪区域,可拖拽定位选择头像区域
- 智能图片压缩:PNG保留透明度,JPEG用于不透明图片

UI/UX改进:
- 优化表格布局:移除账号列,在名称下方显示账号绑定信息
- 调整行高和字体大小,提升信息密度
- 最后使用时间改为相对时间显示,悬浮显示具体时间
- 过期时间编辑改为点击文本触发,带悬浮下划线效果
- 更新默认API Key图标为蓝色渐变设计
- 修复表格悬浮偏移和横向滚动条问题
- 将"TOKEN 数量"改为"Token数"

后端支持:
- apiKeyService增加icon字段持久化
- admin路由增加图标数据处理和验证

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Edric Li
2025-09-07 11:41:22 +08:00
parent fc5c60a9b4
commit 8c9d6381f3
6 changed files with 1313 additions and 207 deletions

View File

@@ -32,14 +32,18 @@
class="mb-1.5 block text-xs font-semibold text-gray-700 dark:text-gray-300 sm:mb-3 sm:text-sm"
>名称</label
>
<input
v-model="form.name"
class="form-input w-full border-gray-300 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
maxlength="100"
placeholder="请输入API Key名称"
required
type="text"
/>
<div class="flex items-center gap-2">
<!-- 图标选择器 -->
<IconPicker v-model="form.icon" size="medium" />
<input
v-model="form.name"
class="form-input flex-1 border-gray-300 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
maxlength="100"
placeholder="请输入API Key名称"
required
type="text"
/>
</div>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400 sm:mt-2">
用于识别此 API Key 的用途
</p>
@@ -658,6 +662,7 @@ import { useClientsStore } from '@/stores/clients'
import { useApiKeysStore } from '@/stores/apiKeys'
import { apiClient } from '@/config/api'
import AccountSelector from '@/components/common/AccountSelector.vue'
import IconPicker from '@/components/common/IconPicker.vue'
const props = defineProps({
apiKey: {
@@ -705,6 +710,7 @@ const unselectedTags = computed(() => {
// 表单数据
const form = reactive({
name: '',
icon: '',
tokenLimit: '', // 保留用于检测历史数据
rateLimitWindow: '',
rateLimitRequests: '',
@@ -803,6 +809,7 @@ const updateApiKey = async () => {
// 准备提交的数据
const data = {
name: form.name, // 添加名称字段
icon: form.icon || '', // 添加图标字段
tokenLimit: 0, // 清除历史token限制
rateLimitWindow:
form.rateLimitWindow !== '' && form.rateLimitWindow !== null
@@ -1035,6 +1042,7 @@ onMounted(async () => {
}
form.name = props.apiKey.name
form.icon = props.apiKey.icon || ''
// 处理速率限制迁移如果有tokenLimit且没有rateLimitCost提示用户
form.tokenLimit = props.apiKey.tokenLimit || ''