refactor: 移除旧的邀请码来源追踪逻辑

1. 删除App.vue中全局邀请码持久化逻辑与相关工具函数
2. 简化http请求的方法与请求头处理逻辑
3. 移除diy-form组件内的邀请码暂存、提交与展示逻辑
4. 清理不再使用的工具类邀请码辅助函数
This commit is contained in:
2026-08-03 16:24:18 +08:00
parent be1e175471
commit 1cda06573e
4 changed files with 21 additions and 354 deletions

View File

@@ -173,19 +173,8 @@ export default {
_sendRequestNow(params) {
// ✅ 关键修复 1:支持调用方指定 params.method(GET/POST/PUT/DELETE);
// 没指定时按老规则:有 data → POST,没 data → GET
var method;
if (params.method && typeof params.method === 'string') {
method = String(params.method).toUpperCase();
if (['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'].indexOf(method) === -1) {
method = 'GET';
}
} else {
method = params.data != undefined ? 'POST' : 'GET';
}
var url = (Config.baseUrl + params.url).replace(/(?<!:)\/+/g, '/'),
var method = params.data != undefined ? 'POST' : 'GET',
url = (Config.baseUrl + params.url).replace(/(?<!:)\/+/g, '/'),
data = {
app_type: appType,
app_type_name: appTypeName
@@ -205,22 +194,9 @@ export default {
if (params.data != undefined) Object.assign(data, params.data);
// ✅ 关键修复 2:Content-Type 合法值,两个 MIME 类型不要乱拼接
// 规则:
// - 调用方 params.header 里指定了 content-type → 优先用调用方的(保持原有 override 能力)
// - GET/HEAD/DELETE:application/x-www-form-urlencoded(URL query 编码)
// - POST/PUT/PATCH Object data:application/json(uni.request 会自动 JSON.stringify)
// - 如果调用方传 FormData / ArrayBuffer 等二进制:不设 Content-Type,让 uni 自动处理
var autoHeader = {};
if (method === 'GET' || method === 'HEAD' || method === 'DELETE') {
autoHeader['content-type'] = 'application/x-www-form-urlencoded';
} else {
// POST/PUT/PATCH:默认用 application/json,后端能直接 json_decode(file_get_contents('php://input'))
autoHeader['content-type'] = 'application/json';
}
// 调用方 params.header 合并(调用方指定的覆盖自动设置的)
const header = Object.assign({}, autoHeader, (params.header && typeof params.header === 'object') ? params.header : {});
const header = params.header || {
'content-type': 'application/x-www-form-urlencoded;application/json'
};
const dataType = params.dataType || 'json';
const responseType = params.responseType || 'text';
@@ -251,9 +227,8 @@ export default {
uni.request({
url: Config.baseUrl + '/api/upload/headimgBase64',
method: 'POST',
// ✅ 修复:application/json,后端能直接 json_decode
header: {
'content-type': 'application/json'
'content-type': 'application/x-www-form-urlencoded;application/json'
},
data: {
app_type: appType,
@@ -266,7 +241,7 @@ export default {
console.log('[HTTP][RESPONSE] uploadBase64', 'statusCode=', res.statusCode, JSON.stringify(res.data));
typeof params.success == 'function' && params.success(res.data);
},
fail: (res) => {
fail: () => {
console.error('[HTTP][FAIL] uploadBase64', JSON.stringify(res));
typeof params.fail == 'function' && params.fail(res);
}
@@ -277,9 +252,8 @@ export default {
uni.request({
url: Config.baseUrl + '/api/upload/headimgPull',
method: 'POST',
// ✅ 修复:application/json
header: {
'content-type': 'application/json'
'content-type': 'application/x-www-form-urlencoded;application/json'
},
data: {
app_type: appType,
@@ -292,7 +266,7 @@ export default {
console.log('[HTTP][RESPONSE] pullImage', 'statusCode=', res.statusCode, JSON.stringify(res.data));
typeof params.success == 'function' && params.success(res.data);
},
fail: (res) => {
fail: () => {
console.error('[HTTP][FAIL] pullImage', JSON.stringify(res));
typeof params.fail == 'function' && params.fail(res);
}
@@ -300,17 +274,6 @@ export default {
},
upload(params) {
console.log('[HTTP][REQUEST] upload', Config.baseUrl + params.url, 'name=', params.name || 'file');
// ✅ 关键修复:uni.uploadFile **绝对不能手动设置 Content-Type**!
// 因为 uni.uploadFile 会自动设置成 multipart/form-data; boundary=----xxxxxx
// 手动设置会覆盖掉 boundary,后端无法解析分段上传,导致文件/表单字段解析为空
var uploadHeader = {};
// 只合并调用方传的自定义 header,不默认加 content-type
if (params.header && typeof params.header === 'object') {
Object.assign(uploadHeader, params.header);
// 兜底:如果调用方误传了 content-type,就删掉,让 uni 自动设置 multipart/form-data
delete uploadHeader['content-type'];
delete uploadHeader['Content-Type'];
}
uni.uploadFile({
url: Config.baseUrl + params.url,
filePath: params.filePath,
@@ -319,10 +282,10 @@ export default {
formData: {
app_type: appType,
app_type_name: appTypeName,
token: store.state.token || '',
uniacid: uni.getStorageSync('uniacid') || Config.uniacid
},
header: uploadHeader,
header: {
'content-type': 'application/x-www-form-urlencoded;application/json'
},
success: (res) => {
console.log('[HTTP][RESPONSE] upload', Config.baseUrl + params.url, 'statusCode=', res.statusCode, res.data);
typeof params.success == 'function' && params.success(JSON.parse(res.data));

View File

@@ -76,113 +76,6 @@ function _getCurrentUniacid() {
return _pickCurrentUniacid(storageVal, configVal);
}
/**
* 从当前登录态读取 memberInfo → 返回后端接口真实生成的推荐码
* 读取优先级:storage.memberInfo.recommend_code > Vuex store.state.memberInfo.recommend_code
* 没登录 / 未同意授权 / 后端还没返回码 → 返回 ''
* @returns {string}
*/
function _getCurrentRecommendCode() {
// P1: storage 中 memberInfo.recommend_code(DIY 推荐码组件 _persistRecommendInfo 已写入)
try {
var info = null;
if (typeof uni !== 'undefined' && uni && typeof uni.getStorageSync === 'function') {
info = uni.getStorageSync('memberInfo');
}
if (info && typeof info === 'object') {
if (info.recommend_code && String(info.recommend_code).trim()) {
return String(info.recommend_code).trim();
}
// 兼容旧字段 invite_code(商家之前保存的配置)
if (info.invite_code && String(info.invite_code).trim()) {
return String(info.invite_code).trim();
}
}
} catch (e) {}
// P2: Vuex store.state.memberInfo(某些平台 storage 还没落地时,内存里可能已经好了)
try {
if (store && store.state && store.state.memberInfo && typeof store.state.memberInfo === 'object') {
var s = store.state.memberInfo;
if (s.recommend_code && String(s.recommend_code).trim()) {
return String(s.recommend_code).trim();
}
if (s.invite_code && String(s.invite_code).trim()) {
return String(s.invite_code).trim();
}
}
} catch (e) {}
return '';
}
/**
* 从 URL 中移除指定 query 参数(防止 URL 里已存在旧的 recommend_code=xxx 时,append 之后重复)
* - 仅移除 key,不影响其他参数
* - 同时处理 hash(xxx#yyy) 在 query 后面的情况(保留 hash 原位置)
* @param {string} url
* @param {string} key
* @returns {string}
*/
function _removeQueryParam(url, key) {
if (!url || !key) return url || '';
// 先拆 hash
var hashIdx = url.indexOf('#');
var hash = '';
var main = url;
if (hashIdx !== -1) {
hash = url.substring(hashIdx);
main = url.substring(0, hashIdx);
}
var qIdx = main.indexOf('?');
if (qIdx === -1) return url; // 没 query
var path = main.substring(0, qIdx);
var qs = main.substring(qIdx + 1);
if (!qs) return url;
var pairs = qs.split('&').filter(function(p) {
if (!p) return false;
var eq = p.indexOf('=');
var k = (eq === -1) ? p : p.substring(0, eq);
// 大小写不敏感(URL 参数通常大小写不敏感)
return String(k).toLowerCase() !== String(key).toLowerCase();
});
var newMain = pairs.length ? (path + '?' + pairs.join('&')) : path;
return newMain + hash;
}
/**
* 给 URL 追加当前登录会员的推荐码(方案 B 标准函数,推荐使用)
* 规则:
* - 当前登录且能拿到后端返回的 recommend_code → 移除 URL 里已存在的旧值
* → 同时追加 recommend_code + invite 两个 key(双参数兼容,后端收哪个都能用)
* - 未登录 / 推荐码为空 → 原样返回
* - 兼容内部相对路径 '/pages/xxx?x=1' 与 外部绝对 URL 'https://host/xx#yyy'
* @param {string} url
* @returns {string}
*/
function _appendRecommendCodeIfLoggedIn(url) {
if (!url) return '';
var code = _getCurrentRecommendCode();
if (!code) return url; // 没登录或没码:不动
// 1) 先清 URL 里已存在的旧参数(两个 key 都清,避免重复追加或旧码覆盖新码)
var cleaned = _removeQueryParam(url, 'recommend_code');
cleaned = _removeQueryParam(cleaned, 'invite');
// 2) 双 key 同时追加:标准名 recommend_code + 历史兼容名 invite
// 这样不管后端 parseCode 接口收哪个 key,都能正确命中
return _appendQueryParamsBase(cleaned, { recommend_code: code, invite: code });
}
/**
* 旧版函数别名(保持对 _appendInviteCodeIfLoggedIn 的调用兼容)
* 之前业务代码调用 _appendInviteCodeIfLoggedIn 的,现在全部委托给新的 _appendRecommendCodeIfLoggedIn
* 确保:一次改动,全链路统一使用后端真实码 + 双 key 兼容
*/
function _appendInviteCodeIfLoggedIn(url) {
return _appendRecommendCodeIfLoggedIn(url);
}
/**
* 把 URL 上的 page_params 还原成对象。是 _toParamValueString 的逆操作。
* 容错策略:任何解析失败都安全降级到 defaultValue,不抛异常。
@@ -1362,11 +1255,6 @@ export default {
let url = this.normalizeUrl(decodeEntity(link.wap_url));
url = this.appendQueryParams(url, params);
// ✅ 外链跳转自动拼邀请码:当前登录有邀请码 → 去 URL 旧 invite → 追加成新值
// H5: window.location.href 新页面打开时 location.search 能收到
// MP: webview src URL 打开目标 H5 页面时能收到
url = _appendInviteCodeIfLoggedIn(url);
// #ifdef H5
// console.log(`url ---->`, url, link)
window.location.href = url;
@@ -1479,16 +1367,6 @@ export default {
// resolveLinkUrl 已把 wap_url 中的 query 合并到 link.page_params
// 这里过滤掉 link 元数据字段, 避免 wap_url/name/parent/title 等被错误附加到目标 URL
// title/enable_set_title/page_params 仍需透传到目标 URL,page_params 放最后
// ✅ 内部页:把推荐码写进 page_params(最终会被拼成 URL query,diy-form onLoad options 能收到)
// 仅在当前登录已拿到推荐码时追加,不覆盖上游已有值;双写 recommend_code+ invite(历史兼容)
var _curRecommendCode = _getCurrentRecommendCode();
if (_curRecommendCode) {
if (!link.page_params || typeof link.page_params !== 'object') link.page_params = {};
if (!link.page_params.recommend_code) link.page_params.recommend_code = _curRecommendCode;
if (!link.page_params.invite) link.page_params.invite = _curRecommendCode;
}
const { wap_url, name, parent, type, appid, page, mobile, image, ...navParams } = link;
this.redirectTo(link.wap_url, {
...navParams,