Files
huangjingfen/pro_v3.5.1/view/uniapp/uni-h5-polyfill.js
apple 263df94d95 chore(frontend): 更新前端配置文件和构建脚本
- 更新 uni-app 配置文件(manifest.json、vue.config.js)
- 新增 babel.config.js 和 uni-h5-polyfill.js 支持
- 更新缓存工具类(cache.js、index.js)
- 新增 nginx-crmeb.conf 部署配置
- 更新 package-lock.json
2026-03-10 13:50:35 +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;
}
})();