新增统一导航栏组件YjyfNavBar,替换各页面原生导航 新增服务选择抽屉组件GoodsPickerDrawer,实现分类选品流程 新增tabbar图标矢量资源,优化底部导航样式 新增后端运力统计接口与多商品下单逻辑 修复页面跳转逻辑,统一使用switchTab/redirectTo 优化订单创建与评价页的UI组件化,提升一致性
126 行
3.2 KiB
JavaScript
126 行
3.2 KiB
JavaScript
/**
|
||
* 统一请求层
|
||
* - 自动携带 token(header: token)
|
||
* - 统一响应契约:code === 1 成功;其余为失败(0 通用 / 401 未登录 / 403 无权限 / 2001~2003 业务语义)
|
||
* - 失败统一 toast,未登录自动清理并引导登录
|
||
* - 内置 POST 请求 500ms 防并发快速连击锁
|
||
*/
|
||
import config from '@/config/config.js';
|
||
|
||
const BASE_URL = (config.baseUrl || config.dev).replace(/\/+$/, '') + '/api';
|
||
|
||
const TOKEN_KEY = 'yjyf_token';
|
||
const USER_KEY = 'yjyf_user';
|
||
|
||
// 活跃中的 POST 请求锁缓存
|
||
const pendingPostMap = new Map();
|
||
|
||
export function getToken() {
|
||
try {
|
||
return uni.getStorageSync(TOKEN_KEY) || '';
|
||
} catch (e) {
|
||
return '';
|
||
}
|
||
}
|
||
|
||
export function setToken(token) {
|
||
uni.setStorageSync(TOKEN_KEY, token || '');
|
||
}
|
||
|
||
export function getUser() {
|
||
try {
|
||
return uni.getStorageSync(USER_KEY) || null;
|
||
} catch (e) {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export function setUser(user) {
|
||
uni.setStorageSync(USER_KEY, user || null);
|
||
}
|
||
|
||
export function clearAuth() {
|
||
uni.removeStorageSync(TOKEN_KEY);
|
||
uni.removeStorageSync(USER_KEY);
|
||
}
|
||
|
||
export function isLogin() {
|
||
return !!getToken();
|
||
}
|
||
|
||
export function toLogin() {
|
||
clearAuth();
|
||
uni.navigateTo({ url: '/pages/login/login' });
|
||
}
|
||
|
||
/**
|
||
* @param {String} path 接口路径,如 /order/index
|
||
* @param {Object} options { method, data, auth, silent }
|
||
*/
|
||
export function request(path, options) {
|
||
const opts = options || {};
|
||
const method = (opts.method || 'GET').toUpperCase();
|
||
const data = opts.data || {};
|
||
const silent = !!opts.silent;
|
||
|
||
// 针对写入类请求 (POST) 做 500ms 防抖/去重锁
|
||
if (method === 'POST') {
|
||
const requestKey = path + '_' + JSON.stringify(data);
|
||
const lastTime = pendingPostMap.get(requestKey);
|
||
const now = Date.now();
|
||
if (lastTime && now - lastTime < 500) {
|
||
return Promise.reject(new Error('请勿频繁重复提交'));
|
||
}
|
||
pendingPostMap.set(requestKey, now);
|
||
setTimeout(() => pendingPostMap.delete(requestKey), 600);
|
||
}
|
||
|
||
return new Promise((resolve, reject) => {
|
||
const header = { 'content-type': 'application/x-www-form-urlencoded' };
|
||
const token = getToken();
|
||
if (token) {
|
||
header.token = token;
|
||
}
|
||
|
||
uni.request({
|
||
url: BASE_URL + path,
|
||
method: method,
|
||
data: data,
|
||
header: header,
|
||
timeout: 15000,
|
||
success: (res) => {
|
||
const body = res.data || {};
|
||
if (body.code === 1) {
|
||
resolve(body.data === undefined || body.data === null ? {} : body.data);
|
||
return;
|
||
}
|
||
const msg = body.msg || ('请求失败(' + res.statusCode + ')');
|
||
if (body.code === 401) {
|
||
clearAuth();
|
||
if (!silent) {
|
||
uni.showToast({ title: '登录已失效,请重新登录', icon: 'none' });
|
||
setTimeout(() => toLogin(), 800);
|
||
}
|
||
} else if (!silent) {
|
||
uni.showToast({ title: msg, icon: 'none' });
|
||
}
|
||
reject(Object.assign(new Error(msg), { code: body.code, data: body.data }));
|
||
},
|
||
fail: () => {
|
||
if (!silent) {
|
||
uni.showToast({ title: '网络异常,请稍后重试', icon: 'none' });
|
||
}
|
||
reject(new Error('网络异常'));
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
export function get(path, data, options) {
|
||
return request(path, Object.assign({ method: 'GET', data: data }, options || {}));
|
||
}
|
||
|
||
export function post(path, data, options) {
|
||
return request(path, Object.assign({ method: 'POST', data: data }, options || {}));
|
||
}
|