更新导入设计

This commit is contained in:
2026-07-03 09:19:56 +08:00
parent 4e2844ff51
commit dbd2d1b79a
2 changed files with 9 additions and 28 deletions
+6 -25
View File
@@ -862,26 +862,12 @@ func (s *TokenService) ImportGrokToken(ctx context.Context, ssoToken, tokenID st
return nil, errors.New("not a grok sso token")
}
sid := grok.SessionIDFromToken(ssoToken)
// Resolve the real account email up front (GET /api/auth/session) for dedup +
// display — the sso session_id rotates per login, so email is the stable id.
email := ""
if s.grok != nil {
s.applyProxy(ctx)
// Best-effort email resolution. A dead/blocked probe must NOT block import:
// land the account and let the async checkPendingGrok disable it if the
// session is truly dead. Empty email just falls back to the session id.
if e, _, ferr := s.grok.FetchSession(ctx, ssoToken); ferr == nil {
email = e
}
}
idKey := email
if idKey == "" {
idKey = sid
}
// Identity is (pool, email): reuse the row for this account, else mint.
if existing, _ := s.tokens.GetByPoolEmail(ctx, "grok", idKey); existing != nil {
tokenID = existing.ID
} else if idKey != "" || tokenID == "" {
// Fully async, no dedup: every import mints a fresh row (a passed-in tokenID is
// an explicit edit → update). We do NOT look up an existing account by
// email/session_id, and we leave account_email empty — email, quota and
// recovery time are all filled off-thread by checkPendingGrok, which also
// disables the account if the sso session is dead.
if strings.TrimSpace(tokenID) == "" {
tokenID = newTokenID("grok")
}
meta := datatypes.JSONMap{"pending_check": true}
@@ -900,11 +886,6 @@ func (s *TokenService) ImportGrokToken(ctx context.Context, ssoToken, tokenID st
return nil, err
}
}
if idKey != "" {
if updated, uerr := s.tokens.Update(ctx, "grok", tokenID, map[string]any{"account_email": idKey}); uerr == nil {
item = updated
}
}
go s.checkPendingGrok(tokenID, ssoToken)
return item, nil
}
+3 -3
View File
@@ -45,7 +45,6 @@ async function doSmartImport() {
const errs = []
for (let i = 0; i < items.length; i++) {
const it = items[i]
setStatus(`正在导入 ${i + 1}/${items.length} (${it.type})…`)
try {
const r = it.type === 'openai'
? await api('/tokens/import-chatgpt-token', jsonBody('POST', { access_token: it.value }))
@@ -77,9 +76,10 @@ async function doSmartImport() {
// Quota isn't checked here — the server probes each token off-thread and the
// account list flips pending → active/dead on its own.
if (fail === 0) {
setStatus(`✓ 导入 ${ok} 项 · 正在后台检测额度…`)
// Close immediately on success — the account lands in the table right away
// and the server backfills quota/email off-thread (pending → active/dead).
emit('imported')
setTimeout(() => emit('close'), 1000)
emit('close')
} else {
setStatus(`成功 ${ok} · 失败 ${fail} · ${errs.slice(0, 3).join(' | ')}`, true)
emit('imported')