Переглянути джерело

feat: 完成自定义请求功能

奔跑的面条 3 роки тому
батько
коміт
ca587c9ee3

+ 0 - 1
src/api/axios.ts

@@ -10,7 +10,6 @@ const axiosInstance = axios.create({
 
 axiosInstance.interceptors.request.use(
   (config: AxiosRequestConfig) => {
-    config.headers = {}
     return config
   },
   (error: AxiosRequestConfig) => {

+ 114 - 4
src/api/http.ts

@@ -1,5 +1,12 @@
 import axiosInstance from './axios'
-import { RequestHttpEnum, ContentTypeEnum } from '@/enums/httpEnum'
+import {
+  RequestHttpEnum,
+  ContentTypeEnum,
+  RequestBodyEnum,
+  RequestDataTypeEnum,
+  RequestContentTypeEnum,
+  RequestParamsObjType
+} from '@/enums/httpEnum'
 import type { RequestGlobalConfigType, RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
 
 export const get = (url: string, params?: object) => {
@@ -74,7 +81,110 @@ export const http = (type?: RequestHttpEnum) => {
   }
 }
 
-// 自定义请求
-export const customizeHttp = (comParams: RequestConfigType, globalParams: RequestGlobalConfigType) => {
-  
+/**
+ * * 自定义请求
+ * @param targetParams 当前组件参数
+ * @param globalParams 全局参数
+ */
+export const customizeHttp = (targetParams: RequestConfigType, globalParams: RequestGlobalConfigType) => {
+  if(!targetParams || !globalParams) {
+    return
+  }
+
+  // 全局
+  const {
+    // 全局请求源地址
+    requestOriginUrl,
+    // 全局请求内容
+    requestParams: globalRequestParams
+  } = globalParams
+
+  // 目标组件(优先级 > 全局组件)
+  const {
+    // 请求地址
+    requestUrl,
+    // 普通 / sql
+    requestContentType,
+    // 获取数据的方式
+    requestDataType,
+    // 请求方式 get/post/del/put/patch
+    requestHttpType,
+    // 请求体类型 none / form-data / x-www-form-urlencoded / json /xml
+    requestParamsBodyType,
+    // SQL 请求对象
+    requestSQLContent,
+    // 请求内容 params / cookie / header / body: 同 requestParamsBodyType
+    requestParams: targetRequestParams
+  } = targetParams
+
+  // 静态排除
+  if (requestDataType === RequestDataTypeEnum.STATIC) return
+
+  if (!requestUrl) {
+    return
+  }
+
+  // 处理头部
+  const headers: RequestParamsObjType = {
+    ...globalRequestParams.Header,
+    ...targetRequestParams.Header,
+  }
+
+  // data 参数
+  let data: RequestParamsObjType | FormData | string = {}
+  // params 参数
+  let params: RequestParamsObjType = targetRequestParams.Params
+  // form 类型处理
+  let formData: FormData = new FormData()
+  formData.set('default', 'defaultData')
+  // 类型处理
+
+  switch (requestParamsBodyType) {
+    case RequestBodyEnum.NONE:
+      break
+
+    case RequestBodyEnum.JSON:
+      headers['Content-Type'] = ContentTypeEnum.JSON
+      data = JSON.parse(targetRequestParams.Body['json'])
+      // json 赋值给 data
+      break
+
+    case RequestBodyEnum.XML:
+      headers['Content-Type'] = ContentTypeEnum.XML
+      // xml 字符串赋值给 data
+      data = targetRequestParams.Body['xml']
+      break
+
+    case RequestBodyEnum.X_WWW_FORM_URLENCODED:
+      headers['Content-Type'] = ContentTypeEnum.FORM_URLENCODED
+      const bodyFormData = targetRequestParams.Body['x-www-form-urlencoded']
+      for (const i in bodyFormData) formData.set(i, bodyFormData[i])
+      // FormData 赋值给 data
+      data = formData
+      break
+
+    case RequestBodyEnum.FORM_DATA:
+      headers['Content-Type'] = ContentTypeEnum.FORM_DATA
+      const bodyFormUrlencoded = targetRequestParams.Body['form-data']
+      for (const i in bodyFormUrlencoded) {
+        formData.set(i, bodyFormUrlencoded[i])
+      }
+      // FormData 赋值给 data
+      data = formData
+      break
+  }
+
+  // sql 处理
+  if (requestContentType === RequestContentTypeEnum.SQL) {
+    headers['Content-Type'] = ContentTypeEnum.JSON
+    data = requestSQLContent
+  }
+
+  return axiosInstance({
+    url: `${requestOriginUrl}${requestUrl}`,
+    method: requestHttpType,
+    data,
+    params,
+    headers
+  })
 }

+ 4 - 4
src/enums/httpEnum.ts

@@ -90,7 +90,6 @@ export enum RequestParamsTypeEnum {
   PARAMS = 'Params',
   BODY = 'Body',
   HEADER = 'Header',
-  COOKIE = 'Cookie'
 }
 
 /**
@@ -101,7 +100,6 @@ export type RequestParamsObjType = {
 }
 export type RequestParams = {
   [RequestParamsTypeEnum.PARAMS]: RequestParamsObjType
-  [RequestParamsTypeEnum.COOKIE]: RequestParamsObjType
   [RequestParamsTypeEnum.HEADER]: RequestParamsObjType
   [RequestParamsTypeEnum.BODY]: {
     [RequestBodyEnum.FORM_DATA]: RequestParamsObjType
@@ -117,9 +115,11 @@ export type RequestParams = {
 export enum ContentTypeEnum {
   // json
   JSON = 'application/json;charset=UTF-8',
-  // json
+  // text
   TEXT = 'text/plain;charset=UTF-8',
-  // form-data 一般配合qs
+  // xml
+  XML = 'application/xml;charset=UTF-8',
+  // application/x-www-form-urlencoded 一般配合qs
   FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8',
   // form-data  上传
   FORM_DATA = 'multipart/form-data;charset=UTF-8'

+ 0 - 1
src/packages/public/publicConfig.ts

@@ -28,7 +28,6 @@ const requestConfig: RequestConfigType = {
       json: '',
       xml: ''
     },
-    Cookie: {},
     Header: {},
     Params: {}
   }

+ 0 - 1
src/store/modules/chartEditStore/chartEditStore.ts

@@ -119,7 +119,6 @@ export const useChartEditStore = defineStore({
           json: '',
           xml: ''
         },
-        Cookie: {},
         Header: {},
         Params: {}
       }

+ 16 - 1
src/utils/utils.ts

@@ -7,7 +7,7 @@ import html2canvas from 'html2canvas'
 import { downloadByA } from './file'
 import { toString } from './type'
 import cloneDeep from 'lodash/cloneDeep'
-import { RequestHttpIntervalEnum } from '@/enums/httpEnum'
+import { RequestHttpIntervalEnum, RequestParamsObjType } from '@/enums/httpEnum'
 
 /**
  * * 判断是否是开发环境
@@ -240,3 +240,18 @@ export const intervalUnitHandle = (num: number, unit: RequestHttpIntervalEnum) =
       return num * 1000
   }
 }
+
+/**
+ * * 对象转换 cookie 格式
+ * @param obj 
+ * @returns string
+ */
+export const objToCookie = (obj: RequestParamsObjType) => {
+  if(!obj) return ''
+  
+  let str = ''
+  for (const key in obj) {
+    str += key + '=' + obj[key] + ';'
+  }
+  return str.substr(0, str.length - 1)
+}

+ 41 - 25
src/views/chart/ContentConfigurations/components/ChartData/components/ChartDataAjax/index.vue

@@ -1,16 +1,28 @@
 <template>
   <div class="go-chart-configurations-data-ajax">
     <n-card class="n-card-shallow">
-      <setting-item-box name="基础配置">
-        <setting-item name="请求方式">
+      <setting-item-box name="请求配置">
+        <setting-item name="类型">
+          <n-tag :bordered="false" type="primary">
+            {{ requestContentType === RequestContentTypeEnum.DEFAULT ? '普通请求' : 'SQL请求' }}
+          </n-tag>
+        </setting-item>
+
+        <setting-item name="方式">
           <n-input size="small" :placeholder="requestHttpType || '暂无'" :disabled="true"></n-input>
         </setting-item>
 
-        <setting-item name="请求间隔">
-          <n-input size="small" :placeholder="requestInterval || '暂无'" :disabled="true">
+        <setting-item name="组件间隔(高级)">
+          <n-input size="small" :placeholder="`${requestInterval}` || '暂无'" :disabled="true">
             <template #suffix> {{ SelectHttpTimeNameObj[requestIntervalUnit] }} </template>
           </n-input>
         </setting-item>
+
+        <setting-item name="全局间隔(默认)">
+          <n-input size="small" :placeholder="`${GlobalRequestInterval}` || '暂无'" :disabled="true">
+            <template #suffix> {{ SelectHttpTimeNameObj[GlobalRequestIntervalUnit] }} </template>
+          </n-input>
+        </setting-item>
       </setting-item-box>
 
       <setting-item-box name="源地址" :alone="true">
@@ -35,7 +47,7 @@
 
       <div class="edit-text" @click="requestModelHandle">
         <div class="go-absolute-center">
-          <n-button type="primary" secondary>点击配置</n-button>
+          <n-button type="primary" secondary>查看更多</n-button>
         </div>
       </div>
     </n-card>
@@ -72,14 +84,14 @@
 </template>
 
 <script setup lang="ts">
-import { ref, toRefs, onBeforeUnmount, watchEffect } from 'vue'
+import { ref, toRefs, onBeforeUnmount, watchEffect, toRaw } from 'vue'
 import { icon } from '@/plugins'
 import { useDesignStore } from '@/store/modules/designStore/designStore'
 import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
 import { ChartDataRequest } from '../ChartDataRequest/index'
-import { RequestHttpEnum, ResultEnum, SelectHttpTimeNameObj } from '@/enums/httpEnum'
+import { RequestHttpEnum, ResultEnum, SelectHttpTimeNameObj, RequestContentTypeEnum } from '@/enums/httpEnum'
 import { chartDataUrl, rankListUrl, scrollBoardUrl, numberFloatUrl, numberIntUrl, textUrl, imageUrl } from '@/api/mock'
-import { http } from '@/api/http'
+import { http, customizeHttp } from '@/api/http'
 import { SelectHttpType } from '../../index.d'
 import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
 import { useTargetData } from '../../../hooks/useTargetData.hook'
@@ -87,8 +99,14 @@ import { isDev, newFunctionHandle } from '@/utils'
 
 const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5
 const { targetData, chartEditStore } = useTargetData()
-const { requestUrl, requestHttpType, requestInterval, requestIntervalUnit } = toRefs(targetData.value.request)
-const { requestOriginUrl } = toRefs(chartEditStore.getRequestGlobalConfig)
+const { requestUrl, requestHttpType, requestInterval, requestIntervalUnit, requestContentType } = toRefs(
+  targetData.value.request
+)
+const {
+  requestOriginUrl,
+  requestInterval: GlobalRequestInterval,
+  requestIntervalUnit: GlobalRequestIntervalUnit
+} = toRefs(chartEditStore.getRequestGlobalConfig)
 const designStore = useDesignStore()
 const themeColor = ref(designStore.getAppTheme)
 
@@ -106,21 +124,19 @@ const requestModelHandle = () => {
 // 发送请求
 const sendHandle = async () => {
   loading.value = true
-  if (!targetData.value) return
-  const { requestUrl, requestHttpType } = targetData.value.request
-  if (!requestUrl) {
-    window['$message'].warning('请求参数不正确,请检查!')
-    return
-  }
-  const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl
-  const res = await http(requestHttpType)(completePath || '', {})
-  loading.value = false
-  if (res.status === ResultEnum.SUCCESS) {
-    targetData.value.option.dataset = newFunctionHandle(res.data, targetData.value.filter)
-    showMatching.value = true
-    return
+  try {
+    const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.requestGlobalConfig))
+    loading.value = false
+    if (res && res.status === ResultEnum.SUCCESS) {
+      targetData.value.option.dataset = newFunctionHandle(res.data, targetData.value.filter)
+      showMatching.value = true
+      return
+    }
+    window['$message'].warning('数据异常,请检查参数!')
+  } catch (error) {
+    loading.value = false
+    window['$message'].warning('数据异常,请检查参数!')
   }
-  window['$message'].warning('数据异常,请检查接口数据!')
 }
 
 watchEffect(() => {
@@ -152,7 +168,7 @@ onBeforeUnmount(() => {
       top: 0px;
       left: 0px;
       width: 325px;
-      height: 235px;
+      height: 292px;
       cursor: pointer;
       opacity: 0;
       transition: all 0.3s;

+ 6 - 11
src/views/chart/ContentConfigurations/components/ChartData/components/ChartDataMonacoEditor/index.vue

@@ -97,13 +97,13 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, computed, watch, toRefs } from 'vue'
+import { ref, computed, watch, toRefs, toRaw } from 'vue'
 import { MonacoEditor } from '@/components/Pages/MonacoEditor'
 import { useTargetData } from '../../../hooks/useTargetData.hook'
 import { RequestHttpEnum, RequestDataTypeEnum, ResultEnum } from '@/enums/httpEnum'
 import { icon } from '@/plugins'
 import { goDialog, toString } from '@/utils'
-import { http } from '@/api/http'
+import { http, customizeHttp } from '@/api/http'
 import cloneDeep from 'lodash/cloneDeep'
 
 const { DocumentTextIcon } = icon.ionicons5
@@ -124,19 +124,14 @@ const sourceData = ref<any>('')
 // 动态获取数据
 const fetchTargetData = async () => {
   try {
-    const { requestUrl, requestHttpType } = targetData.value.request
-    if (!requestUrl) {
-      sourceData.value = '请求参数不正确,请检查!'
-      return
-    }
-    const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl
-    const res = await http(requestHttpType)(completePath || '', {})
-    if (res.status === ResultEnum.SUCCESS) {
+    const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.requestGlobalConfig))
+    if (res && res.status === ResultEnum.SUCCESS) {
       sourceData.value = res.data
       return
     }
+    window['$message'].warning('数据异常,请检查参数!')
   } catch (error) {
-    window['$message'].warning('数据异常,请检查接口数据!')
+    window['$message'].warning('数据异常,请检查参数!')
   }
 }
 

+ 2 - 2
src/views/chart/ContentConfigurations/components/ChartData/components/ChartDataRequest/components/RequestGlobalHeaderTable/index.vue

@@ -19,11 +19,11 @@ const { chartEditStore } = useTargetData()
 const { requestParams } = toRefs(chartEditStore.getRequestGlobalConfig)
 
 const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.HEADER)
-const tabs = [RequestParamsTypeEnum.HEADER, RequestParamsTypeEnum.COOKIE]
+const tabs = [RequestParamsTypeEnum.HEADER]
 
 // 更新表格参数
 const updateRequestParams = (paramsObj: RequestParamsObjType) => {
-  if (tabValue.value === RequestParamsTypeEnum.HEADER || tabValue.value === RequestParamsTypeEnum.COOKIE) {
+  if (tabValue.value === RequestParamsTypeEnum.HEADER) {
     requestParams.value[tabValue.value] = paramsObj
   }
 }

+ 15 - 9
src/views/chart/ContentConfigurations/components/ChartData/components/ChartDataRequest/components/RequestHeader/index.vue

@@ -28,7 +28,7 @@
           </n-radio-group>
 
           <!-- 为 none 时 -->
-          <n-card class="go-mt-3" v-if="requestParamsBodyType === RequestBodyEnum['NONE']">
+          <n-card class="go-mt-3 go-pb-3" v-if="requestParamsBodyType === RequestBodyEnum['NONE']">
             <n-text depth="3">该请求没有 Body 体</n-text>
           </n-card>
 
@@ -69,12 +69,17 @@
       </div>
     </div>
     <div v-show="requestContentType === RequestContentTypeEnum.SQL">
-      <setting-item-box name="键名">
-        <n-tag type="primary" :bordered="false" style="width: 40px; font-size: 16px"> sql </n-tag>
-      </setting-item-box>
-      <setting-item-box name="键值">
-        <monaco-editor v-model:modelValue="requestSQLContent['sql']" width="600px" height="200px" language="sql" />
-      </setting-item-box>
+      <template v-if="requestHttpType === RequestHttpEnum.GET">
+        <n-text>SQL 类型不支持 Get 请求,请使用其它方式</n-text>
+      </template>
+      <template v-else>
+        <setting-item-box name="键名">
+          <n-tag type="primary" :bordered="false" style="width: 40px; font-size: 16px"> sql </n-tag>
+        </setting-item-box>
+        <setting-item-box name="键值">
+          <monaco-editor v-model:modelValue="requestSQLContent['sql']" width="600px" height="200px" language="sql" />
+        </setting-item-box>
+      </template>
     </div>
   </n-space>
 </template>
@@ -92,12 +97,13 @@ import {
   RequestContentTypeEnum,
   RequestParamsObjType,
   RequestBodyEnumList,
-  RequestBodyEnum
+  RequestBodyEnum,
+  RequestHttpEnum
 } from '@/enums/httpEnum'
 
 const { targetData } = useTargetData()
 
-const { requestContentType, requestSQLContent, requestParams, requestParamsBodyType } = toRefs(targetData.value.request)
+const { requestHttpType, requestContentType, requestSQLContent, requestParams, requestParamsBodyType } = toRefs(targetData.value.request)
 
 const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.PARAMS)