mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 09:38:02 +00:00
Merge remote-tracking branch 'f3n9/main' into main-um-8
This commit is contained in:
@@ -890,6 +890,7 @@ router.put('/api-keys/:keyId', authenticateAdmin, async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const { keyId } = req.params
|
const { keyId } = req.params
|
||||||
const {
|
const {
|
||||||
|
name, // 添加名称字段
|
||||||
tokenLimit,
|
tokenLimit,
|
||||||
concurrencyLimit,
|
concurrencyLimit,
|
||||||
rateLimitWindow,
|
rateLimitWindow,
|
||||||
@@ -916,6 +917,18 @@ router.put('/api-keys/:keyId', authenticateAdmin, async (req, res) => {
|
|||||||
// 只允许更新指定字段
|
// 只允许更新指定字段
|
||||||
const updates = {}
|
const updates = {}
|
||||||
|
|
||||||
|
// 处理名称字段
|
||||||
|
if (name !== undefined && name !== null && name !== '') {
|
||||||
|
const trimmedName = name.toString().trim()
|
||||||
|
if (trimmedName.length === 0) {
|
||||||
|
return res.status(400).json({ error: 'API Key name cannot be empty' })
|
||||||
|
}
|
||||||
|
if (trimmedName.length > 100) {
|
||||||
|
return res.status(400).json({ error: 'API Key name must be less than 100 characters' })
|
||||||
|
}
|
||||||
|
updates.name = trimmedName
|
||||||
|
}
|
||||||
|
|
||||||
if (tokenLimit !== undefined && tokenLimit !== null && tokenLimit !== '') {
|
if (tokenLimit !== undefined && tokenLimit !== null && tokenLimit !== '') {
|
||||||
if (!Number.isInteger(Number(tokenLimit)) || Number(tokenLimit) < 0) {
|
if (!Number.isInteger(Number(tokenLimit)) || Number(tokenLimit) < 0) {
|
||||||
return res.status(400).json({ error: 'Token limit must be a non-negative integer' })
|
return res.status(400).json({ error: 'Token limit must be a non-negative integer' })
|
||||||
|
|||||||
@@ -33,12 +33,16 @@
|
|||||||
>名称</label
|
>名称</label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
class="form-input w-full cursor-not-allowed bg-gray-100 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400"
|
v-model="form.name"
|
||||||
disabled
|
class="form-input w-full 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"
|
type="text"
|
||||||
:value="form.name"
|
|
||||||
/>
|
/>
|
||||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400 sm:mt-2">名称不可修改</p>
|
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400 sm:mt-2">
|
||||||
|
用于识别此 API Key 的用途
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 所有者选择 -->
|
<!-- 所有者选择 -->
|
||||||
@@ -798,6 +802,7 @@ const updateApiKey = async () => {
|
|||||||
try {
|
try {
|
||||||
// 准备提交的数据
|
// 准备提交的数据
|
||||||
const data = {
|
const data = {
|
||||||
|
name: form.name, // 添加名称字段
|
||||||
tokenLimit: 0, // 清除历史token限制
|
tokenLimit: 0, // 清除历史token限制
|
||||||
rateLimitWindow:
|
rateLimitWindow:
|
||||||
form.rateLimitWindow !== '' && form.rateLimitWindow !== null
|
form.rateLimitWindow !== '' && form.rateLimitWindow !== null
|
||||||
|
|||||||
@@ -105,7 +105,7 @@
|
|||||||
<input
|
<input
|
||||||
v-model="searchKeyword"
|
v-model="searchKeyword"
|
||||||
class="w-full rounded-lg border border-gray-200 bg-white px-3 py-2 pl-9 text-sm text-gray-700 placeholder-gray-400 shadow-sm transition-all duration-200 hover:border-gray-300 focus:border-cyan-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/20 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:placeholder-gray-500 dark:hover:border-gray-500"
|
class="w-full rounded-lg border border-gray-200 bg-white px-3 py-2 pl-9 text-sm text-gray-700 placeholder-gray-400 shadow-sm transition-all duration-200 hover:border-gray-300 focus:border-cyan-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/20 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:placeholder-gray-500 dark:hover:border-gray-500"
|
||||||
placeholder="搜索名称或所有者..."
|
:placeholder="isLdapEnabled ? '搜索名称或所有者...' : '搜索名称...'"
|
||||||
type="text"
|
type="text"
|
||||||
@input="currentPage = 1"
|
@input="currentPage = 1"
|
||||||
/>
|
/>
|
||||||
@@ -405,7 +405,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 显示所有者信息 -->
|
<!-- 显示所有者信息 -->
|
||||||
<div v-if="key.ownerDisplayName" class="mt-1 text-xs text-red-600">
|
<div
|
||||||
|
v-if="isLdapEnabled && key.ownerDisplayName"
|
||||||
|
class="mt-1 text-xs text-red-600"
|
||||||
|
>
|
||||||
<i class="fas fa-user mr-1" />
|
<i class="fas fa-user mr-1" />
|
||||||
{{ key.ownerDisplayName }}
|
{{ key.ownerDisplayName }}
|
||||||
</div>
|
</div>
|
||||||
@@ -1031,7 +1034,7 @@
|
|||||||
使用共享池
|
使用共享池
|
||||||
</div>
|
</div>
|
||||||
<!-- 显示所有者信息 -->
|
<!-- 显示所有者信息 -->
|
||||||
<div v-if="key.ownerDisplayName" class="text-xs text-red-600">
|
<div v-if="isLdapEnabled && key.ownerDisplayName" class="text-xs text-red-600">
|
||||||
<i class="fas fa-user mr-1" />
|
<i class="fas fa-user mr-1" />
|
||||||
{{ key.ownerDisplayName }}
|
{{ key.ownerDisplayName }}
|
||||||
</div>
|
</div>
|
||||||
@@ -1337,6 +1340,7 @@
|
|||||||
名称
|
名称
|
||||||
</th>
|
</th>
|
||||||
<th
|
<th
|
||||||
|
v-if="isLdapEnabled"
|
||||||
class="w-[15%] min-w-[120px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 dark:text-gray-300"
|
class="w-[15%] min-w-[120px] px-3 py-4 text-left text-xs font-bold uppercase tracking-wider text-gray-700 dark:text-gray-300"
|
||||||
>
|
>
|
||||||
创建者
|
创建者
|
||||||
@@ -1393,7 +1397,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-3 py-4">
|
<td v-if="isLdapEnabled" class="px-3 py-4">
|
||||||
<div class="text-sm">
|
<div class="text-sm">
|
||||||
<span v-if="key.createdBy === 'admin'" class="text-blue-600">
|
<span v-if="key.createdBy === 'admin'" class="text-blue-600">
|
||||||
<i class="fas fa-user-shield mr-1" />
|
<i class="fas fa-user-shield mr-1" />
|
||||||
@@ -1555,6 +1559,7 @@ import { ref, computed, onMounted, watch } from 'vue'
|
|||||||
import { showToast } from '@/utils/toast'
|
import { showToast } from '@/utils/toast'
|
||||||
import { apiClient } from '@/config/api'
|
import { apiClient } from '@/config/api'
|
||||||
import { useClientsStore } from '@/stores/clients'
|
import { useClientsStore } from '@/stores/clients'
|
||||||
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import CreateApiKeyModal from '@/components/apikeys/CreateApiKeyModal.vue'
|
import CreateApiKeyModal from '@/components/apikeys/CreateApiKeyModal.vue'
|
||||||
import EditApiKeyModal from '@/components/apikeys/EditApiKeyModal.vue'
|
import EditApiKeyModal from '@/components/apikeys/EditApiKeyModal.vue'
|
||||||
import RenewApiKeyModal from '@/components/apikeys/RenewApiKeyModal.vue'
|
import RenewApiKeyModal from '@/components/apikeys/RenewApiKeyModal.vue'
|
||||||
@@ -1568,8 +1573,12 @@ import CustomDropdown from '@/components/common/CustomDropdown.vue'
|
|||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const clientsStore = useClientsStore()
|
const clientsStore = useClientsStore()
|
||||||
|
const authStore = useAuthStore()
|
||||||
const apiKeys = ref([])
|
const apiKeys = ref([])
|
||||||
|
|
||||||
|
// 获取 LDAP 启用状态
|
||||||
|
const isLdapEnabled = computed(() => authStore.oemSettings?.ldapEnabled || false)
|
||||||
|
|
||||||
// 多选相关状态
|
// 多选相关状态
|
||||||
const selectedApiKeys = ref([])
|
const selectedApiKeys = ref([])
|
||||||
const selectAllChecked = ref(false)
|
const selectAllChecked = ref(false)
|
||||||
@@ -1663,11 +1672,15 @@ const sortedApiKeys = computed(() => {
|
|||||||
filteredKeys = filteredKeys.filter((key) => {
|
filteredKeys = filteredKeys.filter((key) => {
|
||||||
// 搜索API Key名称
|
// 搜索API Key名称
|
||||||
const nameMatch = key.name && key.name.toLowerCase().includes(keyword)
|
const nameMatch = key.name && key.name.toLowerCase().includes(keyword)
|
||||||
// 搜索所有者名称
|
// 如果启用了 LDAP,搜索所有者名称
|
||||||
const ownerMatch =
|
if (isLdapEnabled.value) {
|
||||||
key.ownerDisplayName && key.ownerDisplayName.toLowerCase().includes(keyword)
|
const ownerMatch =
|
||||||
// 如果API Key名称或所有者名称匹配,则包含该条目
|
key.ownerDisplayName && key.ownerDisplayName.toLowerCase().includes(keyword)
|
||||||
return nameMatch || ownerMatch
|
// 如果API Key名称或所有者名称匹配,则包含该条目
|
||||||
|
return nameMatch || ownerMatch
|
||||||
|
}
|
||||||
|
// 未启用 LDAP 时只搜索名称
|
||||||
|
return nameMatch
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user