mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-30 16:23:31 +00:00
feat(zhipu): support team GLM Coding Plan usage query
Team GLM Coding Plan accounts fail the quota probe with "当前用户不存在coding plan" because the personal-plan query path does not carry team context. - quota probe: when credentials contain zhipu_organization, switch the Zhipu quota endpoint to the team variant (?type=2 + bigmodel-organization / bigmodel-project headers); personal plans keep the existing path - account create/edit modals: optional organization/project ID inputs for zhipu coding-plan accounts, persisted in credentials; edit modal backfills them and clears back to personal plan when emptied - add a click-to-open tooltip tutorial (zh/en) explaining how to grab the IDs from the bigmodel.cn web console via the /api/biz/v1/organization network request, with a sample URL mapping org-/proj_ segments to fields
This commit is contained in:
@@ -547,6 +547,36 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Zhipu 团队版 Coding Plan:组织/项目 ID(可选,填写后额度探测走团队版端点) -->
|
||||
<div v-if="form.platform === 'zhipu' && accountMode === 'coding'" class="mt-4">
|
||||
<div class="flex items-center">
|
||||
<label class="input-label">{{ t('admin.accounts.cnProviders.zhipuTeam.title') }}</label>
|
||||
<HelpTooltip trigger="click" width-class="w-80">
|
||||
<p class="mb-1 font-medium">{{ t('admin.accounts.cnProviders.zhipuTeam.help.title') }}</p>
|
||||
<ol class="list-decimal space-y-1 pl-4">
|
||||
<li>{{ t('admin.accounts.cnProviders.zhipuTeam.help.step1') }}</li>
|
||||
<li>{{ t('admin.accounts.cnProviders.zhipuTeam.help.step2') }}</li>
|
||||
<li>{{ t('admin.accounts.cnProviders.zhipuTeam.help.step3') }}</li>
|
||||
<li>{{ t('admin.accounts.cnProviders.zhipuTeam.help.step4') }}</li>
|
||||
</ol>
|
||||
<p class="mt-2 break-all rounded bg-black/20 p-1.5 font-mono text-[11px] leading-relaxed">
|
||||
{{ t('admin.accounts.cnProviders.zhipuTeam.help.example') }}
|
||||
</p>
|
||||
</HelpTooltip>
|
||||
</div>
|
||||
<div class="mt-2 grid gap-4 sm:grid-cols-2">
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.cnProviders.zhipuTeam.organization') }}</label>
|
||||
<input v-model="zhipuOrganization" type="text" class="input" :placeholder="t('admin.accounts.cnProviders.zhipuTeam.organizationPlaceholder')" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.cnProviders.zhipuTeam.project') }}</label>
|
||||
<input v-model="zhipuProject" type="text" class="input" :placeholder="t('admin.accounts.cnProviders.zhipuTeam.projectPlaceholder')" />
|
||||
</div>
|
||||
</div>
|
||||
<p class="input-hint mt-2">{{ t('admin.accounts.cnProviders.zhipuTeam.hint') }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Account Type Selection (Gemini) -->
|
||||
<div v-if="form.platform === 'gemini'">
|
||||
<div class="flex items-center justify-between">
|
||||
@@ -3764,6 +3794,7 @@ import type {
|
||||
import BaseDialog from '@/components/common/BaseDialog.vue'
|
||||
import ConfirmDialog from '@/components/common/ConfirmDialog.vue'
|
||||
import Select from '@/components/common/Select.vue'
|
||||
import HelpTooltip from '@/components/common/HelpTooltip.vue'
|
||||
import PlatformIcon from '@/components/common/PlatformIcon.vue'
|
||||
import Icon from '@/components/icons/Icon.vue'
|
||||
import ProxySelector from '@/components/common/ProxySelector.vue'
|
||||
@@ -3969,6 +4000,9 @@ const accountMode = ref<CnAccountMode>('payg')
|
||||
// API 协议决定转发端点与格式:cc=现有转换链,anthropic=原生直通(Claude Code),
|
||||
// responses=deepseek 原生 Responses 端点(Codex)。与账号类型正交。
|
||||
const apiProtocol = ref<CnApiProtocol>('adaptive')
|
||||
// 智谱团队版 Coding Plan:组织/项目 ID,写入 credentials 供额度探测切换团队端点
|
||||
const zhipuOrganization = ref('')
|
||||
const zhipuProject = ref('')
|
||||
const adaptiveBaseUrls = ref<Record<CnNativeApiProtocol, string>>({
|
||||
chat_completions: '',
|
||||
anthropic: '',
|
||||
@@ -5544,6 +5578,11 @@ const handleSubmit = async () => {
|
||||
if (apiProtocol.value !== 'adaptive' && resolvedCNBase) {
|
||||
credentials.base_url = resolvedCNBase
|
||||
}
|
||||
// 智谱团队版 Coding Plan:组织/项目 ID 写入凭据(非空才写)
|
||||
if (form.platform === 'zhipu' && accountMode.value === 'coding') {
|
||||
if (zhipuOrganization.value.trim()) credentials.zhipu_organization = zhipuOrganization.value.trim()
|
||||
if (zhipuProject.value.trim()) credentials.zhipu_project = zhipuProject.value.trim()
|
||||
}
|
||||
}
|
||||
|
||||
// Add model mapping if configured(OpenAI 开启自动透传时不应用)
|
||||
|
||||
@@ -118,6 +118,35 @@
|
||||
</div>
|
||||
<p class="input-hint">{{ t(`admin.accounts.cnProviders.apiProtocol.${cnProtocolDescKey}Desc`) }}</p>
|
||||
</div>
|
||||
<!-- Zhipu 团队版 Coding Plan:组织/项目 ID(可选,填写后用量查询走团队版端点) -->
|
||||
<div v-if="account.platform === 'zhipu' && editAccountMode === 'coding'">
|
||||
<div class="flex items-center">
|
||||
<label class="input-label">{{ t('admin.accounts.cnProviders.zhipuTeam.title') }}</label>
|
||||
<HelpTooltip trigger="click" width-class="w-80">
|
||||
<p class="mb-1 font-medium">{{ t('admin.accounts.cnProviders.zhipuTeam.help.title') }}</p>
|
||||
<ol class="list-decimal space-y-1 pl-4">
|
||||
<li>{{ t('admin.accounts.cnProviders.zhipuTeam.help.step1') }}</li>
|
||||
<li>{{ t('admin.accounts.cnProviders.zhipuTeam.help.step2') }}</li>
|
||||
<li>{{ t('admin.accounts.cnProviders.zhipuTeam.help.step3') }}</li>
|
||||
<li>{{ t('admin.accounts.cnProviders.zhipuTeam.help.step4') }}</li>
|
||||
</ol>
|
||||
<p class="mt-2 break-all rounded bg-black/20 p-1.5 font-mono text-[11px] leading-relaxed">
|
||||
{{ t('admin.accounts.cnProviders.zhipuTeam.help.example') }}
|
||||
</p>
|
||||
</HelpTooltip>
|
||||
</div>
|
||||
<div class="mt-2 grid gap-4 sm:grid-cols-2">
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.cnProviders.zhipuTeam.organization') }}</label>
|
||||
<input v-model="editZhipuOrganization" type="text" class="input" :placeholder="t('admin.accounts.cnProviders.zhipuTeam.organizationPlaceholder')" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.cnProviders.zhipuTeam.project') }}</label>
|
||||
<input v-model="editZhipuProject" type="text" class="input" :placeholder="t('admin.accounts.cnProviders.zhipuTeam.projectPlaceholder')" />
|
||||
</div>
|
||||
</div>
|
||||
<p class="input-hint mt-2">{{ t('admin.accounts.cnProviders.zhipuTeam.hint') }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<label class="input-label">{{ t('admin.accounts.apiKey') }}</label>
|
||||
<input
|
||||
@@ -2854,6 +2883,7 @@ import type {
|
||||
import BaseDialog from '@/components/common/BaseDialog.vue'
|
||||
import ConfirmDialog from '@/components/common/ConfirmDialog.vue'
|
||||
import Select from '@/components/common/Select.vue'
|
||||
import HelpTooltip from '@/components/common/HelpTooltip.vue'
|
||||
import Toggle from '@/components/common/Toggle.vue'
|
||||
import Icon from '@/components/icons/Icon.vue'
|
||||
import ProxySelector from '@/components/common/ProxySelector.vue'
|
||||
@@ -2987,6 +3017,9 @@ const cnPresetPlatform = computed<'kimi' | 'zhipu' | 'deepseek'>(() => {
|
||||
})
|
||||
const editApiProtocol = ref<CnApiProtocol>('adaptive')
|
||||
const editAccountMode = ref<CnAccountMode>('payg')
|
||||
// 智谱团队版 Coding Plan:组织/项目 ID,写入 credentials 供额度探测切换团队端点
|
||||
const editZhipuOrganization = ref('')
|
||||
const editZhipuProject = ref('')
|
||||
const editAdaptiveBaseUrls = ref<Record<CnNativeApiProtocol, string>>({
|
||||
chat_completions: '',
|
||||
anthropic: '',
|
||||
@@ -3939,6 +3972,11 @@ const syncFormFromAccount = (newAccount: Account | null) => {
|
||||
nextAdaptiveBaseUrls[legacyProtocol] = legacyBaseUrl
|
||||
}
|
||||
editAdaptiveBaseUrls.value = nextAdaptiveBaseUrls
|
||||
// 智谱团队版 Coding Plan:回填组织/项目 ID
|
||||
if (newAccount.platform === 'zhipu') {
|
||||
editZhipuOrganization.value = typeof credentials.zhipu_organization === 'string' ? credentials.zhipu_organization : ''
|
||||
editZhipuProject.value = typeof credentials.zhipu_project === 'string' ? credentials.zhipu_project : ''
|
||||
}
|
||||
}
|
||||
const platformDefaultUrl =
|
||||
newAccount.platform === 'openai'
|
||||
@@ -4648,6 +4686,19 @@ const handleSubmit = async () => {
|
||||
} else {
|
||||
delete newCredentials.api_base_urls
|
||||
}
|
||||
// 智谱团队版 Coding Plan:组织/项目 ID 写入凭据(非空才写,清空即移除回落个人版路径)
|
||||
if (props.account.platform === 'zhipu') {
|
||||
const org = editZhipuOrganization.value.trim()
|
||||
const project = editZhipuProject.value.trim()
|
||||
if (org) {
|
||||
newCredentials.zhipu_organization = org
|
||||
if (project) newCredentials.zhipu_project = project
|
||||
else delete newCredentials.zhipu_project
|
||||
} else {
|
||||
delete newCredentials.zhipu_organization
|
||||
delete newCredentials.zhipu_project
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle API key
|
||||
|
||||
Reference in New Issue
Block a user