This commit is contained in:
quantulr
2023-10-29 18:37:44 +08:00
commit 373b3d9dff
1813 changed files with 131892 additions and 0 deletions

27
pc/utils/env.ts Normal file
View File

@ -0,0 +1,27 @@
/**
* @description 获取客户端类型
*/
export function getClient() {
return useRuntimeConfig().public.client
}
/**
* @description 获取版本号
*/
export function getVersion() {
return useRuntimeConfig().public.version
}
/**
* @description 获取请求域名
*/
export function getApiUrl() {
return useRuntimeConfig().public.apiUrl
}
/**
* @description 获取请求前缀
*/
export function getApiPrefix() {
return useRuntimeConfig().public.apiPrefix
}

95
pc/utils/feedback.ts Normal file
View File

@ -0,0 +1,95 @@
import {
ElMessage,
ElMessageBox,
ElNotification,
ElLoading,
type ElMessageBoxOptions
} from 'element-plus'
import type { LoadingInstance } from 'element-plus/es/components/loading/src/loading'
export class Feedback {
private loadingInstance: LoadingInstance | null = null
static instance: Feedback | null = null
static getInstance() {
return this.instance ?? (this.instance = new Feedback())
}
// 消息提示
msg(msg: string) {
ElMessage.info(msg)
}
// 错误消息
msgError(msg: string) {
ElMessage.error(msg)
}
// 成功消息
msgSuccess(msg: string) {
ElMessage.success(msg)
}
// 警告消息
msgWarning(msg: string) {
ElMessage.warning(msg)
}
// 弹出提示
alert(msg: string) {
ElMessageBox.alert(msg, '系统提示')
}
// 错误提示
alertError(msg: string) {
ElMessageBox.alert(msg, '系统提示', { type: 'error' })
}
// 成功提示
alertSuccess(msg: string) {
ElMessageBox.alert(msg, '系统提示', { type: 'success' })
}
// 警告提示
alertWarning(msg: string) {
ElMessageBox.alert(msg, '系统提示', { type: 'warning' })
}
// 通知提示
notify(msg: string) {
ElNotification.info(msg)
}
// 错误通知
notifyError(msg: string) {
ElNotification.error(msg)
}
// 成功通知
notifySuccess(msg: string) {
ElNotification.success(msg)
}
// 警告通知
notifyWarning(msg: string) {
ElNotification.warning(msg)
}
// 确认窗体
confirm(msg: string) {
return ElMessageBox.confirm(msg, '温馨提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
}
// 提交内容
prompt(content: string, title: string, options?: ElMessageBoxOptions) {
return ElMessageBox.prompt(content, title, {
confirmButtonText: '确定',
cancelButtonText: '取消',
...options
})
}
// 打开全局loading
loading(msg: string) {
this.loadingInstance = ElLoading.service({
lock: true,
text: msg
})
}
// 关闭全局loading
closeLoading() {
this.loadingInstance?.close()
}
}
const feedback = Feedback.getInstance()
export default feedback

111
pc/utils/http/index.ts Normal file
View File

@ -0,0 +1,111 @@
import { getClient } from '@/utils/env'
import { FetchOptions } from 'ohmyfetch'
import { RequestCodeEnum, RequestMethodsEnum } from '@/enums/requestEnums'
import feedback from '@/utils/feedback'
import { merge } from 'lodash-es'
import { Request } from './request'
import { getApiPrefix, getApiUrl, getVersion } from '../env'
import { useUserStore } from '@/stores/user'
import {
PopupTypeEnum,
useAccount
} from '~~/layouts/components/account/useAccount'
export function createRequest(opt?: Partial<FetchOptions>) {
const userStore = useUserStore()
const { setPopupType, toggleShowPopup } = useAccount()
const defaultOptions: FetchOptions = {
// 基础接口地址
baseURL: getApiUrl(),
//请求头
headers: {
version: getVersion()
},
retry: 2,
async onRequest({ options }) {
const { withToken } = options.requestOptions
const headers = options.headers || {}
// 添加token
if (withToken) {
const token = userStore.token
headers['like-token'] = token
}
options.headers['terminal'] = getClient()
options.headers = headers
},
requestOptions: {
apiPrefix: getApiPrefix(),
isTransformResponse: true,
isReturnDefaultResponse: false,
withToken: true,
isParamsToData: true,
requestInterceptorsHook(options) {
console.log(options)
const { apiPrefix, isParamsToData } = options.requestOptions
// 拼接请求前缀
if (apiPrefix) {
options.url = `${apiPrefix}${options.url}`
}
const params = options.params || {}
// POST请求下如果无data则将params视为data
if (
isParamsToData &&
!Reflect.has(options, 'body') &&
options.method?.toUpperCase() === RequestMethodsEnum.POST
) {
options.body = params
options.params = {}
}
return options
},
async responseInterceptorsHook(response, options) {
const { isTransformResponse, isReturnDefaultResponse } =
options.requestOptions
//返回默认响应,当需要获取响应头及其他数据时可使用
if (isReturnDefaultResponse) {
return response
}
// 是否需要对数据进行处理
if (!isTransformResponse) {
return response._data
}
const { code, data, msg } = response._data
switch (code) {
case RequestCodeEnum.SUCCESS:
return data
case RequestCodeEnum.PARAMS_TYPE_ERROR:
case RequestCodeEnum.PARAMS_VALID_ERROR:
case RequestCodeEnum.REQUEST_METHOD_ERROR:
case RequestCodeEnum.ASSERT_ARGUMENT_ERROR:
case RequestCodeEnum.ASSERT_MYBATIS_ERROR:
case RequestCodeEnum.LOGIN_ACCOUNT_ERROR:
case RequestCodeEnum.LOGIN_DISABLE_ERROR:
case RequestCodeEnum.NO_PERMISSTION:
case RequestCodeEnum.FAILED:
case RequestCodeEnum.SYSTEM_ERROR:
if (msg) {
msg && feedback.msgError(msg)
}
return Promise.reject(msg)
case RequestCodeEnum.TOKEN_INVALID:
case RequestCodeEnum.TOKEN_EMPTY:
userStore.logout()
setPopupType(PopupTypeEnum.LOGIN)
toggleShowPopup(true)
return Promise.reject()
default:
return data
}
},
responseInterceptorsCatchHook(err) {
return err
}
}
}
return new Request(
// 深度合并
merge(defaultOptions, opt || {})
)
}

124
pc/utils/http/request.ts Normal file
View File

@ -0,0 +1,124 @@
import {
FetchOptions,
$fetch,
$Fetch,
FetchResponse,
RequestOptions,
FileParams
} from 'ohmyfetch'
import { merge } from 'lodash-es'
import { isFunction } from '../validate'
import { RequestMethodsEnum } from '@/enums/requestEnums'
export class Request {
private requestOptions: RequestOptions
private fetchInstance: $Fetch
constructor(private fetchOptions: FetchOptions) {
this.fetchInstance = $fetch.create(fetchOptions)
this.requestOptions = fetchOptions.requestOptions
}
getInstance() {
return this.fetchInstance
}
/**
* @description get请求
*/
get(fetchOptions: FetchOptions, requestOptions?: Partial<RequestOptions>) {
return this.request(
{ ...fetchOptions, method: RequestMethodsEnum.GET },
requestOptions
)
}
/**
* @description post请求
*/
post(fetchOptions: FetchOptions, requestOptions?: Partial<RequestOptions>) {
return this.request(
{ ...fetchOptions, method: RequestMethodsEnum.POST },
requestOptions
)
}
/**
* @description: 文件上传
*/
uploadFile(options: FetchOptions, params: FileParams) {
const formData = new FormData()
const customFilename = params.name || 'file'
formData.append(customFilename, params.file)
if (params.data) {
Object.keys(params.data).forEach((key) => {
const value = params.data![key]
if (Array.isArray(value)) {
value.forEach((item) => {
formData.append(`${key}[]`, item)
})
return
}
formData.append(key, params.data![key])
})
}
return this.request({
...options,
method: RequestMethodsEnum.POST,
body: formData
})
}
/**
* @description 请求函数
*/
request(
fetchOptions: FetchOptions,
requestOptions?: Partial<RequestOptions>
): Promise<any> {
let mergeOptions = merge({}, this.fetchOptions, fetchOptions)
mergeOptions.requestOptions = merge(
{},
this.requestOptions,
requestOptions
)
const {
requestInterceptorsHook,
responseInterceptorsHook,
responseInterceptorsCatchHook
} = this.requestOptions
if (requestInterceptorsHook && isFunction(requestInterceptorsHook)) {
mergeOptions = requestInterceptorsHook(mergeOptions)
}
return new Promise((resolve, reject) => {
return this.fetchInstance
.raw(mergeOptions.url, mergeOptions)
.then(async (response: FetchResponse<any>) => {
if (
responseInterceptorsHook &&
isFunction(responseInterceptorsHook)
) {
try {
response = await responseInterceptorsHook(
response,
mergeOptions
)
resolve(response)
} catch (error) {
reject(error)
}
return
}
resolve(response)
})
.catch((err) => {
if (
responseInterceptorsCatchHook &&
isFunction(responseInterceptorsCatchHook)
) {
reject(responseInterceptorsCatchHook(err))
return
}
reject(err)
})
})
}
}

47
pc/utils/util.ts Normal file
View File

@ -0,0 +1,47 @@
/**
* @description 添加单位
* @param {String | Number} value 值 100
* @param {String} unit 单位 px em rem
*/
export const addUnit = (value: string | number, unit = 'px') => {
return !Object.is(Number(value), NaN) ? `${value}${unit}` : value
}
/**
* @description 树转数组,队列实现广度优先遍历
* @param {Array} data 数据
* @param {Object} props `{ children: 'children' }`
*/
export const treeToArray = (data: any[], props = { children: 'children' }) => {
data = JSON.parse(JSON.stringify(data))
const { children } = props
const newData = []
const queue: any[] = []
data.forEach((child: any) => queue.push(child))
while (queue.length) {
const item: any = queue.shift()
if (item[children]) {
item[children].forEach((child: any) => queue.push(child))
delete item[children]
}
newData.push(item)
}
return newData
}
/**
* @description 获取正确的路经
* @param {String} path 数据
*/
export function getNormalPath(path: string) {
if (path.length === 0 || !path || path == 'undefined') {
return path
}
const newPath = path.replace('//', '/')
const length = newPath.length
if (newPath[length - 1] === '/') {
return newPath.slice(0, length - 1)
}
return newPath
}

50
pc/utils/validate.ts Normal file
View File

@ -0,0 +1,50 @@
export {
isArray,
isBoolean,
isDate,
isObject,
isFunction,
isString,
isNumber,
isNull
} from 'lodash-es'
import { isObject } from 'lodash-es'
/**
* @description 是否是http邮件电话号码
*/
export function isExternal(path: string) {
return /^(https?:|mailto:|tel:)/.test(path)
}
/**
* @description 是否是http
*/
export const isLinkHttp = (link: string): boolean =>
/^(https?:)?\/\//.test(link)
/**
* @description 是否是电话号码
*/
export const isLinkTel = (link: string): boolean => /^tel:/.test(link)
/**
* @description 是否是邮件
*/
export const isLinkMailto = (link: string): boolean => /^mailto:/.test(link)
/**
* @description 是否为空
* @param {unknown} value
* @return {Boolean}
*/
export const isEmpty = (value: unknown) => {
return value !== null && value !== '' && typeof value !== 'undefined'
}
/**
* @description 是否为空对象
* @param {Object} value
* @return {Boolean}
*/
export const isEmptyObject = (target: object) => {
return isObject(target) && !Object.keys(target).length
}