init
This commit is contained in:
15
src/utils/auth/index.ts
Normal file
15
src/utils/auth/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
const TokenKey = 'admin-token';
|
||||
const TokenPrefix = 'Bearer ';
|
||||
function isLogin() {
|
||||
return !!uni.getStorageSync(TokenKey);
|
||||
}
|
||||
function getToken() {
|
||||
return uni.getStorageSync(TokenKey);
|
||||
}
|
||||
function setToken(token: string) {
|
||||
uni.setStorageSync(TokenKey, token);
|
||||
}
|
||||
function clearToken() {
|
||||
uni.removeStorageSync(TokenKey);
|
||||
}
|
||||
export { TokenPrefix, isLogin, getToken, setToken, clearToken };
|
28
src/utils/common/index.ts
Normal file
28
src/utils/common/index.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// 小程序更新检测
|
||||
export function mpUpdate() {
|
||||
const updateManager = uni.getUpdateManager();
|
||||
updateManager.onCheckForUpdate((res) => {
|
||||
// 请求完新版本信息的回调
|
||||
console.log(res.hasUpdate);
|
||||
});
|
||||
updateManager.onUpdateReady(() => {
|
||||
uni.showModal({
|
||||
title: '更新提示',
|
||||
content: '检测到新版本,是否下载新版本并重启小程序?',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
||||
updateManager.applyUpdate();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
updateManager.onUpdateFailed(() => {
|
||||
// 新的版本下载失败
|
||||
uni.showModal({
|
||||
title: '已经有新版本了哟~',
|
||||
content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~',
|
||||
showCancel: false,
|
||||
});
|
||||
});
|
||||
}
|
4
src/utils/index.ts
Normal file
4
src/utils/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './auth';
|
||||
export * from './common';
|
||||
export * from './modals';
|
||||
export * from './request';
|
81
src/utils/modals/index.ts
Normal file
81
src/utils/modals/index.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
interface IShowToastOptions {
|
||||
title?: string
|
||||
icon?: 'success' | 'loading' | 'error' | 'none'
|
||||
image?: string
|
||||
duration?: number
|
||||
position?: 'top' | 'center' | 'bottom'
|
||||
mask?: boolean
|
||||
}
|
||||
|
||||
interface ILoadingOptions {
|
||||
show?: (content?: string) => void
|
||||
hide?: () => void
|
||||
}
|
||||
|
||||
interface IShowModalOptions {
|
||||
title?: string
|
||||
content?: string
|
||||
showCancel?: boolean
|
||||
cancelText?: string
|
||||
cancelColor?: string
|
||||
confirmText?: string
|
||||
confirmColor?: string
|
||||
editable?: boolean
|
||||
placeholderText?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 轻提示
|
||||
* @param {string} content 提示内容
|
||||
* @param {object} option 配置
|
||||
*/
|
||||
export function Toast(content: string, option: IShowToastOptions = {}) {
|
||||
uni.showToast({
|
||||
title: content,
|
||||
icon: 'none',
|
||||
mask: true,
|
||||
duration: 1500,
|
||||
...option,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loading 提示框
|
||||
* @param {string} content 提示内容
|
||||
*/
|
||||
export const Loading: ILoadingOptions = {
|
||||
show: (content = '加载中') => {
|
||||
uni.showLoading({
|
||||
title: content,
|
||||
mask: true,
|
||||
});
|
||||
},
|
||||
hide: () => {
|
||||
uni.hideLoading();
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Dialog 提示框
|
||||
* @param {string} content 提示内容
|
||||
* @param {object} option 配置
|
||||
*/
|
||||
export function Dialog(content: string, option: IShowModalOptions = {}) {
|
||||
option.showCancel = false;
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.showModal({
|
||||
title: '温馨提示',
|
||||
content,
|
||||
showCancel: false,
|
||||
confirmColor: '#1677FF',
|
||||
success(res) {
|
||||
if (res.confirm)
|
||||
resolve(res);
|
||||
},
|
||||
fail() {
|
||||
reject(new Error('Alert 调用失败 !'));
|
||||
},
|
||||
...option,
|
||||
});
|
||||
});
|
||||
}
|
42
src/utils/request/index.ts
Normal file
42
src/utils/request/index.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
// 引入配置
|
||||
import type { HttpRequestConfig } from 'uview-plus/libs/luch-request/index';
|
||||
import { requestInterceptors, responseInterceptors } from './interceptors';
|
||||
import type { IResponse } from './type';
|
||||
|
||||
// 引入拦截器配置
|
||||
export function setupRequest() {
|
||||
uni.$u.http.setConfig((defaultConfig: HttpRequestConfig) => {
|
||||
/* defaultConfig 为默认全局配置 */
|
||||
defaultConfig.baseURL = import.meta.env.VITE_APP_BASE_API;
|
||||
return defaultConfig;
|
||||
});
|
||||
requestInterceptors();
|
||||
responseInterceptors();
|
||||
}
|
||||
|
||||
export function request<T = any>(config: HttpRequestConfig): Promise<T> {
|
||||
return new Promise((resolve) => {
|
||||
uni.$u.http.request(config).then((res: IResponse) => {
|
||||
const { result } = res;
|
||||
resolve(result as T);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function get<T = any>(config: HttpRequestConfig): Promise<T> {
|
||||
return request({ ...config, method: 'GET' });
|
||||
}
|
||||
|
||||
export function post<T = any>(config: HttpRequestConfig): Promise<T> {
|
||||
return request({ ...config, method: 'POST' });
|
||||
}
|
||||
|
||||
export function upload<T = any>(config: HttpRequestConfig): Promise<T> {
|
||||
return request({ ...config, method: 'UPLOAD' });
|
||||
}
|
||||
|
||||
export function download<T = any>(config: HttpRequestConfig): Promise<T> {
|
||||
return request({ ...config, method: 'DOWNLOAD' });
|
||||
}
|
||||
|
||||
export default setupRequest;
|
104
src/utils/request/interceptors.ts
Normal file
104
src/utils/request/interceptors.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import type {
|
||||
HttpError,
|
||||
HttpRequestConfig,
|
||||
HttpResponse,
|
||||
} from 'uview-plus/libs/luch-request/index';
|
||||
import { showMessage } from './status';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
// 是否正在刷新token的标记
|
||||
let isRefreshing: boolean = false;
|
||||
// 重试队列,每一项将是一个待执行的函数形式
|
||||
let requestQueue: (() => void)[] = [];
|
||||
|
||||
function requestInterceptors() {
|
||||
/**
|
||||
* 请求拦截
|
||||
* @param {Object} http
|
||||
*/
|
||||
uni.$u.http.interceptors.request.use(
|
||||
(config: HttpRequestConfig) => {
|
||||
// 可使用async await 做异步操作
|
||||
// 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
|
||||
config.data = config.data || {};
|
||||
// token设置
|
||||
const token = getToken();
|
||||
if (token && config.header) {
|
||||
config.header.token = token;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(
|
||||
config: any, // 可使用async await 做异步操作
|
||||
) => Promise.reject(config),
|
||||
);
|
||||
}
|
||||
function responseInterceptors() {
|
||||
/**
|
||||
* 响应拦截
|
||||
* @param {Object} http
|
||||
*/
|
||||
uni.$u.http.interceptors.response.use(
|
||||
async (response: HttpResponse) => {
|
||||
/* 对响应成功做点什么 可使用async await 做异步操作 */
|
||||
const data = response.data;
|
||||
// 配置参数
|
||||
const config = response.config;
|
||||
// 自定义参数
|
||||
const custom = config?.custom;
|
||||
|
||||
// 请求成功则返回结果
|
||||
if (data.code === 200) {
|
||||
return data || {};
|
||||
}
|
||||
|
||||
// 登录状态失效,重新登录
|
||||
if (data.code === 401) {
|
||||
// 是否在获取token中,防止重复获取
|
||||
if (!isRefreshing) {
|
||||
// 修改登录状态为true
|
||||
isRefreshing = true;
|
||||
await useUserStore().authLogin();
|
||||
// 登录完成之后,开始执行队列请求
|
||||
requestQueue.forEach(cb => cb());
|
||||
// 重试完了清空这个队列
|
||||
requestQueue = [];
|
||||
isRefreshing = false;
|
||||
// 重新执行本次请求
|
||||
return uni.$u.http.request(config);
|
||||
} else {
|
||||
return new Promise(resolve => {
|
||||
// 将resolve放进队列,用一个函数形式来保存,等登录后直接执行
|
||||
requestQueue.push(() => {
|
||||
resolve(uni.$u.http.request(config));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
|
||||
if (custom?.toast !== false) {
|
||||
uni.$u.toast(data.message);
|
||||
}
|
||||
|
||||
// 如果需要catch返回,则进行reject
|
||||
if (custom?.catch) {
|
||||
return Promise.reject(data);
|
||||
} else {
|
||||
// 否则返回一个pending中的promise
|
||||
return new Promise(() => {});
|
||||
}
|
||||
},
|
||||
(response: HttpError) => {
|
||||
if (response.statusCode) {
|
||||
// 请求已发出,但是不在2xx的范围
|
||||
showMessage(response.statusCode);
|
||||
return Promise.reject(response.data);
|
||||
}
|
||||
showMessage('网络连接异常,请稍后再试!');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export { requestInterceptors, responseInterceptors };
|
41
src/utils/request/status.ts
Normal file
41
src/utils/request/status.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
export const showMessage = (status: number | string): string => {
|
||||
let message = '';
|
||||
switch (status) {
|
||||
case 400:
|
||||
message = '请求错误(400)';
|
||||
break;
|
||||
case 401:
|
||||
message = '未授权,请重新登录(401)';
|
||||
break;
|
||||
case 403:
|
||||
message = '拒绝访问(403)';
|
||||
break;
|
||||
case 404:
|
||||
message = '请求出错(404)';
|
||||
break;
|
||||
case 408:
|
||||
message = '请求超时(408)';
|
||||
break;
|
||||
case 500:
|
||||
message = '服务器错误(500)';
|
||||
break;
|
||||
case 501:
|
||||
message = '服务未实现(501)';
|
||||
break;
|
||||
case 502:
|
||||
message = '网络错误(502)';
|
||||
break;
|
||||
case 503:
|
||||
message = '服务不可用(503)';
|
||||
break;
|
||||
case 504:
|
||||
message = '网络超时(504)';
|
||||
break;
|
||||
case 505:
|
||||
message = 'HTTP版本不受支持(505)';
|
||||
break;
|
||||
default:
|
||||
message = `连接出错(${status})!`;
|
||||
}
|
||||
return `${message},请检查网络或联系管理员!`;
|
||||
};
|
7
src/utils/request/type.ts
Normal file
7
src/utils/request/type.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
// 返回res.data的interface
|
||||
export interface IResponse<T = any> {
|
||||
code: number | string;
|
||||
result: T;
|
||||
message: string;
|
||||
status: string | number;
|
||||
}
|
Reference in New Issue
Block a user