feat(h5): 我的页改 H5(mine 页 + shared bridge/api) (#89)

- h5/mine/index.html: 个人中心「我的页」H5 实现
- h5/shared/bridge.js, api.js: H5↔客户端桥与 API 封装(mine 依赖)

Reviewed-on: #89
Co-authored-by: xiebing <xiebing@wonderable.ai>
Co-committed-by: xiebing <xiebing@wonderable.ai>
This commit was merged in pull request #89.
This commit is contained in:
xiebing
2026-06-28 14:16:32 +08:00
committed by marco
parent 1548406f29
commit 2ed62c789f
3 changed files with 7985 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
/**
* SGApi —— H5 调 app-server 后端的薄封装。
*
* 同源:H5 由 app-server 的 /media/h5/ 托管,后端在 /api/v1,同 host:port → 用相对路径、无 CORS。
* 鉴权:JWT Bearer。token 经 SGBridge.getToken() 从原生取(原生持登录态);浏览器调试走 bridge 的 mock token。
* 401:交原生拉登录(requestLogin)兜底,本次请求按失败 reject;正式的 refresh 重试策略阶段2 再补。
*
* 依赖 shared/bridge.js 先加载(取 token)。
*/
(function (global) {
'use strict';
var BASE = '/api/v1';
function authHeaders() {
var t = (global.SGBridge && global.SGBridge.getToken()) || '';
var h = { 'Content-Type': 'application/json' };
if (t) h['Authorization'] = 'Bearer ' + t;
return h;
}
function handle(res) {
if (res.status === 401) {
// 未授权:拉原生登录(异步),本次请求按失败处理,调用方自行决定是否重试
if (global.SGBridge) global.SGBridge.requestLogin();
return Promise.reject(new Error('unauthorized'));
}
if (!res.ok) {
return res.text().then(function (t) {
return Promise.reject(new Error('http ' + res.status + ' ' + t));
});
}
// 204 / 空体兜底
return res.text().then(function (t) { return t ? JSON.parse(t) : null; });
}
/** GET /api/v1<path>。path 以 / 开头,如 '/savings/battle'。 */
function apiGet(path) {
return fetch(BASE + path, { method: 'GET', headers: authHeaders() }).then(handle);
}
/** POST /api/v1<path>body 自动 JSON 序列化。 */
function apiPost(path, body) {
return fetch(BASE + path, {
method: 'POST',
headers: authHeaders(),
body: JSON.stringify(body || {}),
}).then(handle);
}
global.SGApi = { base: BASE, get: apiGet, post: apiPost };
})(window);