/* 官网共享登录态助手:与 Web 版 App(shared_preferences_web)共享 localStorage['flutter.*'](值为 JSON 编码)。access token 60 分钟过期, 官网页面不常驻刷新,所以请求 401 时用 refresh_token 自动续签并重试一次, 仍失败才交回调用方跳登录。零依赖。 */ (function () { function get(key) { var raw = localStorage.getItem('flutter.' + key); if (raw === null) return null; try { return JSON.parse(raw); } catch (e) { return raw; } } function set(key, val) { localStorage.setItem('flutter.' + key, JSON.stringify(val)); } function refresh(apiBase) { var rt = get('refresh_token'); if (!rt) return Promise.resolve(false); return fetch(apiBase + '/api/v1/auth/refresh', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refresh_token: rt }), }) .then(function (r) { return r.ok ? r.json() : null; }) .then(function (j) { var d = j && j.data; if (!d || !d.access_token) return false; set('access_token', d.access_token); if (d.refresh_token) set('refresh_token', d.refresh_token); // refresh token 会轮换 return true; }) .catch(function () { return false; }); } function authFetch(apiBase, path, opts) { opts = opts || {}; function doFetch() { var headers = Object.assign({}, opts.headers, { Authorization: 'Bearer ' + get('access_token') }); return fetch(apiBase + path, Object.assign({}, opts, { headers: headers })); } return doFetch().then(function (r) { if (r.status !== 401) return r; return refresh(apiBase).then(function (ok) { return ok ? doFetch() : r; }); }); } /* 是否可视为登录:access 过期但 refresh 还在(7 天),authFetch 会自动续 */ function loggedIn() { return !!(get('access_token') || get('refresh_token')); } /* 退出登录:清凭证与身份,保留 shop_no/username 供登录页回填 */ function clear() { ['access_token', 'refresh_token', 'user_id', 'real_name', 'role', 'shop_id'].forEach(function (k) { localStorage.removeItem('flutter.' + k); }); } window.jiuAuth = { get: get, set: set, refresh: refresh, authFetch: authFetch, loggedIn: loggedIn, clear: clear }; })();