Skip to content

Commit eb2b863

Browse files
committed
fix(frontend): 修复 Grok OAuth 建号缺上游配置入口与 JSON 导入渲染崩溃
- CreateAccountModal 为 Grok OAuth 新增自定义上游地址与请求头覆写区块, 经统一校验注入授权码兑换/RT 批量/SSO 批量三条创建路径(授权码路径 在兑换前校验,避免烧掉一次性 code) - JSON 导入示例文案内嵌花括号被 vue-i18n 消息编译器当占位符解析, 渲染时抛 Invalid token in placeholder 炸掉面板:示例移出 i18n 硬编码; 同类修复 settings 的死键 claudeOAuthSystemPromptBlocksPlaceholder(删) 与 Hint 中被吞掉的 {billing_header}(字面量转义) - 新增 localesMessageCompile 守卫测试:预编译中英全部文案,拦截非法占位符 - 面板打开后 scrollIntoView + 聚焦,避免在弹窗滚动容器视野外展开 - 删除「填入模板」按钮及三平台模板常量(产品决策:无意义) - 抽取 HeaderOverrideEditor 共享组件,消除 Create/Edit/BulkEdit 三处重复
1 parent be6cd12 commit eb2b863

13 files changed

Lines changed: 298 additions & 371 deletions

‎frontend/src/components/account/BulkEditAccountModal.vue‎

Lines changed: 5 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -538,75 +538,10 @@
538538
{{ t('admin.accounts.headerOverride.bulkReplaceHint') }}
539539
</p>
540540

541-
<div v-if="headerOverrideRows.length > 0" class="space-y-2">
542-
<div
543-
v-for="(row, index) in headerOverrideRows"
544-
:key="getHeaderOverrideRowKey(row)"
545-
class="flex items-center gap-2"
546-
>
547-
<input
548-
v-model="row.name"
549-
type="text"
550-
class="input flex-1"
551-
:placeholder="t('admin.accounts.headerOverride.namePlaceholder')"
552-
/>
553-
<input
554-
v-model="row.value"
555-
type="text"
556-
class="input flex-1"
557-
:placeholder="t('admin.accounts.headerOverride.valuePlaceholder')"
558-
/>
559-
<button
560-
type="button"
561-
class="rounded-lg p-2 text-red-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20"
562-
@click="removeHeaderOverrideRow(index)"
563-
>
564-
<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
565-
<path
566-
stroke-linecap="round"
567-
stroke-linejoin="round"
568-
stroke-width="2"
569-
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
570-
/>
571-
</svg>
572-
</button>
573-
</div>
574-
</div>
575-
576-
<button
577-
type="button"
578-
class="w-full rounded-lg border-2 border-dashed border-gray-300 px-4 py-2 text-gray-600 transition-colors hover:border-gray-400 hover:text-gray-700 dark:border-dark-500 dark:text-gray-400 dark:hover:border-dark-400 dark:hover:text-gray-300"
579-
@click="addHeaderOverrideRow"
580-
>
581-
<svg class="mr-1 inline h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
582-
<path
583-
stroke-linecap="round"
584-
stroke-linejoin="round"
585-
stroke-width="2"
586-
d="M12 4v16m8-8H4"
587-
/>
588-
</svg>
589-
{{ t('admin.accounts.headerOverride.addRow') }}
590-
</button>
591-
592-
<div class="flex flex-wrap gap-2">
593-
<button
594-
v-if="headerOverrideTemplatePlatform"
595-
type="button"
596-
class="rounded-lg bg-primary-50 px-3 py-1 text-xs text-primary-700 transition-colors hover:bg-primary-100 dark:bg-primary-900/30 dark:text-primary-400 dark:hover:bg-primary-900/50"
597-
@click="fillHeaderOverrideTemplate"
598-
>
599-
+ {{ t('admin.accounts.headerOverride.fillTemplate') }}
600-
</button>
601-
<HeaderOverrideJsonTools
602-
:rows="headerOverrideRows"
603-
@update:rows="headerOverrideRows = $event"
604-
/>
605-
</div>
606-
607-
<p class="text-xs text-gray-500 dark:text-gray-400">
608-
{{ t('admin.accounts.headerOverride.emptyValueHint') }}
609-
</p>
541+
<HeaderOverrideEditor
542+
:rows="headerOverrideRows"
543+
@update:rows="headerOverrideRows = $event"
544+
/>
610545
</div>
611546
<p v-else class="text-xs text-gray-500 dark:text-gray-400">
612547
{{ t('admin.accounts.headerOverride.bulkDisableHint') }}
@@ -1277,17 +1212,15 @@ import {
12771212
buildModelMappingObject as buildModelMappingPayload,
12781213
getPresetMappingsByPlatform
12791214
} from '@/composables/useModelWhitelist'
1280-
import HeaderOverrideJsonTools from '@/components/account/HeaderOverrideJsonTools.vue'
1215+
import HeaderOverrideEditor from '@/components/account/HeaderOverrideEditor.vue'
12811216
import {
12821217
buildHeaderOverridesObject,
1283-
getHeaderOverrideTemplate,
12841218
isHeaderOverrideCapable,
12851219
validateHeaderOverrideRows,
12861220
HEADER_OVERRIDE_ENABLED_CREDENTIAL_KEY,
12871221
HEADER_OVERRIDES_CREDENTIAL_KEY,
12881222
type HeaderOverrideRow
12891223
} from '@/components/account/credentialsBuilder'
1290-
import { createStableObjectKeyResolver } from '@/utils/stableObjectKey'
12911224
import {
12921225
OPENAI_WS_MODE_CTX_POOL,
12931226
OPENAI_WS_MODE_OFF,
@@ -1436,37 +1369,6 @@ const customErrorCodeInput = ref<number | null>(null)
14361369
const interceptWarmupRequests = ref(false)
14371370
const headerOverrideEnabled = ref(false)
14381371
const headerOverrideRows = ref<HeaderOverrideRow[]>([])
1439-
const getHeaderOverrideRowKey = createStableObjectKeyResolver<HeaderOverrideRow>('bulk-header-override-row')
1440-
1441-
const addHeaderOverrideRow = () => {
1442-
headerOverrideRows.value.push({ name: '', value: '' })
1443-
}
1444-
1445-
const removeHeaderOverrideRow = (index: number) => {
1446-
headerOverrideRows.value.splice(index, 1)
1447-
}
1448-
1449-
// 模板仅在所选账号平台唯一时可用:混合 anthropic+openai 选择无法确定用哪套模板,
1450-
// 误填会把另一平台的专有头写进所有所选账号
1451-
const headerOverrideTemplatePlatform = computed(() => {
1452-
return targetSelectedPlatforms.value.length === 1 ? targetSelectedPlatforms.value[0] : null
1453-
})
1454-
1455-
// 模板按钮:填入所选平台的标准客户端请求头名称(值留空),跳过已存在的同名行
1456-
const fillHeaderOverrideTemplate = () => {
1457-
const platform = headerOverrideTemplatePlatform.value
1458-
if (!platform) return
1459-
const existing = new Set(
1460-
headerOverrideRows.value.map((row) => row.name.trim().toLowerCase()).filter(Boolean)
1461-
)
1462-
const rows = headerOverrideRows.value.filter((row) => row.name.trim() || row.value.trim())
1463-
for (const row of getHeaderOverrideTemplate(platform)) {
1464-
if (!existing.has(row.name)) {
1465-
rows.push(row)
1466-
}
1467-
}
1468-
headerOverrideRows.value = rows
1469-
}
14701372
const proxyId = ref<number | null>(null)
14711373
const concurrency = ref(1)
14721374
const loadFactor = ref<number | null>(null)

0 commit comments

Comments
 (0)