index.ts 6.64 KB
import { RequestBodyEnum, RequestHttpEnum, RequestParams, RequestParamsObjType } from '@/enums/httpEnum'
import { ExtraRequestConfigType } from '@/store/external/modules/extraComponentInfo.d'
import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
import { isShareMode } from '@/views/share/hook'
import { customHttp } from './http'
import { SelectTimeAggregationFieldEnum } from '@/views/chart/ContentConfigurations/components/ChartData/external/components/SelectTImeAggregation'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'

export enum ParamsType {
  REQUIRED,
  OPTIONAL
}

export const getOriginUrl = (originUrl: string) => {
  const locationUrl = 'localhost'
  return originUrl === locationUrl ? location.origin : originUrl
}

const regOptionalParams = /(?={\?)/g
const regDynamicParams = /(?={).+?(?<=})/g

/**
 * @description 判断是否是动态参数
 * @param url
 */
export const isDynamicUrl = (url: string) => {
  regDynamicParams.lastIndex = 0
  return regDynamicParams.test(url)
}

/**
 * @description 解析动态参数
 * @param url
 */
export const decomposeDynamicParams = (url: string) => {
  regDynamicParams.lastIndex = 0
  regOptionalParams.lastIndex = 0

  return Array.from((url || '').matchAll(regDynamicParams), ([item]) => {
    return {
      type: regOptionalParams.test(item) ? ParamsType.OPTIONAL : ParamsType.REQUIRED,
      originValue: item,
      value: item.replaceAll(/[{}?]/g, '').split(',')
    }
  })
}

/**
 * @description 正则替换url中的动态参数
 * @param requestUrl
 * @param Params
 */
const getDynamicRequestUrl = (requestUrl = '', Params: Recordable) => {
  requestUrl = decodeURI(requestUrl || '')

  const paramsList = decomposeDynamicParams(requestUrl)
  requestUrl = paramsList.reduce((prev, next) => {
    const { type, value, originValue } = next
    if (type === ParamsType.REQUIRED) {
      value.forEach(key => {
        prev = prev.replace(key, Reflect.get(Params, key))
        Reflect.deleteProperty(Params, key)
      })
    }

    if (type === ParamsType.OPTIONAL) {
      prev = prev.replace(originValue, '')
    }

    return prev
  }, requestUrl)

  return requestUrl.replaceAll(/[{}?]/g, '')
}

const transformBodyValue = (body: RequestParams['Body'], requestParamsBodyType: RequestBodyEnum) => {
  let value = Reflect.get(body, requestParamsBodyType)

  if (requestParamsBodyType === RequestBodyEnum.FORM_DATA) {
    const formData = new FormData()
    Object.keys(value as RequestParams['Body']['form-data']).forEach(key => {
      formData.append(key, value[key])
    })
    value = formData
  }

  return value
}

const extraValue = (object: Recordable) => {
  return Object.keys(object).reduce((prev, next) => {
    return { ...prev, ...(object[next] ? { [next]: object[next] } : {}) }
  }, {})
}

const handleParams = (Params: Recordable) => {
  Reflect.deleteProperty(Params, 'attrName')
  if (Params.keys && Params?.keys?.length) {
    // 过滤无效参数
    Reflect.deleteProperty(Params, 'attrName')
    /** ft 修改select联动下拉框选择了属性(单个)报错问题
     * 源代码 Params.keys = (Params.keys || [] as any).join(',')
     */
    if (!Array.isArray(Params.keys)) {
      Params.keys = ([Params.keys] || ([] as any)).join(',')
    } else {
      Params.keys = (Params.keys || ([] as any)).join(',')
    }
    //ft
  }

  const timePeriod = Params[SelectTimeAggregationFieldEnum.TIME_PERIOD]
  if (timePeriod) {
    Params.startTs = Date.now() - timePeriod
    Params.endTs = Date.now()
    Reflect.deleteProperty(Params, SelectTimeAggregationFieldEnum.TIME_PERIOD)
  }

  return Object.keys(Params)
    .filter(Boolean)
    .reduce((prev, next) => ({ ...prev, [next]: Params[next] }), {})
}

//post请求动态追加query参数
const objConvertQuery = (data: Recordable) => {
  const _result = []
  for (const key in data) {
    const value = data[key]
    if (value.constructor == Array) {
      value.forEach(function (_value) {
        _result.push(key + '=' + _value)
      })
    } else {
      _result.push(key + '=' + value)
    }
  }
  return _result.join('&')
}

export const customRequest = async (request: RequestConfigType) => {
  const {
    requestHttpType,
    requestParams,
    requestParamsBodyType,
    requestOriginUrl,
    requestVerificationToken,
    pondRequestOriginUrl,
    pondRequestGlobalTokenKey,
    pondRequestGlobalTokenSuffix,
  } = request as ExtraRequestConfigType
  const chartEditStore = useChartEditStore()
  
  const {requestOriginUrl: globalRequestOriginUrl} = chartEditStore.getRequestGlobalConfig

  let { requestUrl } = request as ExtraRequestConfigType
  const { Header, Body } = requestParams
  let { Params } = requestParams
  Params = JSON.parse(JSON.stringify(Params))
  const isDynamicUrlFlag = isDynamicUrl(requestUrl || '')

  if (isDynamicUrlFlag) {
    requestUrl = getDynamicRequestUrl(requestUrl, Params)
  }

  const body = transformBodyValue(Body, requestParamsBodyType)

  /**
   * ft 修改post请求针对这种接口(/api/yt/device,设备列表分页),是post请求,page和pageSize是query参数,body可以不传内容
   * 修改后的代码在注释之间,并标注好源代码和修改后代码,方便回溯
   * 源代码 url: requestUrl
   * 修改后代码 requestHttpType === RequestHttpEnum.GET.toUpperCase() ? requestUrl: `${requestUrl}?${objConvertQuery(Params)}
   */
  Params = handleParams(Params)
  return customHttp.request<any>(
    {
      url:
        requestHttpType === RequestHttpEnum.GET.toUpperCase() ? requestUrl : `${requestUrl}?${objConvertQuery(Params)}`,
      baseURL: requestVerificationToken ? pondRequestOriginUrl : globalRequestOriginUrl ? globalRequestOriginUrl : getOriginUrl(requestOriginUrl!),
      method: requestHttpType,
      params: requestHttpType === RequestHttpEnum.GET.toUpperCase() ? Params : null,
      data: body,
      headers: extraValue(Header)
    },
    {
      joinPrefix: false,
      apiUrl: '',
      withToken:true,
      withShareToken: !requestVerificationToken ? isShareMode(): false,
      withThirdTokenString: requestVerificationToken,
      withThirdTokenKey: pondRequestGlobalTokenKey,
      withThirdTokenPrefix: pondRequestGlobalTokenSuffix
    }
  )
  //ft
}

export interface thirdInterfaceRequest {
  requestOriginUrl: string
  body: RequestParamsObjType
}

//特殊处理第三方接口,一般获取token是POST请求,暂定POST
export const customThirdInterfaceRequest = async (request: thirdInterfaceRequest) => {
  const { body, requestOriginUrl } = request

  return customHttp.request<any>(
    {
      url: requestOriginUrl,
      method: RequestHttpEnum.POST,
      data: body
    },
    {
      joinPrefix: false,
      apiUrl: '',
      withToken: false
    }
  )
}