feat(other): init
This commit is contained in:
61
src/utils/api-config.js
Normal file
61
src/utils/api-config.js
Normal file
@@ -0,0 +1,61 @@
|
||||
// 判断是否为开发环境
|
||||
const isDev = import.meta.env.DEV
|
||||
|
||||
// API接口线路配置管理
|
||||
export const API_ENDPOINTS = {
|
||||
primary: {
|
||||
name: '主要线路',
|
||||
baseURL: import.meta.env.VITE_BASE_API,
|
||||
timeout: 10000,
|
||||
},
|
||||
backup1: {
|
||||
name: '备用线路',
|
||||
baseURL: import.meta.env.VITE_BASE_API_1,
|
||||
timeout: 10000,
|
||||
},
|
||||
}
|
||||
|
||||
// 调试信息
|
||||
console.log('=== 多接口配置信息 ===')
|
||||
console.log('当前环境:', isDev ? '开发环境' : '生产环境')
|
||||
console.log('API配置:', API_ENDPOINTS)
|
||||
console.log('环境变量 VITE_BASE_API:', import.meta.env.VITE_BASE_API)
|
||||
console.log('环境变量 VITE_BASE_API_1:', import.meta.env.VITE_BASE_API_1)
|
||||
console.log('是否使用代理:', import.meta.env.VITE_USE_PROXY)
|
||||
|
||||
// 当前使用的接口线路
|
||||
let currentEndpoint = 'primary'
|
||||
|
||||
// 获取当前接口配置
|
||||
export function getCurrentEndpoint() {
|
||||
return {
|
||||
key: currentEndpoint,
|
||||
...API_ENDPOINTS[currentEndpoint],
|
||||
}
|
||||
}
|
||||
|
||||
// 设置当前接口
|
||||
export function setCurrentEndpoint(endpoint) {
|
||||
if (API_ENDPOINTS[endpoint]) {
|
||||
currentEndpoint = endpoint
|
||||
localStorage.setItem('api_endpoint', endpoint)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 获取所有可用接口
|
||||
export function getAvailableEndpoints() {
|
||||
return Object.entries(API_ENDPOINTS).map(([key, config]) => ({
|
||||
key,
|
||||
...config,
|
||||
}))
|
||||
}
|
||||
|
||||
// 初始化时从本地存储恢复接口选择
|
||||
export function initApiEndpoint() {
|
||||
const savedEndpoint = localStorage.getItem('api_endpoint')
|
||||
if (savedEndpoint && API_ENDPOINTS[savedEndpoint]) {
|
||||
currentEndpoint = savedEndpoint
|
||||
}
|
||||
}
|
||||
17
src/utils/auth/auth.js
Normal file
17
src/utils/auth/auth.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import { router } from '@/router'
|
||||
|
||||
export function toLogin() {
|
||||
const currentRoute = unref(router.currentRoute)
|
||||
const needRedirect =
|
||||
!currentRoute.meta.requireAuth && !['/404', '/login'].includes(router.currentRoute.value.path)
|
||||
router.replace({
|
||||
path: '/login',
|
||||
query: needRedirect ? { ...currentRoute.query, redirect: currentRoute.path } : {},
|
||||
})
|
||||
}
|
||||
|
||||
export function toFourZeroFour() {
|
||||
router.replace({
|
||||
path: '/404',
|
||||
})
|
||||
}
|
||||
2
src/utils/auth/index.js
Normal file
2
src/utils/auth/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './auth'
|
||||
export * from './token'
|
||||
33
src/utils/auth/token.js
Normal file
33
src/utils/auth/token.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import { lStorage } from '@/utils'
|
||||
import api from '@/api'
|
||||
|
||||
const TOKEN_CODE = 'access_token'
|
||||
const DURATION = 6 * 60 * 60
|
||||
|
||||
export function getToken() {
|
||||
return lStorage.get(TOKEN_CODE)
|
||||
}
|
||||
|
||||
export function setToken(token) {
|
||||
lStorage.set(TOKEN_CODE, token, DURATION)
|
||||
}
|
||||
|
||||
export function removeToken() {
|
||||
lStorage.remove(TOKEN_CODE)
|
||||
}
|
||||
|
||||
export async function refreshAccessToken() {
|
||||
const tokenItem = lStorage.getItem(TOKEN_CODE)
|
||||
if (!tokenItem) {
|
||||
return
|
||||
}
|
||||
const { time } = tokenItem
|
||||
// token生成或者刷新后30分钟内不执行刷新
|
||||
if (new Date().getTime() - time <= 1000 * 60 * 30) return
|
||||
try {
|
||||
const res = await api.refreshToken()
|
||||
setToken(res.data.token)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
90
src/utils/common/common.js
Normal file
90
src/utils/common/common.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
/**
|
||||
* @desc 格式化时间
|
||||
* @param {(Object|string|number)} time
|
||||
* @param {string} format
|
||||
* @returns {string | null}
|
||||
*/
|
||||
export function formatDateTime(time = undefined, format = 'YYYY-MM-DD HH:mm:ss') {
|
||||
return dayjs(time).format(format)
|
||||
}
|
||||
|
||||
export function formatDate(date = undefined, format = 'YYYY-MM-DD') {
|
||||
return formatDateTime(date, format)
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 函数节流
|
||||
* @param {Function} fn
|
||||
* @param {Number} wait
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function throttle(fn, wait) {
|
||||
var context, args
|
||||
var previous = 0
|
||||
|
||||
return function () {
|
||||
var now = +new Date()
|
||||
context = this
|
||||
args = arguments
|
||||
if (now - previous > wait) {
|
||||
fn.apply(context, args)
|
||||
previous = now
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @desc 函数防抖
|
||||
* @param {Function} func
|
||||
* @param {number} wait
|
||||
* @param {boolean} immediate
|
||||
* @return {*}
|
||||
*/
|
||||
export function debounce(method, wait, immediate) {
|
||||
let timeout
|
||||
return function (...args) {
|
||||
let context = this
|
||||
if (timeout) {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
// 立即执行需要两个条件,一是immediate为true,二是timeout未被赋值或被置为null
|
||||
if (immediate) {
|
||||
/**
|
||||
* 如果定时器不存在,则立即执行,并设置一个定时器,wait毫秒后将定时器置为null
|
||||
* 这样确保立即执行后wait毫秒内不会被再次触发
|
||||
*/
|
||||
let callNow = !timeout
|
||||
timeout = setTimeout(() => {
|
||||
timeout = null
|
||||
}, wait)
|
||||
if (callNow) {
|
||||
method.apply(context, args)
|
||||
}
|
||||
} else {
|
||||
// 如果immediate为false,则函数wait毫秒后执行
|
||||
timeout = setTimeout(() => {
|
||||
/**
|
||||
* args是一个类数组对象,所以使用fn.apply
|
||||
* 也可写作method.call(context, ...args)
|
||||
*/
|
||||
method.apply(context, args)
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} el
|
||||
* @param {Function} cb
|
||||
* @return {ResizeObserver}
|
||||
*/
|
||||
export function useResize(el, cb) {
|
||||
const observer = new ResizeObserver((entries) => {
|
||||
cb(entries[0].contentRect)
|
||||
})
|
||||
observer.observe(el)
|
||||
return observer
|
||||
}
|
||||
12
src/utils/common/icon.js
Normal file
12
src/utils/common/icon.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { h } from 'vue'
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { NIcon } from 'naive-ui'
|
||||
import SvgIcon from '@/components/icon/SvgIcon.vue'
|
||||
|
||||
export function renderIcon(icon, props = { size: 12 }) {
|
||||
return () => h(NIcon, props, { default: () => h(Icon, { icon }) })
|
||||
}
|
||||
|
||||
export function renderCustomIcon(icon, props = { size: 12 }) {
|
||||
return () => h(NIcon, props, { default: () => h(SvgIcon, { icon }) })
|
||||
}
|
||||
4
src/utils/common/index.js
Normal file
4
src/utils/common/index.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './common'
|
||||
export * from './is'
|
||||
export * from './icon'
|
||||
export * from './naiveTools'
|
||||
119
src/utils/common/is.js
Normal file
119
src/utils/common/is.js
Normal file
@@ -0,0 +1,119 @@
|
||||
const toString = Object.prototype.toString
|
||||
|
||||
export function is(val, type) {
|
||||
return toString.call(val) === `[object ${type}]`
|
||||
}
|
||||
|
||||
export function isDef(val) {
|
||||
return typeof val !== 'undefined'
|
||||
}
|
||||
|
||||
export function isUndef(val) {
|
||||
return typeof val === 'undefined'
|
||||
}
|
||||
|
||||
export function isNull(val) {
|
||||
return val === null
|
||||
}
|
||||
|
||||
export function isWhitespace(val) {
|
||||
return val === ''
|
||||
}
|
||||
|
||||
export function isObject(val) {
|
||||
return !isNull(val) && is(val, 'Object')
|
||||
}
|
||||
|
||||
export function isArray(val) {
|
||||
return val && Array.isArray(val)
|
||||
}
|
||||
|
||||
export function isString(val) {
|
||||
return is(val, 'String')
|
||||
}
|
||||
|
||||
export function isNumber(val) {
|
||||
return is(val, 'Number')
|
||||
}
|
||||
|
||||
export function isBoolean(val) {
|
||||
return is(val, 'Boolean')
|
||||
}
|
||||
|
||||
export function isDate(val) {
|
||||
return is(val, 'Date')
|
||||
}
|
||||
|
||||
export function isRegExp(val) {
|
||||
return is(val, 'RegExp')
|
||||
}
|
||||
|
||||
export function isFunction(val) {
|
||||
return typeof val === 'function'
|
||||
}
|
||||
|
||||
export function isPromise(val) {
|
||||
return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch)
|
||||
}
|
||||
|
||||
export function isElement(val) {
|
||||
return isObject(val) && !!val.tagName
|
||||
}
|
||||
|
||||
export function isWindow(val) {
|
||||
return typeof window !== 'undefined' && isDef(window) && is(val, 'Window')
|
||||
}
|
||||
|
||||
export function isNullOrUndef(val) {
|
||||
return isNull(val) || isUndef(val)
|
||||
}
|
||||
|
||||
export function isNullOrWhitespace(val) {
|
||||
return isNullOrUndef(val) || isWhitespace(val)
|
||||
}
|
||||
|
||||
/** 空数组 | 空字符串 | 空对象 | 空Map | 空Set */
|
||||
export function isEmpty(val) {
|
||||
if (isArray(val) || isString(val)) {
|
||||
return val.length === 0
|
||||
}
|
||||
|
||||
if (val instanceof Map || val instanceof Set) {
|
||||
return val.size === 0
|
||||
}
|
||||
|
||||
if (isObject(val)) {
|
||||
return Object.keys(val).length === 0
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* * 类似mysql的IFNULL函数
|
||||
* * 第一个参数为null/undefined/'' 则返回第二个参数作为备用值,否则返回第一个参数
|
||||
* @param {Number|Boolean|String} val
|
||||
* @param {Number|Boolean|String} def
|
||||
* @returns
|
||||
*/
|
||||
export function ifNull(val, def = '') {
|
||||
return isNullOrWhitespace(val) ? def : val
|
||||
}
|
||||
|
||||
export function isUrl(path) {
|
||||
const reg =
|
||||
/(((^https?:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)$/
|
||||
return reg.test(path)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function isExternal(path) {
|
||||
return /^(https?:|mailto:|tel:)/.test(path)
|
||||
}
|
||||
|
||||
export const isServer = typeof window === 'undefined'
|
||||
|
||||
export const isClient = !isServer
|
||||
99
src/utils/common/naiveTools.js
Normal file
99
src/utils/common/naiveTools.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import * as NaiveUI from 'naive-ui'
|
||||
import { isNullOrUndef } from '@/utils'
|
||||
import { naiveThemeOverrides as themeOverrides } from '~/settings'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
|
||||
export function setupMessage(NMessage) {
|
||||
let loadingMessage = null
|
||||
class Message {
|
||||
/**
|
||||
* 规则:
|
||||
* * loading message只显示一个,新的message会替换正在显示的loading message
|
||||
* * loading message不会自动清除,除非被替换成非loading message,非loading message默认2秒后自动清除
|
||||
*/
|
||||
|
||||
removeMessage(message = loadingMessage, duration = 2000) {
|
||||
setTimeout(() => {
|
||||
if (message) {
|
||||
message.destroy()
|
||||
message = null
|
||||
}
|
||||
}, duration)
|
||||
}
|
||||
|
||||
showMessage(type, content, option = {}) {
|
||||
if (loadingMessage && loadingMessage.type === 'loading') {
|
||||
// 如果存在则替换正在显示的loading message
|
||||
loadingMessage.type = type
|
||||
loadingMessage.content = content
|
||||
|
||||
if (type !== 'loading') {
|
||||
// 非loading message需设置自动清除
|
||||
this.removeMessage(loadingMessage, option.duration)
|
||||
}
|
||||
} else {
|
||||
// 不存在正在显示的loading则新建一个message,如果新建的message是loading message则将message赋值存储下来
|
||||
let message = NMessage[type](content, option)
|
||||
if (type === 'loading') {
|
||||
loadingMessage = message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loading(content) {
|
||||
this.showMessage('loading', content, { duration: 0 })
|
||||
}
|
||||
|
||||
success(content, option = {}) {
|
||||
this.showMessage('success', content, option)
|
||||
}
|
||||
|
||||
error(content, option = {}) {
|
||||
this.showMessage('error', content, option)
|
||||
}
|
||||
|
||||
info(content, option = {}) {
|
||||
this.showMessage('info', content, option)
|
||||
}
|
||||
|
||||
warning(content, option = {}) {
|
||||
this.showMessage('warning', content, option)
|
||||
}
|
||||
}
|
||||
|
||||
return new Message()
|
||||
}
|
||||
|
||||
export function setupDialog(NDialog) {
|
||||
NDialog.confirm = function (option = {}) {
|
||||
const showIcon = !isNullOrUndef(option.title)
|
||||
return NDialog[option.type || 'warning']({
|
||||
showIcon,
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: option.confirm,
|
||||
onNegativeClick: option.cancel,
|
||||
onMaskClick: option.cancel,
|
||||
...option,
|
||||
})
|
||||
}
|
||||
|
||||
return NDialog
|
||||
}
|
||||
|
||||
export function setupNaiveDiscreteApi() {
|
||||
const appStore = useAppStore()
|
||||
const configProviderProps = computed(() => ({
|
||||
theme: appStore.isDark ? NaiveUI.darkTheme : undefined,
|
||||
themeOverrides,
|
||||
}))
|
||||
const { message, dialog, notification, loadingBar } = NaiveUI.createDiscreteApi(
|
||||
['message', 'dialog', 'notification', 'loadingBar'],
|
||||
{ configProviderProps }
|
||||
)
|
||||
|
||||
window.$loadingBar = loadingBar
|
||||
window.$notification = notification
|
||||
window.$message = setupMessage(message)
|
||||
window.$dialog = setupDialog(dialog)
|
||||
}
|
||||
35
src/utils/http/helpers.js
Normal file
35
src/utils/http/helpers.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { useUserStore } from '@/store'
|
||||
|
||||
export function addBaseParams(params) {
|
||||
if (!params.userId) {
|
||||
params.userId = useUserStore().userId
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveResError(code, message) {
|
||||
switch (code) {
|
||||
case 400:
|
||||
message = message ?? '请求参数错误'
|
||||
break
|
||||
case 401:
|
||||
message = message ?? '登录已过期'
|
||||
useUserStore().logout()
|
||||
break
|
||||
case 403:
|
||||
message = message ?? '没有权限'
|
||||
break
|
||||
case 404:
|
||||
message = message ?? '资源或接口不存在'
|
||||
break
|
||||
case 500:
|
||||
message = message ?? '服务器异常'
|
||||
break
|
||||
case 402:
|
||||
message = message ?? '无权限访问'
|
||||
break
|
||||
default:
|
||||
message = message ?? `【${code}】: 未知异常!`
|
||||
break
|
||||
}
|
||||
return message
|
||||
}
|
||||
107
src/utils/http/index.js
Normal file
107
src/utils/http/index.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import axios from 'axios'
|
||||
import { resReject, resResolve, reqReject, reqResolve } from './interceptors'
|
||||
import { getCurrentEndpoint, getAvailableEndpoints } from '../api-config'
|
||||
|
||||
export function createAxios(options = {}) {
|
||||
const defaultOptions = {
|
||||
timeout: 12000,
|
||||
}
|
||||
const service = axios.create({
|
||||
...defaultOptions,
|
||||
...options,
|
||||
})
|
||||
service.interceptors.request.use(reqResolve, reqReject)
|
||||
service.interceptors.response.use(resResolve, resReject)
|
||||
return service
|
||||
}
|
||||
|
||||
// 创建支持多接口的请求实例
|
||||
export function createMultiEndpointRequest() {
|
||||
let instances = null
|
||||
|
||||
// 延迟创建axios实例
|
||||
function ensureInstances() {
|
||||
if (!instances) {
|
||||
instances = {}
|
||||
const endpoints = getAvailableEndpoints()
|
||||
|
||||
console.log('创建axios实例,接口列表:', endpoints)
|
||||
|
||||
endpoints.forEach((endpoint) => {
|
||||
console.log(`创建实例 ${endpoint.key}:`, endpoint.baseURL)
|
||||
instances[endpoint.key] = createAxios({
|
||||
baseURL: endpoint.baseURL,
|
||||
timeout: endpoint.timeout,
|
||||
})
|
||||
})
|
||||
}
|
||||
return instances
|
||||
}
|
||||
|
||||
return {
|
||||
// 使用当前选中的接口发送请求
|
||||
async request(config) {
|
||||
const instances = ensureInstances()
|
||||
const currentEndpoint = getCurrentEndpoint()
|
||||
|
||||
console.log('当前接口配置:', currentEndpoint)
|
||||
console.log('可用实例:', Object.keys(instances))
|
||||
|
||||
const instance = instances[currentEndpoint.key]
|
||||
|
||||
if (!instance) {
|
||||
throw new Error(`接口实例不存在: ${currentEndpoint.key}`)
|
||||
}
|
||||
|
||||
console.log(`使用接口: ${currentEndpoint.name} (${currentEndpoint.baseURL})`)
|
||||
console.log('请求配置:', config)
|
||||
|
||||
return await instance(config)
|
||||
},
|
||||
|
||||
// 获取当前接口实例
|
||||
getCurrentInstance() {
|
||||
const instances = ensureInstances()
|
||||
const currentEndpoint = getCurrentEndpoint()
|
||||
return instances[currentEndpoint.key]
|
||||
},
|
||||
|
||||
// 获取所有接口实例
|
||||
getAllInstances() {
|
||||
return ensureInstances()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// export const request = createAxios({
|
||||
// baseURL: import.meta.env.VITE_BASE_API,
|
||||
// })
|
||||
|
||||
// 支持多接口的请求实例
|
||||
export const multiRequest = createMultiEndpointRequest()
|
||||
|
||||
// 创建自动适配多接口的request实例
|
||||
const multiEndpointInstance = createMultiEndpointRequest()
|
||||
|
||||
// 创建支持axios方法的request实例
|
||||
export const request = {
|
||||
// 基础请求方法
|
||||
request: (config) => multiEndpointInstance.request(config),
|
||||
|
||||
// 自动适配axios方法
|
||||
get: (url, config = {}) => multiEndpointInstance.request({ method: 'get', url, ...config }),
|
||||
post: (url, data, config = {}) =>
|
||||
multiEndpointInstance.request({ method: 'post', url, data, ...config }),
|
||||
put: (url, data, config = {}) =>
|
||||
multiEndpointInstance.request({ method: 'put', url, data, ...config }),
|
||||
delete: (url, config = {}) => multiEndpointInstance.request({ method: 'delete', url, ...config }),
|
||||
patch: (url, data, config = {}) =>
|
||||
multiEndpointInstance.request({ method: 'patch', url, data, ...config }),
|
||||
head: (url, config = {}) => multiEndpointInstance.request({ method: 'head', url, ...config }),
|
||||
options: (url, config = {}) =>
|
||||
multiEndpointInstance.request({ method: 'options', url, ...config }),
|
||||
|
||||
// 获取当前接口实例(用于直接访问axios实例)
|
||||
getCurrentInstance: () => multiEndpointInstance.getCurrentInstance(),
|
||||
getAllInstances: () => multiEndpointInstance.getAllInstances(),
|
||||
}
|
||||
63
src/utils/http/interceptors.js
Normal file
63
src/utils/http/interceptors.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import { getToken } from '@/utils'
|
||||
import { resolveResError } from './helpers'
|
||||
|
||||
export function reqResolve(config) {
|
||||
// if (config.url.includes('/admin')) {
|
||||
// config.baseURL = import.meta.env.VITE_ADMIN_API
|
||||
// } else {
|
||||
// config.baseURL = import.meta.env.VITE_BASE_API
|
||||
// }
|
||||
// 处理不需要token的请求
|
||||
if (config.noNeedToken) {
|
||||
return config
|
||||
}
|
||||
|
||||
const token = getToken()
|
||||
if (!token) {
|
||||
return Promise.reject({ code: 401, message: '登录已过期,请重新登录!' })
|
||||
}
|
||||
|
||||
/**
|
||||
* * 加上 token
|
||||
* ! 认证方案: JWT Bearer
|
||||
*/
|
||||
config.headers.Authorization = config.headers.Authorization || 'Bearer ' + token
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
export function reqReject(error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
|
||||
export function resResolve(response) {
|
||||
// TODO: 处理不同的 response.headers
|
||||
const { data, status, config, statusText } = response
|
||||
if (data?.code !== 200) {
|
||||
const code = data?.code ?? status
|
||||
|
||||
/** 根据code处理对应的操作,并返回处理后的message */
|
||||
const message = resolveResError(code, data?.msg ?? statusText)
|
||||
|
||||
/** 需要错误提醒 */
|
||||
!config.noNeedTip && window.$message?.error(message)
|
||||
return Promise.reject({ code, message, error: data || response })
|
||||
}
|
||||
return Promise.resolve(data)
|
||||
}
|
||||
|
||||
export function resReject(error) {
|
||||
if (!error || !error.response) {
|
||||
const code = error?.code
|
||||
/** 根据code处理对应的操作,并返回处理后的message */
|
||||
const message = resolveResError(code, error.message)
|
||||
window.$message?.error(message)
|
||||
return Promise.reject({ code, message, error })
|
||||
}
|
||||
const { data, status, config } = error.response
|
||||
const code = data?.code ?? status
|
||||
const message = resolveResError(code, data?.message ?? error.message)
|
||||
/** 需要错误提醒 */
|
||||
!config?.noNeedTip && window.$message?.error(message)
|
||||
return Promise.reject({ code, message, error: error.response?.data || error.response })
|
||||
}
|
||||
4
src/utils/index.js
Normal file
4
src/utils/index.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './common'
|
||||
export * from './storage'
|
||||
export * from './http'
|
||||
export * from './auth'
|
||||
21
src/utils/storage/index.js
Normal file
21
src/utils/storage/index.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { createStorage } from './storage'
|
||||
|
||||
const prefixKey = 'Vue_Naive_Admin_'
|
||||
|
||||
export const createLocalStorage = function (option = {}) {
|
||||
return createStorage({
|
||||
prefixKey: option.prefixKey || '',
|
||||
storage: localStorage,
|
||||
})
|
||||
}
|
||||
|
||||
export const createSessionStorage = function (option = {}) {
|
||||
return createStorage({
|
||||
prefixKey: option.prefixKey || '',
|
||||
storage: sessionStorage,
|
||||
})
|
||||
}
|
||||
|
||||
export const lStorage = createLocalStorage({ prefixKey })
|
||||
|
||||
export const sStorage = createSessionStorage({ prefixKey })
|
||||
55
src/utils/storage/storage.js
Normal file
55
src/utils/storage/storage.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import { isNullOrUndef } from '@/utils'
|
||||
|
||||
class Storage {
|
||||
constructor(option) {
|
||||
this.storage = option.storage
|
||||
this.prefixKey = option.prefixKey
|
||||
}
|
||||
|
||||
getKey(key) {
|
||||
return `${this.prefixKey}${key}`.toUpperCase()
|
||||
}
|
||||
|
||||
set(key, value, expire) {
|
||||
const stringData = JSON.stringify({
|
||||
value,
|
||||
time: Date.now(),
|
||||
expire: !isNullOrUndef(expire) ? new Date().getTime() + expire * 1000 : null,
|
||||
})
|
||||
this.storage.setItem(this.getKey(key), stringData)
|
||||
}
|
||||
|
||||
get(key) {
|
||||
const { value } = this.getItem(key, {})
|
||||
return value
|
||||
}
|
||||
|
||||
getItem(key, def = null) {
|
||||
const val = this.storage.getItem(this.getKey(key))
|
||||
if (!val) return def
|
||||
try {
|
||||
const data = JSON.parse(val)
|
||||
const { value, time, expire } = data
|
||||
if (isNullOrUndef(expire) || expire > new Date().getTime()) {
|
||||
return { value, time }
|
||||
}
|
||||
this.remove(key)
|
||||
return def
|
||||
} catch (error) {
|
||||
this.remove(key)
|
||||
return def
|
||||
}
|
||||
}
|
||||
|
||||
remove(key) {
|
||||
this.storage.removeItem(this.getKey(key))
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.storage.clear()
|
||||
}
|
||||
}
|
||||
|
||||
export function createStorage({ prefixKey = '', storage = sessionStorage }) {
|
||||
return new Storage({ prefixKey, storage })
|
||||
}
|
||||
Reference in New Issue
Block a user