fix(site): 官网 401 自动用 refresh_token 续签重试;资产加构建版本号破缓存

- 新增共享 auth.js(jiuAuth):access token 60 分钟过期后,checkout 提交/
  结果页轮询遇 401 自动 POST /auth/refresh 换新 token 并重试一次,仍失败
  才跳登录——修复「已登录点提交订单却被踢回登录页」
- 登录判定放宽为 access 或 refresh token 任一存在(refresh 7 天有效)
- 所有 JS/CSS 引用加 ?v=构建版本号:修复旧版 nav.js 被浏览器缓存后在新
  页面执行(右上角错位的旧用户面板、带引号的 "张三" 显示)
- nav.js 改经 jiuAuth 读 localStorage(JSON 解码,去掉引号显示)
- 登录页回填上次的门店编号与账号

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
This commit is contained in:
wangjia
2026-07-03 21:08:13 +08:00
parent 71909a76d7
commit c010d8b416
8 changed files with 76 additions and 26 deletions
+48
View File
@@ -0,0 +1,48 @@
/* 官网共享登录态助手:与 Web 版 Appshared_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')); }
window.jiuAuth = { get: get, set: set, refresh: refresh, authFetch: authFetch, loggedIn: loggedIn };
})();