@zhangqingcq/vgce
Version:
Vector graphics configure editor. svg组态编辑器。基于vue3.3+ts+element-plus+vite
350 lines (341 loc) • 9.13 kB
text/typescript
/**
* @description 基于axios的网络请求插件
* @author Ricky email:zhangqingcq@foxmail.com
* @created 2023.06.21
*/
import { isEmpty } from 'lodash-es'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import type { Collection } from './types'
// const host = window.location.origin
const host = 'http://localhost:6789'
interface RequestConfigR extends AxiosRequestConfig {
spin?: boolean
noEmptyStr?: boolean
}
// 创建自定义对象
let service: AxiosInstance = axios.create({
baseURL: host,
withCredentials: true // 允许携带cookie
})
/**
* 拦截器,在发起请求前调用
*/
service.interceptors.request.use(
(q) => {
return q
},
(e) => {
return Promise.reject(e)
}
)
/**
* 封装请求结果和错误处理
*/
function checkResult(r: Partial<AxiosResponse>, msg?: string, rPath?: string[], config?: RequestConfigR) {
let y = true
let d = r && r.data
if (d) {
rPath = rPath ? rPath : []
for (let e of rPath) {
d = d[e]
y = y && d
}
if (y) {
return d
}
msg && console.warn(msg)
return false
}
msg && console.warn(msg)
return false
}
function handleRequest(
method: string,
url: string,
data?: Collection,
msg?: string,
rPath?: string[],
config?: RequestConfigR,
isUrlData?: boolean
) {
return new Promise((s, j) => {
switch (method) {
case 'get':
service
.get(url, { params: data })
.then((r) => {
let d = checkResult(r, msg, rPath, config)
if (d) {
s(d)
} else {
j(r)
}
})
.catch((e) => {
checkResult({}, msg, rPath, config)
j(e)
})
break
case 'delete':
let keyT = isUrlData ? 'params' : 'data'
service
.delete(url, { [keyT]: data })
.then((r) => {
let d = checkResult(r, msg, rPath, config)
if (d) {
s(d)
} else {
j(r)
}
})
.catch((e) => {
checkResult({}, msg, rPath, config)
j(e)
})
break
case 'post':
service
.post(url, data, config)
.then((r) => {
let d = checkResult(r, msg, rPath, config)
if (d) {
s(d)
} else {
j(r)
}
})
.catch((e) => {
checkResult({}, msg, rPath, config)
j(e)
})
break
case 'put':
service
.put(url, data, config)
.then((r) => {
let d = checkResult(r, msg, rPath, config)
if (d) {
s(d)
} else {
j(r)
}
})
.catch((e) => {
checkResult({}, msg, rPath, config)
j(e)
})
break
default:
}
})
}
/**
* 检查请求传入的各个参数
* @param method 请求方法
* @param url 地址
* @param data 餐宿
* @param msg 错误信息
* @param rPath 返回数据路径(提取)
* @param config 请求配置
* @param isUrlData delete方法传参模式 true:params,false:data
* @returns {Promise<*>}
*/
function checkRequest(
method: string,
url: string,
data: Collection = {},
msg?: string,
rPath?: string[],
config?: RequestConfigR,
isUrlData?: boolean
) {
return new Promise((s, j) => {
if (url) {
let data_: Collection | undefined
if (config && config.headers && config.headers['Content-Type'] === 'multipart/form-data') {
data_ = data
} else {
if (data && !isEmpty(data)) {
if (Array.isArray(data)) {
data_ = []
for (let e of data) {
if (e || e === 0 || e === false || (e === '' && config && !config.noEmptyStr)) {
data_.push(e)
}
}
} else {
data_ = {}
for (let key in data) {
if (
data.hasOwnProperty(key) &&
(data[key] ||
data[key] === 0 ||
data[key] === false ||
(data[key] === '' && config && !config.noEmptyStr))
) {
data_[key] = data[key]
}
}
}
}
}
let method_ = method.toLowerCase()
handleRequest(method_, url, data_, msg, rPath, config, isUrlData)
.then((r) => {
s(r)
})
.catch((e) => {
j(e)
})
} else {
console.error('没有请求地址:url')
j('没有请求地址:url')
}
})
}
/**
* @description 基于axios封装的请求插件,引入库时使用this.$fetch时直接调用以下方法,例如:this.$fetch.get("/getData",{id:1}),
* vue3的setup模式使用:proxy调用
* 单独引入时遵循Es Modules规范即可
* @class
*/
export default {
/**
* post 请求
* @function
* @param {string} url 请求地址
* @param {object} data 请求数据
* @param {string} msg 错误信息,在控制台输出,方便调试,不用可以不传,例如:
* @example this.$fetch.post("/getDataB",{name:'ricky'},"获取数据B失败")
* @param {Array.<string>} rPath 请求结果提取路径,如:[data,list]表示data.list,如不需过滤可不传
* @param {object} config 请求配置 如请求过程需要遮罩层,设置 spin:true即可
* @return {Promise<object>}
* @example this.$fetch.post("/getData",{id:1},null,['result','list'])
* .then(r=>{
* console.log(r)
* r相当于:data.result.list,data是网络请求结果
* })
*
* 注意:
* 请求最多支持5个入参,最少一个(url),依次为:url,data,msg,rPath,config。如果要传靠后的入参,但不想传前面的,应该这样传:
* this.$fetch.post("/setData",{},null,[],{
* headers: {
* 'Content-Type': 'multipart/form-data'
* },
* spin:true
* }
* )
*/
post(url: string, data?: Collection, msg?: string, rPath?: string[], config?: RequestConfigR) {
return new Promise((s, j) => {
checkRequest('post', url, data, msg, rPath, config)
.then((r) => {
s(r)
})
.catch((e) => {
j(e)
})
})
},
/**
* put请求
* @param {string} url 请求地址
* @param {object} data 请求数据
* @param {string} msg 错误信息,在控制台输出,方便调试,不用可以不传
* @param {Array.<string>} rPath 请求结果提取路径
* @param {object} config 请求配置 如请求过程需要遮罩层,设置 spin:true即可
* @return {Promise<unknown>}
*/
put(url: string, data?: Collection, msg?: string, rPath?: string[], config?: RequestConfigR) {
return new Promise((s, j) => {
checkRequest('put', url, data, msg, rPath, config)
.then((r) => {
s(r)
})
.catch((e) => {
j(e)
})
})
},
/**
* get请求
* @param {string} url 请求地址
* @param {object} data 请求数据
* @param {string} msg 错误信息,在控制台输出,方便调试,不用可以不传
* @param {Array.<string>} rPath 请求结果提取路径
* @param {object} config 请求配置 如请求过程需要遮罩层,设置 spin:true即可
* @return {Promise<unknown>}
* PS: get请求时(delete请求同理),可以把请求参数写在url里,也可以写在data里,注意写在data里时,data是对象
* 以请求'/devices',找到id=2,name=meter举例:
* 只传url时,url = '/devices?id=2&name=meter'
* url和data都传时,url = '/devices',data={id:2,name:'meter'}
*/
get(url: string, data?: Collection, msg?: string, rPath?: string[], config?: RequestConfigR) {
return new Promise((s, j) => {
checkRequest('get', url, data, msg, rPath, config)
.then((r) => {
s(r)
})
.catch((e) => {
j(e)
})
})
},
/**
* delete 请求
* @param {string} url 请求地址
* @param {object} data 请求数据
* @param {string} msg 错误信息,在控制台输出,方便调试,不用可以不传
* @param {Array.<string>} rPath 请求结果提取路径
* @param {object} config 请求配置 如请求过程需要遮罩层,设置 spin:true即可
* @param isUrlData 传参模式 true:params,false:data
* @return {Promise<unknown>}
*/
delete(
url: string,
data?: Collection,
msg?: string,
rPath?: string[],
config?: RequestConfigR,
isUrlData: boolean = true
) {
return new Promise((s, j) => {
checkRequest('delete', url, data, msg, rPath, config, isUrlData)
.then((r) => {
s(r)
})
.catch((e) => {
j(e)
})
})
},
/**
* 并发请求 例如:
* @example this.$fetch.all(
* [
* this.$fetch.get("/getData"),
* this.$fetch.post("/getDataB",{name:'ricky'})
* ]
* )
*/
all: axios.all,
/**
* 并发请求结果分离 例如:
* @example this.$fetch.all(
* [
* this.$fetch.get("/getData"),
* this.$fetch.post("/getDataB",{name:'ricky'})
* ]
* )
* .then(
* this.$fetch.spread((result1,result2)=>{
* console.log(result1,result2)
* })
* )
*/
spread: axios.spread,
/**
* 该请求插件暴露给外界的配置对象,为axios.create创建的实例对象,使用方法见axios官方网站
*/
config: service
}