fix: 适配多平台url编码规则,修复双重编码问题
针对H5和小程序/App平台分别处理url参数编码: 1. H5平台需要手动encodeURIComponent避免参数解析错误 2. 小程序/App平台由uni内部自动编码,避免双重编码导致参数解码异常 同时重构了工具类中的编码逻辑,统一多场景下的平台适配规则
This commit is contained in:
@@ -282,7 +282,14 @@ export const resolvePageUrl = (page_key, params = {}) => {
|
||||
Object.keys(params).forEach(function (key) {
|
||||
const value = params[key];
|
||||
if (value === null || value === undefined || value === '') return;
|
||||
// H5:浏览器不自动编码,需要手动 encodeURIComponent
|
||||
// 小程序/App:uni.navigateTo 会自动编码,这里不能再 encode,否则双重编码
|
||||
// #ifdef H5
|
||||
parts.push(key + '=' + encodeURIComponent(value));
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
parts.push(key + '=' + value);
|
||||
// #endif
|
||||
});
|
||||
if (parts.length > 0) {
|
||||
url = url + (url.indexOf('?') !== -1 ? '&' : '?') + parts.join('&');
|
||||
@@ -643,18 +650,25 @@ export default {
|
||||
// 2. 合并 param:同 key 时新值覆盖旧值,杜绝 ?name=A&name=B 这种重复
|
||||
const merged = Object.assign({}, existingParams, param || {});
|
||||
|
||||
// 3. 统一编码。decode -> encode 双向 roundtrip 兼具两种语义:
|
||||
// - 调用方传原始值(/pages_tool/index/diy?name=XXX) -> encode 后 %2F%3F...
|
||||
// - 调用方已传编码值(%2F%3F...) -> decode 还原 -> encode 还原回去,不会被二次编码
|
||||
// - 任何不能 decode 的非法序列(如裸 %) 走 catch 路径,直接 encode
|
||||
// 3. 参数编码策略,按平台区分:
|
||||
// - 小程序/App: uni.navigateTo / router.pushUrl 内部会自动对 url 做一次编码,
|
||||
// 若在 JS 侧再 encodeURIComponent 一次,会被平台再编码一层,目标页 onLoad(options)
|
||||
// 只 decode 一次后仍是编码形态(如 %25E6%25B2%2599%25E5%258F%2591 -> %E6%B2%99%E5%8F%91)
|
||||
// => 这里必须保持原始值,完全交给平台去编码
|
||||
// - H5: 浏览器不会自动编码 url,若参数含 & ? = 等特殊字符会被 queryString 错位解析
|
||||
// => 这里仍需手动 encodeURIComponent,decode->encode roundtrip 兼容调用方已编码的入参
|
||||
const safeEncode = (v) => {
|
||||
const s = v == null ? '' : String(v);
|
||||
// try {
|
||||
// return encodeURIComponent(decodeURIComponent(s));
|
||||
// } catch (e) {
|
||||
// return encodeURIComponent(s);
|
||||
// }
|
||||
// #ifdef H5
|
||||
try {
|
||||
return encodeURIComponent(decodeURIComponent(s));
|
||||
} catch (e) {
|
||||
return encodeURIComponent(s);
|
||||
}
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
return s;
|
||||
// #endif
|
||||
};
|
||||
const queryStr = Object.keys(merged)
|
||||
.map(k => safeEncode(k) + '=' + safeEncode(merged[k]))
|
||||
@@ -2020,10 +2034,12 @@ export default {
|
||||
// 判断当前 URL 是否已经包含查询参数,决定使用 ? 还是 &
|
||||
const separator = targetUrl.includes('?') ? '&' : '?';
|
||||
|
||||
// 遍历参数对象,手动进行 encodeURIComponent 编码并拼接
|
||||
// 遍历参数对象,拼接参数
|
||||
// 小程序/App 端:uni.navigateTo/router.pushUrl 内部会自动对 url 编码,
|
||||
// 这里不能再 encodeURIComponent,否则会被平台再编码一层导致双重编码
|
||||
const queryString = Object.entries(params)
|
||||
.filter(([_, value]) => value !== undefined && value !== null)
|
||||
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
|
||||
.map(([key, value]) => `${key}=${value}`)
|
||||
.join('&');
|
||||
|
||||
// 重新拼接成完整的 URL
|
||||
|
||||
Reference in New Issue
Block a user