Files
xk-client-wx/request/api/request.js

404 lines
16 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.
import {Base64} from "js-base64";
import {checkDev} from "@/utils/utils";
import {isGuestMode, getGuestStoreId} from "@/common/utils/auth.js";
const arr = [
'mobile',
'express_mobile',
'doctor',
'accept_tel',
'patient_mobile',
'id_card',
'idcard',
'password'
]
// 敏感数据:响应解密后保留明文原字段,脱敏值写入 {field}_tm
const sensitiveData = [
'id_card',
'idcard',
'guardian_id_card'
]
// 仅展示脱敏、编辑需明文的字段
const displayMaskFields = [
'mobile',
'express_mobile',
'patient_mobile',
]
/**
* 脱敏展示值(写入 field_tm
*/
function maskFieldValue(key, plainText) {
if (plainText == null || plainText === '') {
return plainText
}
const str = String(plainText)
switch (key) {
case 'express_name':
case 'express_region':
case 'accept_name':
case 'patient':
return str.slice(0, 1).padEnd(str.length, '*')
case 'mobile':
case 'express_mobile':
case 'patient_mobile':
case 'guardian_mobile':
if (str.length <= 7) {
return str
}
return str.slice(0, 3).padEnd(str.length - 4, '*') + str.slice(-4)
case 'id_card':
case 'idcard':
case 'guardian_id_card':
if (str.length <= 10) {
return str
}
return str.slice(0, 6).padEnd(str.length - 4, '*') + str.slice(-4)
default:
return str
}
}
/** 只读展示:优先 field_tm */
export function displayTm(obj, field) {
if (obj == null) {
return ''
}
const tm = obj[field + '_tm']
if (tm != null && tm !== '') {
return tm
}
return obj[field] ?? ''
}
const isDev = checkDev('dev');
// 环境URL配置
const ENV_URLS = {
// 生产环境
prod: {
main: "https://app.xiaokang88.com/member",
xkApi: "https://api.xiaokang88.com/api/mobile",
shop: "https://shop.xiaokang88.com/member",
im: "https://api.ws.g.xiaokang88.com/api"
},
// 测试环境
test: {
main: "https://test.xk.app.nailaoyun.cn/member",
xkApi: "https://test.xk.api.nailaoyun.cn/api/mobile",
shop: "https://test.xk.shop.nailaoyun.cn/member",
im: "https://api.ws.g.nailaoyun.cn/api"
},
// 本地开发环境
local: {
main: "http://127.0.0.1:18000/member",
xkApi: "http://127.0.0.1:18001/api/mobile",
shop: "http://127.0.0.1:18018/member",
im: "http://127.0.0.1:12080/api"
}
};
// 获取当前环境配置
function getEnvUrls() {
// 如果是本地开发环境,使用本地配置
if (isDev === true) {
return ENV_URLS.local;
}
// 检查是否开启了开发者测试模式
const devMode = uni.getStorageSync('dev_mode');
return devMode ? ENV_URLS.test : ENV_URLS.prod;
}
function request(url, params, method = 0) {
const envUrls = getEnvUrls();
let baseURL = envUrls.main;
// 判断是否为guest模式且未登录
const guestMode = isGuestMode();
const token = uni.getStorageSync("token");
const isGuestRequest = guestMode && !token;
// 如果是guest模式且是xkApi请求转换为guest路由
if (isGuestRequest && url.indexOf('/xkApi') !== -1) {
if (url.indexOf('/xkApi/online-consultation/get-default-doctor-id') !== -1) {
url = url.replace('/xkApi/online-consultation/get-default-doctor-id', '/guest/guest-home/get-default-doctor-id');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/xkApi/product/drug-list-by-salesperson') !== -1) {
url = url.replace('/xkApi/product/drug-list-by-salesperson', '/guest/guest-product/drug-list-by-salesperson');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/xkApi/product/home-top-products') !== -1) {
url = url.replace('/xkApi/product/home-top-products', '/guest/guest-product/home-top-products');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/xkApi/product/home-zones') !== -1) {
url = url.replace('/xkApi/product/home-zones', '/guest/guest-product/home-zones');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/xkApi/platform/config') !== -1) {
url = url.replace('/xkApi/platform/config', '/guest/guest-platform/config');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/xkApi/platform/qualifications') !== -1) {
url = url.replace('/xkApi/platform/qualifications', '/guest/guest-platform/qualifications');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/xkApi/store/info') !== -1) {
url = url.replace('/xkApi/store/info', '/guest/guest-home/store-info');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/xkApi/store/list') !== -1) {
url = url.replace('/xkApi/store/list', '/guest/guest-home/store-list');
baseURL = envUrls.xkApi;
}
}
// 如果是guest模式且是oldApi请求转换为guest路由需要在替换之前处理
if (isGuestRequest && url.indexOf('/oldApi') !== -1) {
// 将 /oldApi/v1/xxx 转换为 /guest/guest-xxx/xxx
// 注意:路由前缀是 api/mobile所以完整路径是 api/mobile/guest/guest-doctor/list
if (url.indexOf('/oldApi/v1/doctor/all-list') !== -1) {
url = url.replace('/oldApi/v1/doctor/all-list', '/guest/guest-doctor/list');
baseURL = envUrls.xkApi; // guest路由使用xkApi的baseURL
} else if (url.indexOf('/oldApi/v1/doctor/detail') !== -1) {
url = url.replace('/oldApi/v1/doctor/detail', '/guest/guest-doctor/detail');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/oldApi/v1/doctor/comment-list') !== -1) {
url = url.replace('/oldApi/v1/doctor/comment-list', '/guest/guest-doctor/comment-list');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/oldApi/v1/patient/list') !== -1) {
url = url.replace('/oldApi/v1/patient/list', '/guest/guest-patient/list');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/oldApi/v1/store/info') !== -1) {
url = url.replace('/oldApi/v1/store/info', '/guest/guest-home/store-info');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/oldApi/v1/store/detail') !== -1) {
url = url.replace('/oldApi/v1/store/detail', '/guest/guest-home/store-detail');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/oldApi/v1/store/list') !== -1) {
url = url.replace('/oldApi/v1/store/list', '/guest/guest-home/store-list');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/oldApi/v1/register/doc-register-info') !== -1) {
url = url.replace('/oldApi/v1/register/doc-register-info', '/guest/guest-doctor/doc-register-info');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/oldApi/v1/doctor/office-list') !== -1) {
url = url.replace('/oldApi/v1/doctor/office-list', '/guest/guest-doctor/office-list');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/oldApi/v1/info/categories') !== -1) {
url = url.replace('/oldApi/v1/info/categories', '/guest/guest-info/categories');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/oldApi/v1/info/article-list') !== -1) {
url = url.replace('/oldApi/v1/info/article-list', '/guest/guest-info/article-list');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/oldApi/v1/info/article-info') !== -1) {
url = url.replace('/oldApi/v1/info/article-info', '/guest/guest-info/article-info');
baseURL = envUrls.xkApi;
}
}
// 如果是guest模式且是member/v1请求也需要转换为guest路由
if (isGuestRequest && (url.indexOf('/member/v1') !== -1 || url.indexOf('/v1/') !== -1)) {
if (url.indexOf('/v1/doctor/comment-list') !== -1 || url.indexOf('/member/v1/doctor/comment-list') !== -1) {
url = url.replace(/\/member\/v1\/doctor\/comment-list|\/v1\/doctor\/comment-list/, '/guest/guest-doctor/comment-list');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/v1/patient/list') !== -1 || url.indexOf('/member/v1/patient/list') !== -1) {
url = url.replace(/\/member\/v1\/patient\/list|\/v1\/patient\/list/, '/guest/guest-patient/list');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/v1/register/doc-register-info') !== -1 || url.indexOf('/member/v1/register/doc-register-info') !== -1) {
url = url.replace(/\/member\/v1\/register\/doc-register-info|\/v1\/register\/doc-register-info/, '/guest/guest-doctor/doc-register-info');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/v1/store/info') !== -1 || url.indexOf('/member/v1/store/info') !== -1) {
url = url.replace(/\/member\/v1\/store\/info|\/v1\/store\/info/, '/guest/guest-home/store-info');
baseURL = envUrls.xkApi;
} else if (url.indexOf('/v1/store/list') !== -1 || url.indexOf('/member/v1/store/list') !== -1) {
url = url.replace(/\/member\/v1\/store\/list|\/v1\/store\/list/, '/guest/guest-home/store-list');
baseURL = envUrls.xkApi;
}
}
if (url.split('/').indexOf('imApi') !== -1) {
baseURL = envUrls.im;
}
if (url.split('/').indexOf('newApi') !== -1) {
baseURL = envUrls.shop;
}
if (url.split('/').indexOf('xkApi') !== -1) {
baseURL = envUrls.xkApi;
// 如果是guest模式且是xkApi请求添加/guest/前缀(但避免重复添加)
// 转诊相关接口需要登录不转换为guest路由
if (isGuestRequest && url.indexOf('/guest/') === -1 && url.indexOf('/transfer-prescription') === -1) {
url = url.replace('/xkApi', '/guest/xkApi');
}
}
url = url.replace('/oldApi', '');
url = url.replace('/newApi', '');
url = url.replace('/imApi', '');
url = url.replace('/xkApi', '');
// 加密
if (params != null) {
if (!params.data) {
params.data = {};
}
params.data = getRes(params.data, false);
const isProductApi = url.indexOf('/product/') !== -1;
if (isProductApi && !params.data.store_id) {
const localStoreId = uni.getStorageSync('store_id');
params.data.store_id = localStoreId || getGuestStoreId();
}
// 如果是guest模式设置store_id优先使用用户传入或本地存储的值
if (isGuestRequest && params.data) {
// 优先使用用户传入的 store_id
if (!params.data.store_id) {
// 如果用户没传,尝试从本地存储获取
const localStoreId = uni.getStorageSync('store_id');
if (localStoreId) {
params.data.store_id = localStoreId;
} else {
// 如果本地存储也没有,使用默认值(保持向后兼容)
params.data.store_id = getGuestStoreId();
}
}
// 如果用户已经传了 store_id就使用用户传入的值不做任何修改
}
}
let num = 0;
// promise导出
return new Promise((resolve, reject) => {
uni.request({
// 基地址 + 传过来的地址
url: baseURL + url,
timeout: 8000, // 8秒超时时间单位ms
// 展开传过来的数据 请求方式 所需数据 wxfc279dcf921a38f7
// store_id: '11001'
...params,
// 请求头
header: {
"authorization": 'Bearer ' + uni.getStorageSync("token"),
"Content-Type": method === 0? "application/x-www-form-urlencoded": 'application/json'
},
// 成功钩子
success(res) {
if (res.data.errcode === 401) {
const currentPage = getCurrentPages()[getCurrentPages().length - 1];
const currentRoute = currentPage ? currentPage.route : '';
const isLoginPage = currentRoute === 'pages/login/login';
// 如果当前不在登录页,则跳转到登录页
if (!isLoginPage) {
uni.removeStorageSync('token')
uni.removeStorageSync('userinfo')
uni.removeStorageSync('token_h5')
uni.removeStorageSync('user_id')
uni.reLaunch({url: '/pages/login/login'})
}
}
if (res.data?.data != null) {
res.data.data = getRes(res.data.data)
}
// 处理 xkApi 返回的 result 格式
if (res.data?.result != null) {
res.data.result = getRes(res.data.result)
}
resolve(res)
},
// 失败钩子
fail(err) {
reject(err)
uni.showToast({
title: "请求失败",
duration: 1500,
mask: false,
icon: "error"
})
},
// 成功失败都会执行的钩子
complete() {
// 成功或者失败停止下拉刷新
uni.stopPullDownRefresh()
}
})
})
}
function getRes(obj, isDecode = true) {
try {
if (obj == null || typeof obj !== 'object') {
return obj
}
for (const key in obj) {
if (key.endsWith('_tm')) {
continue
}
if (Array.isArray(obj[key])) {
obj[key] = getRes(obj[key], isDecode)
} else if (obj[key] !== null && typeof obj[key] === 'object') {
obj[key] = getRes(obj[key], isDecode)
} else if (arr.indexOf(key) !== -1) {
let plainValue = ''
if (isDecode === true) {
plainValue = customBase64Decode(obj[key])
} else {
plainValue = customBase64Encode(obj[key])
}
const isGarbled = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\xFF]|[\u{E000}-\u{F8FF}]/u.test(
typeof plainValue === 'string' ? plainValue : ''
)
if (isGarbled) {
plainValue = obj[key]
}
if (isDecode === true) {
const needTm = sensitiveData.indexOf(key) !== -1
|| displayMaskFields.indexOf(key) !== -1
obj[key] = plainValue
if (needTm) {
obj[key + '_tm'] = maskFieldValue(key, plainValue)
}
} else {
obj[key] = plainValue
}
}
}
return obj
} catch (error) {
console.error('错误:', error)
return obj
}
}
function customBase64Decode(data) {
// return data
try {
// 第一次Base64解码
const decodedFirst = Base64.decode(data)
// 截取从第30个字符开始往后的内容
const subStr = decodedFirst.slice(30)
// 第二次Base64解码
return Base64.decode(subStr) != '' ? Base64.decode(subStr) : data
} catch (error) {
console.error(`解码Base64字符串【${data}】时发生错误`, error)
return data
}
}
// 加密
function customBase64Encode(data) {
if (data == null || data === '') return data
// return data
try {
// 和加密方法差不多但是是要生成30个随机字符
let randomString = ''
for (let i = 0; i < 30; i++) {
const randomChar = String.fromCharCode(Math.floor(Math.random() * (126 - 32 + 1)) + 32)
randomString += randomChar
}
const encoded = Base64.encode(data)
return Base64.encode(randomString + encoded)
} catch (error) {
console.error(`加密字符串【${data}】时发生错误`, error)
return data
}
}
// 导出
export default request