Files
huangjingfen/pro_v3.5.1_副本/view/uniapp/uni-h5-polyfill.js
apple 434aa8c69d 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

189 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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;
}
})();