61 lines
2.9 KiB
JavaScript
61 lines
2.9 KiB
JavaScript
/* Guest access uses an ephemeral server session, never a saved browser identity. */
|
|
window.AccountClient = (function () {
|
|
'use strict';
|
|
var kindKey = 'juzi.auth.kind.v1', user = null, guestReady = false;
|
|
function clearGuestCache() {
|
|
try {
|
|
localStorage.removeItem('juzi.identity.v1');
|
|
localStorage.removeItem('juzi.reports.v1'); // Retired local guest-report cache.
|
|
Object.keys(localStorage).filter(function (name) { return name.indexOf('juzi.profile.v1.browser.') === 0; })
|
|
.forEach(function (name) { localStorage.removeItem(name); });
|
|
if (localStorage.getItem(kindKey) === 'browser') localStorage.removeItem(kindKey);
|
|
} catch (_) {}
|
|
}
|
|
function rememberKind() {
|
|
try { if (user && user.kind === 'wechat') localStorage.setItem(kindKey, 'wechat'); else localStorage.removeItem(kindKey); } catch (_) {}
|
|
}
|
|
function request(url, data) {
|
|
var controller = new AbortController();
|
|
// Bound only authentication waits. Full report snapshots contain photos and
|
|
// must retain their existing download budget on a slow mobile connection.
|
|
var timer = url.indexOf('api/auth/') === 0 ? setTimeout(function () { controller.abort(); }, 12000) : null;
|
|
return fetch(url, { credentials: 'same-origin', method: data ? 'POST' : 'GET',
|
|
signal: controller.signal,
|
|
headers: data ? { 'Content-Type': 'application/json' } : {},
|
|
body: data ? JSON.stringify(data) : undefined }).then(function (r) {
|
|
return r.json().then(function (v) { if (!r.ok || !v.ok) throw new Error(v.message || '请求失败'); return v; });
|
|
}).catch(function (error) {
|
|
if (error.name === 'AbortError') throw new Error('网络响应超时,请检查网络后重试');
|
|
throw error;
|
|
}).finally(function () { clearTimeout(timer); });
|
|
}
|
|
function browser(consent) {
|
|
clearGuestCache();
|
|
return request('api/auth/browser', { consent: consent }).then(function (v) {
|
|
user = v.user; guestReady = true; rememberKind(); return v;
|
|
});
|
|
}
|
|
function guest() {
|
|
clearGuestCache();
|
|
user = { id: 'guest-page-' + Date.now() + '-' + Math.random().toString(36).slice(2), kind: 'browser' };
|
|
guestReady = false; rememberKind(); return user;
|
|
}
|
|
function ensureGuest() {
|
|
// The visitor entry is entirely local. Create temporary server access only
|
|
// after explicit consent in the welcome dialog, not on entry/button tap.
|
|
if (!user || user.kind === 'wechat' || guestReady) return Promise.resolve({ user: user });
|
|
return browser(true);
|
|
}
|
|
function init(options) {
|
|
clearGuestCache();
|
|
return request('api/auth/session').then(function (v) {
|
|
user = v.user;
|
|
guestReady = !!(user && user.kind === 'browser');
|
|
rememberKind();
|
|
// Never restore a guest credential or silently fall back from WeChat.
|
|
return v;
|
|
});
|
|
}
|
|
return { request: request, init: init, browser: browser, guest: guest, ensureGuest: ensureGuest, user: function () { return user; } };
|
|
})();
|