重构 monorepo 并完善网页端订阅与首页体验
- 迁移为 frontend-web、frontend-electron、backend-web 与 docker 部署结构 - 网页端:订阅门禁二次弹窗、套餐/支付组件化、顶栏分组对齐 - 首页:最近文件与模板库布局优化,缩略图对齐,下载与删除操作 - 新增管理后台、支付与云端文件 API,更新 README 与项目规范 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var refreshPromise = null;
|
||||
|
||||
function getAccessToken() {
|
||||
try { return localStorage.getItem('soon_access') || ''; } catch (e) { return ''; }
|
||||
}
|
||||
|
||||
function getRefreshToken() {
|
||||
try { return localStorage.getItem('soon_refresh') || ''; } catch (e) { return ''; }
|
||||
}
|
||||
|
||||
function clearSession() {
|
||||
try {
|
||||
localStorage.removeItem('soon_access');
|
||||
localStorage.removeItem('soon_refresh');
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function getApiBase() {
|
||||
var cfg = (typeof window !== 'undefined' && window.SOON_DEPLOY_CONFIG && window.SOON_DEPLOY_CONFIG.api_v1_base);
|
||||
if (cfg) return String(cfg).replace(/\/+$/, '');
|
||||
if (typeof window !== 'undefined' && window.location) {
|
||||
return window.location.origin + '/api/v1';
|
||||
}
|
||||
return '/api/v1';
|
||||
}
|
||||
|
||||
function redirectToLogin() {
|
||||
var path = 'login.web.html';
|
||||
try {
|
||||
var current = window.location.pathname.replace(/^.*\/pages\//, '').replace(/^\//, '');
|
||||
if (current && current.indexOf('login.web.html') !== 0) {
|
||||
var redirect = typeof soonSafeRedirect === 'function'
|
||||
? soonSafeRedirect(current + window.location.search, 'index.web.html')
|
||||
: 'index.web.html';
|
||||
path = 'login.web.html?redirect=' + encodeURIComponent(redirect);
|
||||
}
|
||||
} catch (e) { /* use default */ }
|
||||
window.location.href = path;
|
||||
}
|
||||
|
||||
function refreshAccessToken() {
|
||||
if (refreshPromise) return refreshPromise;
|
||||
var refresh = getRefreshToken();
|
||||
if (!refresh) {
|
||||
return Promise.reject(new Error('no_refresh_token'));
|
||||
}
|
||||
refreshPromise = fetch(getApiBase() + '/auth/refresh', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ refresh_token: refresh }),
|
||||
}).then(function (r) {
|
||||
return r.json().then(function (j) {
|
||||
if (!r.ok || !j.ok || !j.data || !j.data.access_token) {
|
||||
throw new Error(j.message || 'refresh_failed');
|
||||
}
|
||||
localStorage.setItem('soon_access', j.data.access_token);
|
||||
if (j.data.refresh_token) {
|
||||
localStorage.setItem('soon_refresh', j.data.refresh_token);
|
||||
}
|
||||
return j.data.access_token;
|
||||
});
|
||||
}).finally(function () {
|
||||
refreshPromise = null;
|
||||
});
|
||||
return refreshPromise;
|
||||
}
|
||||
|
||||
function soonAuthedFetch(url, opts) {
|
||||
opts = opts || {};
|
||||
var headers = Object.assign({}, opts.headers || {});
|
||||
var token = getAccessToken();
|
||||
if (token) {
|
||||
headers['Authorization'] = 'Bearer ' + token;
|
||||
} else {
|
||||
delete headers['Authorization'];
|
||||
delete headers['authorization'];
|
||||
}
|
||||
opts.headers = headers;
|
||||
|
||||
var fullUrl = url;
|
||||
if (url.indexOf('http') !== 0) {
|
||||
fullUrl = getApiBase() + '/' + String(url).replace(/^\/+/, '');
|
||||
}
|
||||
|
||||
return fetch(fullUrl, opts).then(function (response) {
|
||||
if (response.status !== 401) return response;
|
||||
return refreshAccessToken().then(function (newToken) {
|
||||
var retryHeaders = Object.assign({}, opts.headers || {});
|
||||
retryHeaders['Authorization'] = 'Bearer ' + newToken;
|
||||
var retryOpts = Object.assign({}, opts, { headers: retryHeaders });
|
||||
return fetch(fullUrl, retryOpts);
|
||||
}).catch(function () {
|
||||
clearSession();
|
||||
redirectToLogin();
|
||||
return response;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.soonAuthedFetch = soonAuthedFetch;
|
||||
window.soonClearAuthSession = clearSession;
|
||||
window.soonGetAccessToken = getAccessToken;
|
||||
window.soonRedirectToLogin = redirectToLogin;
|
||||
})();
|
||||
Reference in New Issue
Block a user