Files
huangjingfen/pro_v3.5.1_副本/view/uniapp/uni-h5-polyfill.js

189 lines
6.5 KiB
JavaScript
Raw Normal View History

feat(fsgx): 完成全部24项开发任务 Phase1-7 Phase1 后端核心: - 新增 fsgx_v1.sql 迁移脚本(is_queue_goods/frozen_points/available_points/no_assess) - SystemConfigServices 返佣设置扩展(周期人数/分档比例/范围/时机) - StoreOrderCreateServices 周期循环佣金计算 - StoreOrderTakeServices 佣金发放后同步冻结积分 - StoreProductServices/StoreProduct 保存 is_queue_goods Phase2 后端接口: - GET /api/hjf/brokerage/progress 佣金周期进度 - GET /api/hjf/assets/overview 资产总览 - HjfPointsServices 每日 frozen_points 0.4‰ 释放定时任务 - PUT /adminapi/hjf/member/{uid}/no_assess 不考核接口 - GET /adminapi/hjf/points/release_log 积分日志接口 Phase3 前端清理: - hjfCustom.js 路由精简(仅保留 points/log) - hjfQueue.js/hjfMember.js API 清理/重定向至 CRMEB 原生接口 - pages.json 公排→推荐佣金/佣金记录/佣金规则 Phase4-5 前端改造: - queue/status.vue 推荐佣金进度页整体重写 - 商品详情/订单确认/支付结果页文案与逻辑改造 - 个人中心/资产页/引导页/规则页文案改造 - HjfQueueProgress/HjfRefundNotice/HjfAssetCard 组件改造 - 推广中心嵌入佣金进度摘要 - hjfMockData.js 全量更新(公排字段→佣金字段) Phase6 Admin 增强: - 用户列表新增 frozen_points/available_points 列及不考核操作按钮 - hjfPoints.js USE_MOCK=false 对接真实积分日志接口 Phase7 配置文档: - docs/fsgx-phase7-config-checklist.md 后台配置与全链路验收清单 Made-with: Cursor
2026-03-23 22:32:19 +08:00
/**
* H5 polyfill: UniApp 框架初始化完成前 uni API 提供浏览器降级实现
*
* 核心策略
* - Object.defineProperty 拦截 window.uni 的赋值防止 UniApp 运行时
* 用存根对象覆盖我们的实现
* - UniApp stub 对象赋给 window.uni stub 合并到我们的代理
* 对象中同时保留我们对"未实现"API 的真实降级实现
* - 之后 UniApp 注册真正的 H5 实现 uni.request = xhrImpl属性直接
* 写到代理对象上我们的 polyfill 就会被替换互不干扰
*/
;(function () {
if (typeof window === 'undefined') return;
/* -------- 各 API 的降级实现 -------- */
var polyfills = {};
// uni.request → XHR
polyfills.request = function (opts) {
opts = opts || {};
var xhr = new XMLHttpRequest();
var method = (opts.method || 'GET').toUpperCase();
var url = opts.url || '';
// GET/HEAD 把 data 追加到 query string
if (opts.data && (method === 'GET' || method === 'HEAD')) {
var qs = Object.keys(opts.data).map(function (k) {
return encodeURIComponent(k) + '=' + encodeURIComponent(opts.data[k]);
}).join('&');
if (qs) url += (url.indexOf('?') >= 0 ? '&' : '?') + qs;
}
try {
xhr.open(method, url, true);
} catch (e) {
opts.fail && opts.fail({ errMsg: 'request:fail ' + e.message });
return;
}
// 设置请求头
var header = opts.header || opts.headers || {};
Object.keys(header).forEach(function (k) {
try { xhr.setRequestHeader(k, header[k]); } catch (e) {}
});
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
var statusCode = xhr.status;
var data;
try { data = JSON.parse(xhr.responseText); } catch (e) { data = xhr.responseText; }
// 解析响应头
var resHeader = {};
try {
(xhr.getAllResponseHeaders() || '').split('\r\n').forEach(function (line) {
var idx = line.indexOf(':');
if (idx > 0) resHeader[line.slice(0, idx).trim().toLowerCase()] = line.slice(idx + 1).trim();
});
} catch (e) {}
var res = { statusCode: statusCode, data: data, header: resHeader };
if (statusCode >= 200 && statusCode < 400) {
opts.success && opts.success(res);
} else {
opts.fail && opts.fail({ errMsg: 'request:fail statusCode ' + statusCode });
}
opts.complete && opts.complete(res);
};
xhr.onerror = function () {
var err = { errMsg: 'request:fail network error' };
opts.fail && opts.fail(err);
opts.complete && opts.complete(err);
};
xhr.ontimeout = function () {
var err = { errMsg: 'request:fail timeout' };
opts.fail && opts.fail(err);
opts.complete && opts.complete(err);
};
var body = null;
if (opts.data && method !== 'GET' && method !== 'HEAD') {
body = typeof opts.data === 'string' ? opts.data : JSON.stringify(opts.data);
}
try { xhr.send(body); } catch (e) {
opts.fail && opts.fail({ errMsg: 'request:fail ' + e.message });
}
};
// getStorageSync → localStorage
polyfills.getStorageSync = function (key) {
try {
var v = localStorage.getItem(key);
if (v === null) return undefined;
try { return JSON.parse(v); } catch (e) { return v; }
} catch (e) { return undefined; }
};
polyfills.setStorageSync = function (key, data) {
try {
localStorage.setItem(key, typeof data === 'object' ? JSON.stringify(data) : String(data));
} catch (e) {}
};
polyfills.removeStorageSync = function (key) {
try { localStorage.removeItem(key); } catch (e) {}
};
// getWindowInfo → 浏览器 window
polyfills.getWindowInfo = function () {
return {
windowWidth: window.innerWidth || 375,
windowHeight: window.innerHeight || 667,
screenWidth: window.screen ? window.screen.width : 375,
screenHeight: window.screen ? window.screen.height : 667,
statusBarHeight: 0,
safeAreaInsets: { top: 0, bottom: 0, left: 0, right: 0 }
};
};
// getEnterOptionsSync → 解析当前 URL query
polyfills.getEnterOptionsSync = function () {
var query = {};
try {
var search = location.search.slice(1);
if (search) {
search.split('&').forEach(function (pair) {
var kv = pair.split('=');
if (kv[0]) query[decodeURIComponent(kv[0])] = decodeURIComponent(kv[1] || '');
});
}
} catch (e) {}
return { query: query, path: location.pathname };
};
/* -------- 代理对象:稳定的 window.uni -------- */
// 创建持久代理对象,把 polyfill 方法写入
var _proxy = {};
Object.keys(polyfills).forEach(function (k) { _proxy[k] = polyfills[k]; });
/**
* 把一个 uni 对象可能含存根合并到 _proxy
* 原则如果 polyfill 中有对应 key则仅当对方的实现不是存根时才覆盖
* 其余 key 直接合并以保留 UniApp 运行时的其他功能路由组件等
*/
function mergeIntoProxy(srcObj) {
if (!srcObj || typeof srcObj !== 'object') return;
Object.keys(srcObj).forEach(function (k) {
var val = srcObj[k];
if (polyfills[k]) {
// 对于我们有 polyfill 的 key只有对方是真正的实现时才覆盖
// 简单判断UniApp 存根函数不含 prototype.constructor 以外的属性且长度固定
// 最安全的方式:暂时保留我们的实现,等真实实现直接赋值给 uni.xxx 时再替换
// 这里什么都不做——让 UniApp 运行时后续直接赋值来替换
} else {
_proxy[k] = val;
}
});
// 把 prototype 链上的方法也复制(如 $emit/$on 等)
try {
var proto = Object.getPrototypeOf(srcObj);
if (proto && proto !== Object.prototype) {
Object.getOwnPropertyNames(proto).forEach(function (k) {
if (k !== 'constructor' && !_proxy[k]) {
try { _proxy[k] = proto[k].bind(srcObj); } catch (e) {}
}
});
}
} catch (e) {}
}
/* 拦截 window.uni 赋值 */
try {
Object.defineProperty(window, 'uni', {
get: function () { return _proxy; },
set: function (newVal) {
// UniApp 运行时把存根对象赋给 window.uni 时在这里被拦截
mergeIntoProxy(newVal);
},
configurable: true,
enumerable: true
});
} catch (e) {
// 极少数情况下 defineProperty 失败,退化为直接赋值
window.uni = _proxy;
}
})();