Эх сурвалжийг харах

feat: 新增请求编辑页面

奔跑的面条 3 жил өмнө
parent
commit
20b196a12a

+ 4 - 0
src/components/Pages/MonacoEditor/EditorWorker.vue

@@ -5,6 +5,7 @@ import * as monaco from 'monaco-editor'
 import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
 import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
 import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
+import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
 
 self.MonacoEnvironment = {
   getWorker(workerId, label) {
@@ -14,6 +15,9 @@ self.MonacoEnvironment = {
     if (label === 'typescript' || label === 'javascript') {
       return new tsWorker()
     }
+    if (label === 'html') {
+      return new htmlWorker()
+    }
     return new editorWorker()
   }
 }

+ 22 - 7
src/enums/httpEnum.ts

@@ -65,12 +65,24 @@ export const SelectHttpTimeNameObj = {
  * @description: 请求头部类型
  */
 export enum RequestBodyEnum {
+  NONE = 'none',
   FORM_DATA = 'form-data',
   X_WWW_FORM_URLENCODED = 'x-www-form-urlencoded',
   JSON = 'json',
   XML = 'xml'
 }
 
+/**
+ * @description: 请求头部类型数组
+ */
+export const RequestBodyEnumList = [
+  RequestBodyEnum.NONE,
+  RequestBodyEnum.FORM_DATA,
+  RequestBodyEnum.X_WWW_FORM_URLENCODED,
+  RequestBodyEnum.JSON,
+  RequestBodyEnum.XML
+]
+
 /**
  * @description: 请求参数类型
  */
@@ -84,15 +96,18 @@ export enum RequestParamsTypeEnum {
 /**
  * @description: 请求参数主体
  */
+export type RequestParamsObjType = {
+  [T: string]: string
+}
 export type RequestParams = {
-  [RequestParamsTypeEnum.PARAMS]: object,
-  [RequestParamsTypeEnum.COOKIE]: object,
-  [RequestParamsTypeEnum.HEADER]: object,
+  [RequestParamsTypeEnum.PARAMS]: RequestParamsObjType
+  [RequestParamsTypeEnum.COOKIE]: RequestParamsObjType
+  [RequestParamsTypeEnum.HEADER]: RequestParamsObjType
   [RequestParamsTypeEnum.BODY]: {
-    [RequestBodyEnum.FORM_DATA]: object,
-    [RequestBodyEnum.X_WWW_FORM_URLENCODED]: object,
-    [RequestBodyEnum.JSON]: object,
-    [RequestBodyEnum.XML]: string,
+    [RequestBodyEnum.FORM_DATA]: RequestParamsObjType
+    [RequestBodyEnum.X_WWW_FORM_URLENCODED]: RequestParamsObjType
+    [RequestBodyEnum.JSON]: string
+    [RequestBodyEnum.XML]: string
   }
 }
 

+ 2 - 0
src/main.ts

@@ -7,6 +7,8 @@ import { setupNaive, setupDirectives, setupCustomComponents } from '@/plugins'
 import { GoAppProvider } from '@/components/GoAppProvider/index'
 import { setHtmlTheme } from '@/utils'
 
+// 引入全局样式
+import '@/styles/pages/index.scss'
 // 引入动画
 import 'animate.css/animate.min.css'
 // 引入标尺

+ 24 - 3
src/packages/public/publicConfig.ts

@@ -1,7 +1,13 @@
 import { getUUID } from '@/utils'
 import { PublicConfigType } from '@/packages/index.d'
 import { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
-import { RequestHttpEnum, RequestDataTypeEnum, RequestHttpIntervalEnum, RequestContentTypeEnum } from '@/enums/httpEnum'
+import {
+  RequestHttpEnum,
+  RequestDataTypeEnum,
+  RequestHttpIntervalEnum,
+  RequestContentTypeEnum,
+  RequestBodyEnum
+} from '@/enums/httpEnum'
 import { chartInitConfig } from '@/settings/designSetting'
 
 const requestConfig: RequestConfigType = {
@@ -10,7 +16,22 @@ const requestConfig: RequestConfigType = {
   requestUrl: '',
   requestInterval: undefined,
   requestIntervalUnit: RequestHttpIntervalEnum.SECOND,
-  requestContentType: RequestContentTypeEnum.DEFAULT
+  requestContentType: RequestContentTypeEnum.DEFAULT,
+  requestParamsBodyType: RequestBodyEnum.NONE,
+  requestSQLContent: {
+    sql: 'select * from  where'
+  },
+  requestParams: {
+    Body: {
+      'form-data': {},
+      'x-www-form-urlencoded': {},
+      json: '',
+      xml: ''
+    },
+    Cookie: {},
+    Header: {},
+    Params: {}
+  }
 }
 
 export class publicConfig implements PublicConfigType {
@@ -40,7 +61,7 @@ export class publicConfig implements PublicConfigType {
     // 倾斜
     skewX: 0,
     skewY: 0,
-    
+
     // 动画
     animations: []
   }

+ 10 - 2
src/store/modules/chartEditStore/chartEditStore.d.ts

@@ -5,9 +5,11 @@ import {
   RequestContentTypeEnum,
   RequestDataTypeEnum,
   RequestHttpIntervalEnum,
-  RequestParams
+  RequestParams,
+  RequestBodyEnum,
+  RequestParamsObjType
 } from '@/enums/httpEnum'
-import { PreviewScaleEnum, RequestBodyEnum } from '@/enums/styleEnum'
+import { PreviewScaleEnum } from '@/enums/styleEnum'
 import type { ChartColorsNameType, GlobalThemeJsonType } from '@/settings/chartThemes/index'
 
 // 编辑画布属性
@@ -141,6 +143,8 @@ type RequestPublicConfigType = {
   requestIntervalUnit: RequestHttpIntervalEnum
   // 请求内容
   requestParams: RequestParams
+  // 请求体类型
+  requestParamsBodyType: RequestBodyEnum
 }
 
 // 全局的图表请求配置
@@ -159,6 +163,10 @@ export interface RequestConfigType extends RequestPublicConfigType {
   requestUrl?: string
   // 请求内容主体方式 普通/sql
   requestContentType: RequestContentTypeEnum
+  // SQL 请求对象
+  requestSQLContent: {
+    sql: string
+  }
 }
 
 // Store 类型

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

@@ -4,6 +4,7 @@ import debounce from 'lodash/debounce'
 import cloneDeep from 'lodash/cloneDeep'
 import { defaultTheme, globalThemeJson } from '@/settings/chartThemes/index'
 import { requestInterval, previewScaleType, requestIntervalUnit } from '@/settings/designSetting'
+import { RequestBodyEnum } from '@/enums/httpEnum'
 // 记录记录
 import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
 // 全局设置
@@ -111,11 +112,12 @@ export const useChartEditStore = defineStore({
       requestOriginUrl: '',
       requestInterval: requestInterval,
       requestIntervalUnit: requestIntervalUnit,
+      requestParamsBodyType: RequestBodyEnum.NONE,
       requestParams: {
         Body: {
           "form-data": {},
           "x-www-form-urlencoded": {},
-          json: {},
+          json: '',
           xml: ''
         },
         Cookie: {},

+ 1 - 0
src/styles/pages/index.scss

@@ -0,0 +1 @@
+// 页面全局样式

+ 1 - 1
src/views/chart/ContentConfigurations/components/ChartData/components/ChartDataMatchingAndShow/index.vue

@@ -166,7 +166,7 @@ const dimensionsAndSourceHandle = () => {
 // 过滤结果
 const filterRes = (data: any) => {
   try {
-    if(targetData.value.filter) {
+    if (targetData.value.filter) {
       const fn = new Function('data', targetData.value.filter)
       const res = fn(cloneDeep(data))
       return toString(res)

+ 92 - 11
src/views/chart/ContentConfigurations/components/ChartData/components/ChartDataRequest/components/RequestHeader/index.vue

@@ -7,16 +7,73 @@
       </n-tabs>
     </div>
     <div v-show="requestContentType === RequestContentTypeEnum.DEFAULT">
-      <n-tabs type="line" animated>
+      <n-tabs type="line" animated v-model:value="tabValue">
         <n-tab v-for="item in RequestParamsTypeEnum" :key="item" :name="item" :tab="item"> {{ item }} </n-tab>
       </n-tabs>
+
+      <!-- 各个页面 -->
+      <div class="tabs-content go-mt-3">
+        <div v-if="tabValue !== RequestParamsTypeEnum.BODY">
+          <request-header-table :target="requestParams[tabValue]" @update="updateRequestParams"></request-header-table>
+        </div>
+
+        <!-- 选择了 body -->
+        <div v-else>
+          <n-radio-group v-model:value="requestParamsBodyType" name="radiogroup">
+            <n-space>
+              <n-radio v-for="bodyEnum in RequestBodyEnumList" :key="bodyEnum" :value="bodyEnum">
+                {{ bodyEnum }}
+              </n-radio>
+            </n-space>
+          </n-radio-group>
+
+          <!-- 为 none 时 -->
+          <n-card class="go-mt-3" v-if="requestParamsBodyType === RequestBodyEnum['NONE']">
+            <n-text depth="3">该请求没有 Body 体</n-text>
+          </n-card>
+
+          <!-- 具有对象属性时 -->
+          <template
+            v-else-if="
+              requestParamsBodyType === RequestBodyEnum['FORM_DATA'] ||
+              requestParamsBodyType === RequestBodyEnum['X_WWW_FORM_URLENCODED']
+            "
+          >
+            <request-header-table
+              class="go-mt-3"
+              :target="requestParams[RequestParamsTypeEnum.BODY][requestParamsBodyType]"
+              @update="updateRequestBodyTable"
+            ></request-header-table>
+          </template>
+
+          <!-- json  -->
+          <template v-else-if="requestParamsBodyType === RequestBodyEnum['JSON']">
+            <monaco-editor
+              v-model:modelValue="requestParams[RequestParamsTypeEnum.BODY][requestParamsBodyType]"
+              width="600px"
+              height="200px"
+              language="json"
+            />
+          </template>
+
+          <!-- xml  -->
+          <template v-else-if="requestParamsBodyType === RequestBodyEnum['XML']">
+            <monaco-editor
+              v-model:modelValue="requestParams[RequestParamsTypeEnum.BODY][requestParamsBodyType]"
+              width="600px"
+              height="200px"
+              language="html"
+            />
+          </template>
+        </div>
+      </div>
     </div>
     <div v-show="requestContentType === RequestContentTypeEnum.SQL">
       <setting-item-box name="键名">
-        <n-input v-model:value.trim="sqlObject.key" :min="1" placeholder="请输入内容" />
+        <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="sqlObject.value" width="600px" height="200px" language="sql" />
+        <monaco-editor v-model:modelValue="requestSQLContent['sql']" width="600px" height="200px" language="sql" />
       </setting-item-box>
     </div>
   </n-space>
@@ -24,20 +81,44 @@
 
 <script setup lang="ts">
 import { reactive, ref, toRefs } from 'vue'
-import { RequestParamsTypeEnum, RequestContentTypeEnum ,RequestBodyEnum } from '@/enums/httpEnum'
+
 import { MonacoEditor } from '@/components/Pages/MonacoEditor'
 import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
 import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
+import { RequestHeaderTable } from '../RequestHeaderTable/index'
+
+import {
+  RequestParamsTypeEnum,
+  RequestContentTypeEnum,
+  RequestParamsObjType,
+  RequestBodyEnumList,
+  RequestBodyEnum
+} from '@/enums/httpEnum'
+
+const { targetData } = useTargetData()
 
-const { targetData, chartEditStore } = useTargetData()
+const { requestContentType, requestSQLContent, requestParams, requestParamsBodyType } = toRefs(targetData.value.request)
 
-const { requestContentType } = toRefs(targetData.value.request)
+const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.PARAMS)
 
-const tabValue = ref(RequestParamsTypeEnum.NONE)
-const sqlObject = reactive({
-  key: 'sql',
-  value: 'select * from  where'
-})
+// 更新参数表格数据
+const updateRequestParams = (paramsObj: RequestParamsObjType) => {
+  if (tabValue.value !== RequestParamsTypeEnum.BODY) {
+    requestParams.value[tabValue.value] = paramsObj
+  }
+}
+
+// 更新参数表格数据
+const updateRequestBodyTable = (paramsObj: RequestParamsObjType) => {
+  if (
+    tabValue.value === RequestParamsTypeEnum.BODY &&
+    // 仅有两种类型有 body
+    (requestParamsBodyType.value === RequestBodyEnum.FORM_DATA ||
+      requestParamsBodyType.value === RequestBodyEnum.X_WWW_FORM_URLENCODED)
+  ) {
+    requestParams.value[RequestParamsTypeEnum.BODY][requestParamsBodyType.value] = paramsObj
+  }
+}
 </script>
 
 <style lang="scss" scoped>

+ 153 - 4
src/views/chart/ContentConfigurations/components/ChartData/components/ChartDataRequest/components/RequestHeaderTable/index.vue

@@ -1,11 +1,160 @@
 <template>
-  <n-scrollbar style="max-height: 250px"> 
-    <n-h1>2321</n-h1>
+  <n-scrollbar style="max-height: 250px">
+    <n-table class="go-request-header-table-box" :single-line="false" size="small">
+      <thead>
+        <tr>
+          <th></th>
+          <th>Key</th>
+          <th>Value</th>
+          <th>操作</th>
+          <th>结果</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr v-for="(item, index) in tableArray.content" :key="index">
+          <td>
+            {{ index + 1 }}
+          </td>
+          <td>
+            <n-input v-model:value="item.key" type="text" size="small" @blur="blur" />
+          </td>
+          <td>
+            <n-input v-model:value="item.value" type="text" size="small" @blur="blur" />
+          </td>
+          <td>
+            <div style="width: 80px">
+              <n-button class="go-ml-2" type="primary" size="small" ghost @click="add(index)">+</n-button>
+              <n-button
+                class="go-ml-2"
+                type="warning"
+                size="small"
+                ghost
+                :disabled="index === 0"
+                @click="remove(index)"
+              >
+                -
+              </n-button>
+            </div>
+          </td>
+          <td>
+            <n-button v-if="item.error" class="go-ml-2" text type="error"> 格式错误 </n-button>
+            <n-button v-else class="go-ml-2" text type="success"> 格式通过 </n-button>
+          </td>
+        </tr>
+      </tbody>
+    </n-table>
   </n-scrollbar>
 </template>
 
 <script setup lang="ts">
-import { RequestBodyEnum, RequestParamsTypeEnum } from '@/enums/httpEnum'
+import { PropType, reactive, ref, toRefs, watch } from 'vue'
+import { RequestBodyEnum, RequestParamsObjType } from '@/enums/httpEnum'
+import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
+
+const emits = defineEmits(['update'])
+
+const props = defineProps({
+  target: {
+    type: Object as PropType<RequestParamsObjType>,
+    required: true,
+    default: () => {}
+  }
+})
+
+const { targetData } = useTargetData()
+const { requestParams } = toRefs(targetData.value.request)
+
+// 错误标识
+const error = ref(false)
+
+// 默认表格
+const defaultItem = {
+  key: '',
+  value: '',
+  error: false
+}
+const tableArray = reactive<{
+  content: typeof defaultItem[]
+}>({ content: [] })
+
+// 失焦
+const blur = () => {
+  let successNum = 0
+  tableArray.content.forEach(item => {
+    if ((item.key !== '' && item.value == '') || (item.key === '' && item.value !== '')) {
+      // 错误
+      item.error = true
+    } else {
+      // 正确
+      successNum++
+      item.error = false
+    }
+  })
+  // 验证是否全部通过
+  if (successNum == tableArray.content.length) {
+    // 转换数据成对象
+    const updateObj: any = {}
+    tableArray.content.forEach((e: typeof defaultItem) => {
+      if (e.key) updateObj[e.key] = e.value
+    })
+    emits('update', updateObj)
+  }
+}
+
+// 新增
+const add = (index: number) => {
+  tableArray.content.splice(index + 1, 0, {
+    key: '',
+    value: '',
+    error: false
+  })
+}
+
+// 减少
+const remove = (index: number) => {
+  if (tableArray.content.length !== 1) {
+    tableArray.content.splice(index, 1)
+  }
+  blur()
+}
+
+// 监听选项
+watch(
+  () => props.target,
+  (target: RequestParamsObjType) => {
+    tableArray.content = []
+    for (const k in target) {
+      tableArray.content.push({
+        key: k,
+        value: target[k],
+        error: false
+      })
+    }
+    // 默认值
+    if (!tableArray.content.length) tableArray.content = [JSON.parse(JSON.stringify(defaultItem))]
+  },
+  {
+    immediate: true,
+    deep: true
+  }
+)
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss">
+@include go('request-header-table-box') {
+  background-color: rgba(0, 0, 0, 0);
+  @include deep() {
+    .n-data-table .n-data-table-td {
+      background-color: rgba(0, 0, 0, 0);
+    }
+    .add-btn-box {
+      width: 100%;
+      display: flex;
+      justify-content: center;
+      .add-btn {
+        width: 300px;
+      }
+    }
+  }
+}
+</style>

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

@@ -7,7 +7,7 @@
       gridTemplateColumns: '5fr 2fr 1fr'
     }"
   >
-    <setting-item name="请求 URL">
+    <setting-item name="请求方式 & URL 地址">
       <n-input-group>
         <n-select class="select-type-options" v-model:value="requestHttpType" :options="selectTypeOptions" />
         <n-input v-model:value.trim="requestUrl" :min="1" placeholder="请输入地址(去除源)">
@@ -55,11 +55,10 @@ import { selectTypeOptions, selectTimeOptions } from '@/views/chart/ContentConfi
 import { RequestHeader } from '../RequestHeader'
 import { icon } from '@/plugins'
 
-const { PencilIcon, FlashIcon } = icon.ionicons5
+const { FlashIcon } = icon.ionicons5
 const { targetData, chartEditStore } = useTargetData()
 const { requestOriginUrl } = toRefs(chartEditStore.getRequestGlobalConfig)
 const { requestInterval, requestIntervalUnit, requestHttpType, requestUrl } = toRefs(targetData.value.request)
-const disabled = ref(true)
 </script>
 
 <style lang="scss" scoped>

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

@@ -11,7 +11,7 @@
       <template #action>
         <n-space justify="space-between">
           <div>
-            <n-text>「 柱状图 」</n-text>
+            <n-text>「 {{chartConfig.categoryName ||rename}} 」</n-text>
             <n-text>—— </n-text>
             <n-tag type="primary" :bordered="false"> {{requestContentTypeObj[requestContentType]}} </n-tag>
           </div>
@@ -31,8 +31,9 @@ import { RequestTargetConfig } from './components/RequestTargetConfig'
 
 const emit = defineEmits(['update:modelShow'])
 
-const { targetData, chartEditStore } = useTargetData()
+const { targetData } = useTargetData()
 // 解构基础配置
+const { chartConfig, rename } = toRefs(targetData.value)
 const { requestContentType } = toRefs(targetData.value.request)
 
 const requestContentTypeObj = {

+ 1 - 1
vite.config.ts

@@ -38,7 +38,7 @@ export default defineConfig({
   plugins: [
     vue(),
     monacoEditorPlugin({
-      languageWorkers: ['editorWorkerService', 'typescript', 'json']
+      languageWorkers: ['editorWorkerService', 'typescript', 'json', 'html']
     }),
     viteMockServe({
       mockPath: '/src/api/mock',