mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 00:53:33 +00:00
resolve: 解决与upstream/dev的合并冲突
- 合并admin.js中的groupIds和autoStopOnWarning参数 - 统一AccountForm.vue中的错误提示文案和平台判断逻辑 - 保留AccountsView.vue中的分组过滤和ungrouped功能 - 确保Azure OpenAI账户创建和更新逻辑完整性 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -556,7 +556,17 @@
|
||||
>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<label
|
||||
v-for="model in ['gpt-4', 'gpt-4-turbo', 'gpt-35-turbo', 'gpt-35-turbo-16k']"
|
||||
v-for="model in [
|
||||
'gpt-4',
|
||||
'gpt-4-turbo',
|
||||
'gpt-4o',
|
||||
'gpt-4o-mini',
|
||||
'gpt-5',
|
||||
'gpt-5-mini',
|
||||
'gpt-35-turbo',
|
||||
'gpt-35-turbo-16k',
|
||||
'codex-mini'
|
||||
]"
|
||||
:key="model"
|
||||
class="flex cursor-pointer items-center"
|
||||
>
|
||||
@@ -825,6 +835,25 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Claude 5小时限制自动停止调度选项 -->
|
||||
<div v-if="form.platform === 'claude'" class="mt-4">
|
||||
<label class="flex items-start">
|
||||
<input
|
||||
v-model="form.autoStopOnWarning"
|
||||
class="mt-1 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div class="ml-3">
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
5小时使用量接近限制时自动停止调度
|
||||
</span>
|
||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
当系统检测到账户接近5小时使用限制时,自动暂停调度该账户。进入新的时间窗口后会自动恢复调度。
|
||||
</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- 所有平台的优先级设置 -->
|
||||
<div>
|
||||
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
|
||||
@@ -1364,6 +1393,25 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Claude 5小时限制自动停止调度选项(编辑模式) -->
|
||||
<div v-if="form.platform === 'claude'" class="mt-4">
|
||||
<label class="flex items-start">
|
||||
<input
|
||||
v-model="form.autoStopOnWarning"
|
||||
class="mt-1 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div class="ml-3">
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
5小时使用量接近限制时自动停止调度
|
||||
</span>
|
||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
当系统检测到账户接近5小时使用限制时,自动暂停调度该账户。进入新的时间窗口后会自动恢复调度。
|
||||
</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<!-- 所有平台的优先级设置(编辑模式) -->
|
||||
<div>
|
||||
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
|
||||
@@ -1660,9 +1708,112 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Azure OpenAI 特定字段(编辑模式)-->
|
||||
<div v-if="form.platform === 'azure_openai'" class="space-y-4">
|
||||
<div>
|
||||
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
|
||||
>Azure Endpoint</label
|
||||
>
|
||||
<input
|
||||
v-model="form.azureEndpoint"
|
||||
class="form-input w-full dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
|
||||
:class="{ 'border-red-500': errors.azureEndpoint }"
|
||||
placeholder="https://your-resource.openai.azure.com"
|
||||
type="url"
|
||||
/>
|
||||
<p v-if="errors.azureEndpoint" class="mt-1 text-xs text-red-500">
|
||||
{{ errors.azureEndpoint }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
|
||||
>API 版本</label
|
||||
>
|
||||
<input
|
||||
v-model="form.apiVersion"
|
||||
class="form-input w-full dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
|
||||
placeholder="2024-02-01"
|
||||
type="text"
|
||||
/>
|
||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
Azure OpenAI API 版本,默认使用最新稳定版本 2024-02-01
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
|
||||
>部署名称</label
|
||||
>
|
||||
<input
|
||||
v-model="form.deploymentName"
|
||||
class="form-input w-full dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
|
||||
:class="{ 'border-red-500': errors.deploymentName }"
|
||||
placeholder="gpt-4"
|
||||
type="text"
|
||||
/>
|
||||
<p v-if="errors.deploymentName" class="mt-1 text-xs text-red-500">
|
||||
{{ errors.deploymentName }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
|
||||
>API Key</label
|
||||
>
|
||||
<input
|
||||
v-model="form.apiKey"
|
||||
class="form-input w-full dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 dark:placeholder-gray-400"
|
||||
:class="{ 'border-red-500': errors.apiKey }"
|
||||
placeholder="留空表示不更新"
|
||||
type="password"
|
||||
/>
|
||||
<p v-if="errors.apiKey" class="mt-1 text-xs text-red-500">
|
||||
{{ errors.apiKey }}
|
||||
</p>
|
||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">留空表示不更新 API Key</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="mb-3 block text-sm font-semibold text-gray-700 dark:text-gray-300"
|
||||
>支持的模型</label
|
||||
>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<label
|
||||
v-for="model in [
|
||||
'gpt-4',
|
||||
'gpt-4-turbo',
|
||||
'gpt-4o',
|
||||
'gpt-4o-mini',
|
||||
'gpt-5',
|
||||
'gpt-5-mini',
|
||||
'gpt-35-turbo',
|
||||
'gpt-35-turbo-16k',
|
||||
'codex-mini'
|
||||
]"
|
||||
:key="model"
|
||||
class="flex cursor-pointer items-center"
|
||||
>
|
||||
<input
|
||||
v-model="form.supportedModels"
|
||||
class="mr-2 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700"
|
||||
type="checkbox"
|
||||
:value="model"
|
||||
/>
|
||||
<span class="text-sm text-gray-700 dark:text-gray-300">{{ model }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">选择此部署支持的模型类型</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Token 更新 -->
|
||||
<div
|
||||
v-if="form.platform !== 'claude-console' && form.platform !== 'bedrock'"
|
||||
v-if="
|
||||
form.platform !== 'claude-console' &&
|
||||
form.platform !== 'bedrock' &&
|
||||
form.platform !== 'azure_openai'
|
||||
"
|
||||
class="rounded-lg border border-amber-200 bg-amber-50 p-4 dark:border-amber-700 dark:bg-amber-900/30"
|
||||
>
|
||||
<div class="mb-4 flex items-start gap-3">
|
||||
@@ -1826,6 +1977,7 @@ const form = ref({
|
||||
description: props.account?.description || '',
|
||||
accountType: props.account?.accountType || 'shared',
|
||||
subscriptionType: 'claude_max', // 默认为 Claude Max,兼容旧数据
|
||||
autoStopOnWarning: props.account?.autoStopOnWarning || false, // 5小时限制自动停止调度
|
||||
groupId: '',
|
||||
groupIds: [],
|
||||
projectId: props.account?.projectId || '',
|
||||
@@ -1839,16 +1991,16 @@ const form = ref({
|
||||
priority: props.account?.priority || 50,
|
||||
supportedModels: (() => {
|
||||
const models = props.account?.supportedModels
|
||||
if (!models) return ''
|
||||
if (!models) return []
|
||||
// 处理对象格式(Claude Console 的新格式)
|
||||
if (typeof models === 'object' && !Array.isArray(models)) {
|
||||
return Object.keys(models).join('\n')
|
||||
return Object.keys(models)
|
||||
}
|
||||
// 处理数组格式(向后兼容)
|
||||
if (Array.isArray(models)) {
|
||||
return models.join('\n')
|
||||
return models
|
||||
}
|
||||
return ''
|
||||
return []
|
||||
})(),
|
||||
userAgent: props.account?.userAgent || '',
|
||||
enableRateLimit: props.account ? props.account.rateLimitDuration > 0 : true,
|
||||
@@ -1859,7 +2011,11 @@ const form = ref({
|
||||
region: props.account?.region || '',
|
||||
sessionToken: props.account?.sessionToken || '',
|
||||
defaultModel: props.account?.defaultModel || '',
|
||||
smallFastModel: props.account?.smallFastModel || ''
|
||||
smallFastModel: props.account?.smallFastModel || '',
|
||||
// Azure OpenAI 特定字段
|
||||
azureEndpoint: props.account?.azureEndpoint || '',
|
||||
apiVersion: props.account?.apiVersion || '',
|
||||
deploymentName: props.account?.deploymentName || ''
|
||||
})
|
||||
|
||||
// 模型映射表数据
|
||||
@@ -1896,7 +2052,9 @@ const errors = ref({
|
||||
apiKey: '',
|
||||
accessKeyId: '',
|
||||
secretAccessKey: '',
|
||||
region: ''
|
||||
region: '',
|
||||
azureEndpoint: '',
|
||||
deploymentName: ''
|
||||
})
|
||||
|
||||
// 计算是否可以进入下一步
|
||||
@@ -2096,6 +2254,7 @@ const handleOAuthSuccess = async (tokenInfo) => {
|
||||
// Claude使用claudeAiOauth字段
|
||||
data.claudeAiOauth = tokenInfo.claudeAiOauth || tokenInfo
|
||||
data.priority = form.value.priority || 50
|
||||
data.autoStopOnWarning = form.value.autoStopOnWarning || false
|
||||
// 添加订阅类型信息
|
||||
data.subscriptionInfo = {
|
||||
accountType: form.value.subscriptionType || 'claude_max',
|
||||
@@ -2176,15 +2335,15 @@ const createAccount = async () => {
|
||||
} else if (form.value.platform === 'azure_openai') {
|
||||
// Azure OpenAI 验证
|
||||
if (!form.value.azureEndpoint || form.value.azureEndpoint.trim() === '') {
|
||||
errors.value.azureEndpoint = 'Azure Endpoint 是必填项'
|
||||
errors.value.azureEndpoint = '请填写 Azure Endpoint'
|
||||
hasError = true
|
||||
}
|
||||
if (!form.value.deploymentName || form.value.deploymentName.trim() === '') {
|
||||
errors.value.deploymentName = 'Deployment Name 是必填项'
|
||||
errors.value.deploymentName = '请填写部署名称'
|
||||
hasError = true
|
||||
}
|
||||
if (!form.value.apiKey || form.value.apiKey.trim() === '') {
|
||||
errors.value.apiKey = 'API Key 是必填项'
|
||||
errors.value.apiKey = '请填写 API Key'
|
||||
hasError = true
|
||||
}
|
||||
} else if (form.value.addType === 'manual') {
|
||||
@@ -2257,6 +2416,7 @@ const createAccount = async () => {
|
||||
scopes: [] // 手动添加没有 scopes
|
||||
}
|
||||
data.priority = form.value.priority || 50
|
||||
data.autoStopOnWarning = form.value.autoStopOnWarning || false
|
||||
// 添加订阅类型信息
|
||||
data.subscriptionInfo = {
|
||||
accountType: form.value.subscriptionType || 'claude_max',
|
||||
@@ -2360,10 +2520,12 @@ const createAccount = async () => {
|
||||
} else if (form.value.platform === 'azure_openai') {
|
||||
// Azure OpenAI 账户特定数据
|
||||
data.azureEndpoint = form.value.azureEndpoint
|
||||
data.apiKey = form.value.apiKey
|
||||
data.apiVersion = form.value.apiVersion || '2024-02-01'
|
||||
data.deploymentName = form.value.deploymentName
|
||||
data.apiKey = form.value.apiKey
|
||||
data.supportedModels = form.value.supportedModels || []
|
||||
data.supportedModels = Array.isArray(form.value.supportedModels)
|
||||
? form.value.supportedModels
|
||||
: []
|
||||
data.priority = form.value.priority || 50
|
||||
data.isActive = form.value.isActive !== false
|
||||
data.schedulable = form.value.schedulable !== false
|
||||
@@ -2507,6 +2669,7 @@ const updateAccount = async () => {
|
||||
// Claude 官方账号优先级和订阅类型更新
|
||||
if (props.account.platform === 'claude') {
|
||||
data.priority = form.value.priority || 50
|
||||
data.autoStopOnWarning = form.value.autoStopOnWarning || false
|
||||
// 更新订阅类型信息
|
||||
data.subscriptionInfo = {
|
||||
accountType: form.value.subscriptionType || 'claude_max',
|
||||
@@ -2565,6 +2728,21 @@ const updateAccount = async () => {
|
||||
data.rateLimitDuration = form.value.enableRateLimit ? form.value.rateLimitDuration || 60 : 0
|
||||
}
|
||||
|
||||
// Azure OpenAI 特定更新
|
||||
if (props.account.platform === 'azure_openai') {
|
||||
data.azureEndpoint = form.value.azureEndpoint
|
||||
data.apiVersion = form.value.apiVersion || '2024-02-01'
|
||||
data.deploymentName = form.value.deploymentName
|
||||
data.supportedModels = Array.isArray(form.value.supportedModels)
|
||||
? form.value.supportedModels
|
||||
: []
|
||||
data.priority = form.value.priority || 50
|
||||
// 只有当有新的 API Key 时才更新
|
||||
if (form.value.apiKey && form.value.apiKey.trim()) {
|
||||
data.apiKey = form.value.apiKey
|
||||
}
|
||||
}
|
||||
|
||||
if (props.account.platform === 'claude') {
|
||||
await accountsStore.updateClaudeAccount(props.account.id, data)
|
||||
} else if (props.account.platform === 'claude-console') {
|
||||
@@ -2629,6 +2807,26 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
// 监听Azure Endpoint变化,清除错误
|
||||
watch(
|
||||
() => form.value.azureEndpoint,
|
||||
() => {
|
||||
if (errors.value.azureEndpoint && form.value.azureEndpoint?.trim()) {
|
||||
errors.value.azureEndpoint = ''
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 监听Deployment Name变化,清除错误
|
||||
watch(
|
||||
() => form.value.deploymentName,
|
||||
() => {
|
||||
if (errors.value.deploymentName && form.value.deploymentName?.trim()) {
|
||||
errors.value.deploymentName = ''
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 分组相关数据
|
||||
const groups = ref([])
|
||||
const loadingGroups = ref(false)
|
||||
@@ -2872,6 +3070,7 @@ watch(
|
||||
description: newAccount.description || '',
|
||||
accountType: newAccount.accountType || 'shared',
|
||||
subscriptionType: subscriptionType,
|
||||
autoStopOnWarning: newAccount.autoStopOnWarning || false,
|
||||
groupId: groupId,
|
||||
groupIds: [],
|
||||
projectId: newAccount.projectId || '',
|
||||
@@ -2884,16 +3083,16 @@ watch(
|
||||
priority: newAccount.priority || 50,
|
||||
supportedModels: (() => {
|
||||
const models = newAccount.supportedModels
|
||||
if (!models) return ''
|
||||
if (!models) return []
|
||||
// 处理对象格式(Claude Console 的新格式)
|
||||
if (typeof models === 'object' && !Array.isArray(models)) {
|
||||
return Object.keys(models).join('\n')
|
||||
return Object.keys(models)
|
||||
}
|
||||
// 处理数组格式(向后兼容)
|
||||
if (Array.isArray(models)) {
|
||||
return models.join('\n')
|
||||
return models
|
||||
}
|
||||
return ''
|
||||
return []
|
||||
})(),
|
||||
userAgent: newAccount.userAgent || '',
|
||||
enableRateLimit:
|
||||
@@ -2905,7 +3104,11 @@ watch(
|
||||
region: newAccount.region || '',
|
||||
sessionToken: '', // 编辑模式不显示现有的会话令牌
|
||||
defaultModel: newAccount.defaultModel || '',
|
||||
smallFastModel: newAccount.smallFastModel || ''
|
||||
smallFastModel: newAccount.smallFastModel || '',
|
||||
// Azure OpenAI 特定字段
|
||||
azureEndpoint: newAccount.azureEndpoint || '',
|
||||
apiVersion: newAccount.apiVersion || '',
|
||||
deploymentName: newAccount.deploymentName || ''
|
||||
}
|
||||
|
||||
// 如果是分组类型,加载分组ID
|
||||
|
||||
Reference in New Issue
Block a user