@@ -22,15 +22,18 @@ import { t } from '../../i18n'
2222
2323const props = defineProps <{ projectWorkspaces: ProjectWorkspaceDto [] }>()
2424
25- const managementSecret = ref (getMcpManagementCredential ())
25+ const initialCredential = getMcpManagementCredential ()
26+ const managementSecret = ref (initialCredential )
27+ const credentialInput = ref (initialCredential ?? ' ' )
2628const rememberCredential = ref (hasRememberedMcpManagementCredential ())
2729const keys = ref <McpApiKeyDto []>([])
2830const isLoading = ref (false )
2931const isSaving = ref (false )
32+ const isAuthenticated = ref (false )
3033const error = ref (' ' )
3134const notice = ref (' ' )
3235const revealedSecret = ref (' ' )
33- const connected = computed (() => Boolean ( managementSecret .value ) )
36+ const connected = computed (() => isAuthenticated .value )
3437const projectOptions = computed (() => mcpKeyProjectOptions (props .projectWorkspaces ))
3538
3639const createForm = reactive <CreateMcpApiKeyRequestDto >({
@@ -56,19 +59,23 @@ const permissionOptions: Array<{ value: McpPermission; label: string; hint: stri
5659 { value: ' sensitive.read' , label: ' 敏感内容读取' , hint: ' 读取脚本源码或流程字面量' },
5760]
5861
59- async function loadKeys(): Promise <void > {
60- if (! managementSecret . value ) return
62+ async function loadKeys(secret = managementSecret . value ): Promise <boolean > {
63+ if (! secret ) return false
6164 isLoading .value = true
6265 error .value = ' '
6366 try {
64- keys .value = await listMcpApiKeys (managementSecret .value )
67+ keys .value = await listMcpApiKeys (secret )
68+ managementSecret .value = secret
69+ isAuthenticated .value = true
70+ return true
6571 } catch (exception ) {
6672 if (exception instanceof McpApiError && exception .status === 401 ) {
6773 clearCredential ()
6874 error .value = t (' console.mcpKeyUnauthorized' )
6975 } else {
7076 error .value = errorMessage (exception )
7177 }
78+ return false
7279 } finally {
7380 isLoading .value = false
7481 }
@@ -81,6 +88,8 @@ async function setupKey(): Promise<void> {
8188 try {
8289 const created = await setupMcpApiKey ()
8390 managementSecret .value = created .secret
91+ credentialInput .value = created .secret
92+ isAuthenticated .value = true
8493 storeMcpManagementCredential (created .secret , rememberCredential .value )
8594 revealedSecret .value = created .secret
8695 notice .value = t (' console.mcpKeyCreated' )
@@ -93,14 +102,17 @@ async function setupKey(): Promise<void> {
93102}
94103
95104async function connectKey(): Promise <void > {
96- const candidate = managementSecret .value ?.trim ()
105+ if (isLoading .value || isSaving .value ) return
106+ const candidate = credentialInput .value .trim ()
97107 if (! candidate ) {
98108 error .value = t (' console.mcpKeyRequired' )
99109 return
100110 }
101- storeMcpManagementCredential (candidate , rememberCredential .value )
102- managementSecret .value = candidate
103- await loadKeys ()
111+ notice .value = ' '
112+ if (await loadKeys (candidate )) {
113+ storeMcpManagementCredential (candidate , rememberCredential .value )
114+ notice .value = t (' console.mcpKeyConnected' )
115+ }
104116}
105117
106118async function createKey(): Promise <void > {
@@ -189,6 +201,8 @@ async function copySecret(): Promise<void> {
189201function clearCredential(): void {
190202 clearMcpManagementCredential ()
191203 managementSecret .value = undefined
204+ credentialInput .value = ' '
205+ isAuthenticated .value = false
192206 keys .value = []
193207 revealedSecret .value = ' '
194208}
@@ -225,7 +239,7 @@ onMounted(() => { void loadKeys() })
225239 <h2 id =" mcp-key-settings-title" ><KeyRound :size =" 17 " />{{ t('console.mcpKeyTitle') }}</h2 >
226240 <p >{{ t('console.mcpKeyHint') }}</p >
227241 </div >
228- <button v-if =" connected" class =" icon-button" type =" button" :title =" t('console.mcpKeyRefresh')" :aria-label =" t('console.mcpKeyRefresh')" :disabled =" isLoading" @click =" loadKeys" ><RefreshCw :size =" 15 " :class =" { ' is-spinning' : isLoading } " /></button >
242+ <button v-if =" connected" class =" icon-button" type =" button" :title =" t('console.mcpKeyRefresh')" :aria-label =" t('console.mcpKeyRefresh')" :disabled =" isLoading" @click =" loadKeys() " ><RefreshCw :size =" 15 " :class =" { ' is-spinning' : isLoading } " /></button >
229243 </div >
230244
231245 <p v-if =" error" class =" mcp-key-settings__message mcp-key-settings__message--error" role =" alert" >{{ error }}</p >
@@ -240,9 +254,9 @@ onMounted(() => { void loadKeys() })
240254
241255 <div v-if =" !connected" class =" mcp-key-settings__connect" >
242256 <div class =" mcp-key-settings__empty" ><LockKeyhole :size =" 20 " /><div ><strong >{{ t('console.mcpKeyConnectTitle') }}</strong ><p >{{ t('console.mcpKeyConnectHint') }}</p ></div ></div >
243- <label class =" mcp-key-settings__credential" ><span >{{ t('console.mcpKeySecretLabel') }}</span ><input v-model =" managementSecret " type =" password" autocomplete =" off" :placeholder =" t('console.mcpKeySecretPlaceholder')" @keyup.enter =" connectKey" /></label >
257+ <label class =" mcp-key-settings__credential" ><span >{{ t('console.mcpKeySecretLabel') }}</span ><input v-model =" credentialInput " type =" password" autocomplete =" off" :placeholder =" t('console.mcpKeySecretPlaceholder')" @keyup.enter =" connectKey" /></label >
244258 <label class =" mcp-key-settings__remember" ><input v-model =" rememberCredential" type =" checkbox" /><span >{{ t('console.mcpKeyRemember') }}</span ></label >
245- <div class =" mcp-key-settings__actions" ><button class =" command-button run" type =" button" :disabled =" isSaving" @click =" connectKey" ><ShieldCheck :size =" 15 " /><span >{{ t('console.mcpKeyConnect') }}</span ></button ><button class =" command-button quiet" type =" button" :disabled =" isSaving" @click =" setupKey" ><Plus :size =" 15 " /><span >{{ t('console.mcpKeySetup') }}</span ></button ></div >
259+ <div class =" mcp-key-settings__actions" ><button class =" command-button run" type =" button" :disabled =" isSaving || isLoading " @click =" connectKey" ><ShieldCheck :size =" 15 " /><span >{{ t('console.mcpKeyConnect') }}</span ></button ><button class =" command-button quiet" type =" button" :disabled =" isSaving || isLoading " @click =" setupKey" ><Plus :size =" 15 " /><span >{{ t('console.mcpKeySetup') }}</span ></button ></div >
246260 </div >
247261
248262 <template v-else >
0 commit comments