Download src/aistudio_api/static/app.js from jlshu/vproxy: direct link, hf CLI and curl.
- Browser
- Download file 7.6 kB
-
https://huggingface.co/spaces/jlshu/vproxy/resolve/main/src/aistudio_api/static/app.js
- Command line
-
hf download hf://spaces/jlshu/vproxy/src/aistudio_api/static/app.js
-
curl -L -o app.js https://huggingface.co/spaces/jlshu/vproxy/resolve/main/src/aistudio_api/static/app.js
7.6 kB
| function app() { | |
| return { | |
| view: 'dashboard', sidebarOpen: false, configOpen: false, openSelect: null, | |
| stats: {}, rotationMode: 'round_robin', rotCfg: { mode: 'round_robin', cooldown: 60 }, | |
| accounts: [], rotationAccounts: {}, activeId: '', activeAccount: {}, | |
| models: [], | |
| auth: { token: '' }, | |
| authEnabled: false, | |
| toast: { show: false, msg: '', t: null }, | |
| cookieModal: { open: false, cookies: '', name: '', email: '', importing: false, autoProbe: true }, | |
| async init() { | |
| await this.checkAuth(); | |
| this.loadFromCache(); | |
| this.loadStats(); | |
| this.loadAccounts(); | |
| this.loadRotation(); | |
| this.$watch('auth.token', () => this.saveToCache()); | |
| document.addEventListener('click', () => this.openSelect = null); | |
| }, | |
| async checkAuth() { | |
| try { | |
| const res = await fetch('/auth/check'); | |
| const data = await res.json(); | |
| this.authEnabled = data.auth_enabled; | |
| if (this.authEnabled) { | |
| const token = localStorage.getItem('asp_api_token'); | |
| if (!token) { | |
| window.location.href = '/static/login.html'; | |
| return; | |
| } | |
| // 验证 token 是否有效(/stats 受鉴权保护) | |
| const verifyRes = await fetch('/stats', { | |
| headers: { 'Authorization': `Bearer ${token}` } | |
| }); | |
| if (!verifyRes.ok) { | |
| localStorage.removeItem('asp_api_token'); | |
| window.location.href = '/static/login.html'; | |
| return; | |
| } | |
| this.auth.token = token; | |
| } | |
| } catch (e) { | |
| console.error('Auth check failed', e); | |
| } | |
| }, | |
| logout() { | |
| localStorage.removeItem('asp_api_token'); | |
| this.auth.token = ''; | |
| window.location.href = '/static/login.html'; | |
| }, | |
| loadFromCache() { | |
| try { | |
| const token = localStorage.getItem('asp_api_token'); | |
| if (token) this.auth.token = token; | |
| } catch (e) { console.error('Cache load error', e); } | |
| }, | |
| saveToCache() { | |
| try { | |
| if (this.auth.token.trim()) localStorage.setItem('asp_api_token', this.auth.token.trim()); | |
| else localStorage.removeItem('asp_api_token'); | |
| } catch (e) { console.error('Cache save error', e); } | |
| }, | |
| clearCache() { | |
| if (!confirm('确定要清理本地缓存吗?')) return; | |
| localStorage.removeItem('asp_api_token'); | |
| location.reload(); | |
| }, | |
| go(v) { this.view = v; this.sidebarOpen = false; if (v === 'dashboard') this.loadStats(); if (v === 'accounts') { this.loadAccounts(); this.loadRotation() } }, | |
| showToast(m) { this.toast.msg = m; this.toast.show = true; if (this.toast.t) clearTimeout(this.toast.t); this.toast.t = setTimeout(() => this.toast.show = false, 3000) }, | |
| toggleSelect(k, e) { e.stopPropagation(); this.openSelect = this.openSelect === k ? null : k }, | |
| selectOpt(k, model, val) { this[model] = val; this.openSelect = null }, | |
| authHeaders(headers = {}) { | |
| const next = { ...headers }; | |
| const token = this.auth.token.trim(); | |
| if (token && !next.Authorization && !next.authorization) next.Authorization = `Bearer ${token}`; | |
| return next; | |
| }, | |
| async apiFetch(url, options = {}) { | |
| const res = await fetch(url, { ...options, headers: this.authHeaders(options.headers || {}) }); | |
| if (res.status === 401) this.showToast('鉴权失败,请检查 API Token'); | |
| return res; | |
| }, | |
| async loadModels() { try { const r = await this.apiFetch('/v1beta/models'); const d = await r.json(); this.models = d.models || []; if (!this.model && this.models.length) this.model = this.models[0].name || this.models[0].id; this.saveToCache(); } catch (e) { } }, | |
| async loadStats() { try { const r = await this.apiFetch('/stats'); const d = await r.json(); this.stats = d.models || {} } catch (e) { } }, | |
| async loadAccounts() { try { const [a, b] = await Promise.all([this.apiFetch('/accounts').then(r => r.json()), this.apiFetch('/accounts/active').then(r => r.json())]); this.accounts = a || []; this.activeId = b?.id || ''; this.activeAccount = b || {} } catch (e) { } }, | |
| async loadRotation() { try { const r = await this.apiFetch('/rotation'); const d = await r.json(); this.rotationMode = d.mode || 'round_robin'; this.rotCfg.mode = d.mode || 'round_robin'; this.rotCfg.cooldown = d.cooldown_seconds || 60; this.rotationAccounts = d.accounts || {} } catch (e) { } }, | |
| get accountRows() { return this.accounts.map(a => ({ ...a, ...(this.rotationAccounts[a.id] || {}) })) }, | |
| get totalReqs() { return Object.values(this.stats).reduce((s, v) => s + (v.requests || 0), 0) }, | |
| get totalRL() { return Object.values(this.stats).reduce((s, v) => s + (v.rate_limited || 0), 0) }, | |
| async saveRotation() { try { await this.apiFetch('/rotation/mode', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ mode: this.rotCfg.mode, cooldown_seconds: this.rotCfg.cooldown }) }); this.showToast('已保存'); this.loadRotation() } catch (e) { this.showToast('保存失败') } }, | |
| async forceNext() { try { await this.apiFetch('/rotation/next', { method: 'POST' }); this.showToast('已切换账号'); this.loadAccounts() } catch (e) { this.showToast('切换失败') } }, | |
| async activateAccount(id) { try { await this.apiFetch(`/accounts/${id}/activate`, { method: 'POST' }); this.showToast('已激活'); this.loadAccounts(); this.loadRotation() } catch (e) { this.showToast('激活失败') } }, | |
| async importCookies() { | |
| const raw = this.cookieModal.cookies.trim(); | |
| if (!raw) { this.showToast('请输入 Cookie'); return } | |
| this.cookieModal.importing = true; | |
| try { | |
| if (this.cookieModal.autoProbe) { | |
| const body = { cookies: raw, name_prefix: this.cookieModal.name.trim() || undefined }; | |
| const r = await this.apiFetch('/accounts/probe-import', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(body) | |
| }); | |
| const d = await r.json(); | |
| if (r.ok) { | |
| this.showToast(`🎉 成功探测并导入 ${d.imported_count} 个多登录账号`); | |
| this.cookieModal.open = false; this.cookieModal.cookies = ''; this.cookieModal.name = ''; this.cookieModal.email = ''; | |
| this.loadAccounts(); this.loadRotation(); | |
| } else { | |
| this.showToast(d.detail || '自动探活导入失败'); | |
| } | |
| } else { | |
| const body = { cookies: raw }; | |
| if (this.cookieModal.name.trim()) body.name = this.cookieModal.name.trim(); | |
| if (this.cookieModal.email.trim()) body.email = this.cookieModal.email.trim(); | |
| const r = await this.apiFetch('/accounts/import-cookies', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify(body) | |
| }); | |
| const d = await r.json(); | |
| if (r.ok) { | |
| this.showToast(`导入成功: ${d.cookie_count} 个 cookie (u/${d.auth_user})`); | |
| this.cookieModal.open = false; this.cookieModal.cookies = ''; this.cookieModal.name = ''; this.cookieModal.email = ''; | |
| this.loadAccounts(); this.loadRotation(); | |
| } else { | |
| this.showToast(d.detail || '导入失败'); | |
| } | |
| } | |
| } catch (e) { | |
| this.showToast('网络错误'); | |
| } finally { | |
| this.cookieModal.importing = false; | |
| } | |
| }, | |
| fmtDate(s) { if (!s) return '-'; try { return new Date(s).toLocaleString() } catch (e) { return s } } | |
| } | |
| } | |