feat: 新增全局请求数据处理

This commit is contained in:
奔跑的面条 2022-07-16 19:01:05 +08:00
parent 20b196a12a
commit 5d9b3d5a9b
13 changed files with 231 additions and 109 deletions

View File

@ -4,7 +4,7 @@ import { http } from '@/api/http'
import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d' import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { RequestDataTypeEnum } from '@/enums/httpEnum' import { RequestDataTypeEnum } from '@/enums/httpEnum'
import { isPreview, newFunctionHandle } from '@/utils' import { isPreview, newFunctionHandle, intervalUnitHandle } from '@/utils'
// 获取类型 // 获取类型
type ChartEditStoreType = typeof useChartEditStore type ChartEditStoreType = typeof useChartEditStore
@ -25,7 +25,7 @@ export const useChartDataFetch = (
const requestIntervalFn = () => { const requestIntervalFn = () => {
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const { requestOriginUrl, requestInterval } = toRefs(chartEditStore.getRequestGlobalConfig) const { requestOriginUrl, requestInterval, requestIntervalUnit } = toRefs(chartEditStore.getRequestGlobalConfig)
// 组件类型 // 组件类型
const { chartFrame } = targetComponent.chartConfig const { chartFrame } = targetComponent.chartConfig
// 请求配置 // 请求配置
@ -35,45 +35,52 @@ export const useChartDataFetch = (
requestUrl, requestUrl,
requestInterval: targetInterval requestInterval: targetInterval
} = toRefs(targetComponent.request) } = toRefs(targetComponent.request)
// 非请求类型 // 非请求类型
if (requestDataType.value !== RequestDataTypeEnum.AJAX) return if (requestDataType.value !== RequestDataTypeEnum.AJAX || !requestInterval) return
// 处理地址
if (requestUrl?.value && requestInterval.value > 0) {
// requestOriginUrl 允许为空
const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value
if (!completePath) return
clearInterval(fetchInterval) try {
// 处理地址
// @ts-ignore
if (requestUrl?.value && requestInterval && requestInterval.value > 0) {
// requestOriginUrl 允许为空
const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value
if (!completePath) return
const fetchFn = async () => { clearInterval(fetchInterval)
const res: any = await http(requestHttpType.value)(completePath || '', {})
if (res.data) { const fetchFn = async () => {
try { const res: any = await http(requestHttpType.value)(completePath || '', {})
const filter = targetComponent.filter if (res.data) {
// 更新回调函数 try {
if (updateCallback) { const filter = targetComponent.filter
updateCallback(newFunctionHandle(res.data, filter)) // 更新回调函数
} else { if (updateCallback) {
// eCharts 组件配合 vChart 库更新方式 updateCallback(newFunctionHandle(res.data, filter))
if (chartFrame === ChartFrameEnum.ECHARTS) { } else {
if (vChartRef.value) { // eCharts 组件配合 vChart 库更新方式
vChartRef.value.setOption({ dataset: newFunctionHandle(res.data, filter) }) if (chartFrame === ChartFrameEnum.ECHARTS) {
if (vChartRef.value) {
vChartRef.value.setOption({ dataset: newFunctionHandle(res.data, filter) })
}
} }
} }
} catch (error) {
console.error(error)
} }
} catch (error) {
console.error(error)
} }
} }
// 立即调用
fetchFn()
// 开启定时
const time = targetInterval && targetInterval.value ? targetInterval.value : requestInterval.value
// 处理单位时间
fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, requestIntervalUnit.value))
} }
} catch (error) {}
// 立即调用
fetchFn()
// 开启定时
const time = targetInterval && targetInterval.value ? targetInterval.value : requestInterval.value
fetchInterval = setInterval(fetchFn, time * 1000)
}
} }
isPreview() && requestIntervalFn() isPreview() && requestIntervalFn()

View File

@ -53,6 +53,8 @@ import {
ArrowForward as ArrowForwardIcon, ArrowForward as ArrowForwardIcon,
Planet as PawIcon, Planet as PawIcon,
Search as SearchIcon, Search as SearchIcon,
ChevronUpOutline as ChevronUpOutlineIcon,
ChevronDownOutline as ChevronDownOutlineIcon
} from '@vicons/ionicons5' } from '@vicons/ionicons5'
import { import {
@ -194,7 +196,11 @@ const ionicons5 = {
// 搜索(放大镜) // 搜索(放大镜)
SearchIcon, SearchIcon,
// 过滤器 // 过滤器
FilterIcon FilterIcon,
// 向上
ChevronUpOutlineIcon,
// 向下
ChevronDownOutlineIcon
} }
const carbon = { const carbon = {

View File

@ -137,24 +137,24 @@ export enum ChartEditStoreEnum {
// 请求公共类型 // 请求公共类型
type RequestPublicConfigType = { type RequestPublicConfigType = {
// 组件定制轮询时间
requestInterval?: number
// 时间单位(时分秒) // 时间单位(时分秒)
requestIntervalUnit: RequestHttpIntervalEnum requestIntervalUnit: RequestHttpIntervalEnum
// 请求内容 // 请求内容
requestParams: RequestParams requestParams: RequestParams
// 请求体类型
requestParamsBodyType: RequestBodyEnum
} }
// 全局的图表请求配置 // 全局的图表请求配置
export interface RequestGlobalConfigType extends RequestPublicConfigType { export interface RequestGlobalConfigType extends RequestPublicConfigType {
// 组件定制轮询时间
requestInterval: number
// 请求源地址 // 请求源地址
requestOriginUrl?: string requestOriginUrl?: string
} }
// 单个图表请求配置 // 单个图表请求配置
export interface RequestConfigType extends RequestPublicConfigType { export interface RequestConfigType extends RequestPublicConfigType {
// 组件定制轮询时间
requestInterval?: number
// 获取数据的方式 // 获取数据的方式
requestDataType: RequestDataTypeEnum requestDataType: RequestDataTypeEnum
// 请求方式 get/post/del/put/patch // 请求方式 get/post/del/put/patch
@ -163,6 +163,8 @@ export interface RequestConfigType extends RequestPublicConfigType {
requestUrl?: string requestUrl?: string
// 请求内容主体方式 普通/sql // 请求内容主体方式 普通/sql
requestContentType: RequestContentTypeEnum requestContentType: RequestContentTypeEnum
// 请求体类型
requestParamsBodyType: RequestBodyEnum
// SQL 请求对象 // SQL 请求对象
requestSQLContent: { requestSQLContent: {
sql: string sql: string

View File

@ -112,7 +112,6 @@ export const useChartEditStore = defineStore({
requestOriginUrl: '', requestOriginUrl: '',
requestInterval: requestInterval, requestInterval: requestInterval,
requestIntervalUnit: requestIntervalUnit, requestIntervalUnit: requestIntervalUnit,
requestParamsBodyType: RequestBodyEnum.NONE,
requestParams: { requestParams: {
Body: { Body: {
"form-data": {}, "form-data": {},

View File

@ -6,7 +6,8 @@ import Image_404 from '../assets/images/exception/image-404.png'
import html2canvas from 'html2canvas' import html2canvas from 'html2canvas'
import { downloadByA } from './file' import { downloadByA } from './file'
import { toString } from './type' import { toString } from './type'
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep'
import { RequestHttpIntervalEnum } from '@/enums/httpEnum'
/** /**
* * * *
@ -203,7 +204,7 @@ export const newFunctionHandle = (
try { try {
if (!funcStr) return data if (!funcStr) return data
const fn = new Function('data', funcStr) const fn = new Function('data', funcStr)
const fnRes = fn( cloneDeep(data)) const fnRes = fn(cloneDeep(data))
const resHandle = isToString ? toString(fnRes) : fnRes const resHandle = isToString ? toString(fnRes) : fnRes
// 成功回调 // 成功回调
successCallBack && successCallBack(resHandle) successCallBack && successCallBack(resHandle)
@ -214,3 +215,28 @@ export const newFunctionHandle = (
return '函数执行错误' return '函数执行错误'
} }
} }
/**
* *
* @param num
* @param unit RequestHttpIntervalEnum
* @return number
*/
export const intervalUnitHandle = (num: number, unit: RequestHttpIntervalEnum) => {
switch (unit) {
// 秒
case RequestHttpIntervalEnum.SECOND:
return num * 1000
// 分
case RequestHttpIntervalEnum.MINUTE:
return num * 1000 * 60
// 时
case RequestHttpIntervalEnum.HOUR:
return num * 1000 * 60 * 60
// 天
case RequestHttpIntervalEnum.DAY:
return num * 1000 * 60 * 60 * 24
default:
return num * 1000
}
}

View File

@ -126,7 +126,6 @@ const fetchTargetData = async () => {
try { try {
const { requestUrl, requestHttpType } = targetData.value.request const { requestUrl, requestHttpType } = targetData.value.request
if (!requestUrl) { if (!requestUrl) {
window['$message'].warning('请求参数不正确,请检查!')
sourceData.value = '请求参数不正确,请检查!' sourceData.value = '请求参数不正确,请检查!'
return return
} }

View File

@ -10,7 +10,7 @@
> >
<!-- 源地址 --> <!-- 源地址 -->
<setting-item name="前置 URL"> <setting-item name="前置 URL">
<n-input v-model:value.trim="requestOriginUrl" :disabled="disabled" placeholder="http://127.0.0.1/"></n-input> <n-input v-model:value.trim="requestOriginUrl" :disabled="editDisabled" placeholder="http://127.0.0.1/"></n-input>
</setting-item> </setting-item>
<setting-item name="更新间隔(为 0 表示不更新)"> <setting-item name="更新间隔(为 0 表示不更新)">
<n-input-group> <n-input-group>
@ -19,7 +19,7 @@
v-model:value.trim="requestInterval" v-model:value.trim="requestInterval"
min="0" min="0"
:show-button="false" :show-button="false"
:disabled="disabled" :disabled="editDisabled"
placeholder="请输入数字" placeholder="请输入数字"
> >
</n-input-number> </n-input-number>
@ -28,11 +28,11 @@
class="select-time-options" class="select-time-options"
v-model:value="requestIntervalUnit" v-model:value="requestIntervalUnit"
:options="selectTimeOptions" :options="selectTimeOptions"
:disabled="disabled" :disabled="editDisabled"
/> />
</n-input-group> </n-input-group>
</setting-item> </setting-item>
<n-button v-show="disabled" type="primary" secondary @click="disabled = false"> <n-button v-show="editDisabled" type="primary" secondary @click="editDisabled = false">
<template #icon> <template #icon>
<n-icon> <n-icon>
<pencil-icon /> <pencil-icon />
@ -41,23 +41,61 @@
编辑配置 编辑配置
</n-button> </n-button>
</setting-item-box> </setting-item-box>
<!-- table 内容体 -->
<n-collapse-transition :show="showTable">
<request-global-header-table :editDisabled="editDisabled"></request-global-header-table>
</n-collapse-transition>
<!-- 箭头 -->
<div v-if="showTable" class="go-flex-center go-mt-3 down" @click="showTable = false">
<n-icon size="32">
<chevron-up-outline-icon />
</n-icon>
</div>
<div v-else class="go-flex-center go-mt-3 down" @click="showTable = true">
<n-tooltip trigger="hover" placement="top" :keep-alive-on-hover="false">
<template #trigger>
<n-icon size="32">
<chevron-down-outline-icon />
</n-icon>
</template>
展开
</n-tooltip>
</div>
</n-card> </n-card>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, toRefs } from 'vue' import { ref, toRefs } from 'vue'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook' import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { selectTypeOptions, selectTimeOptions } from '@/views/chart/ContentConfigurations/components/ChartData/index.d' import { selectTypeOptions, selectTimeOptions } from '@/views/chart/ContentConfigurations/components/ChartData/index.d'
import { RequestGlobalHeaderTable } from '../RequestGlobalHeaderTable'
import { icon } from '@/plugins' import { icon } from '@/plugins'
const { PencilIcon } = icon.ionicons5 const { PencilIcon, ChevronDownOutlineIcon, ChevronUpOutlineIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData() const { chartEditStore } = useTargetData()
const { requestOriginUrl, requestInterval, requestIntervalUnit } = toRefs(chartEditStore.getRequestGlobalConfig) const { requestOriginUrl, requestInterval, requestIntervalUnit } = toRefs(chartEditStore.getRequestGlobalConfig)
const disabled = ref(true) const editDisabled = ref(true)
const designStore = useDesignStore()
const themeColor = ref(designStore.getAppTheme)
const showTable = ref(true)
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.n-card-shallow {
&:hover {
border-color: v-bind('themeColor');
}
}
.down {
cursor: pointer;
&:hover {
color: v-bind('themeColor');
}
}
.select-time-number { .select-time-number {
width: 100%; width: 100%;
} }

View File

@ -0,0 +1,3 @@
import RequestGlobalHeaderTable from './index.vue'
export { RequestGlobalHeaderTable }

View File

@ -0,0 +1,32 @@
<template>
<div>
<n-tabs type="line" animated v-model:value="tabValue">
<n-tab v-for="item in tabs" :key="item" :name="item" :tab="item"> {{ item }} </n-tab>
</n-tabs>
<div class="go-mt-3">
<request-header-table :editDisabled="$attrs.editDisabled" :target="requestParams[tabValue]" @update="updateRequestParams"></request-header-table>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, toRefs } from 'vue'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { RequestHeaderTable } from '../RequestHeaderTable'
import { RequestParamsTypeEnum, RequestParamsObjType } from '@/enums/httpEnum'
const { chartEditStore } = useTargetData()
const { requestParams } = toRefs(chartEditStore.getRequestGlobalConfig)
const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.HEADER)
const tabs = [RequestParamsTypeEnum.HEADER, RequestParamsTypeEnum.COOKIE]
//
const updateRequestParams = (paramsObj: RequestParamsObjType) => {
if (tabValue.value === RequestParamsTypeEnum.HEADER || tabValue.value === RequestParamsTypeEnum.COOKIE) {
requestParams.value[tabValue.value] = paramsObj
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -12,7 +12,7 @@
</n-tabs> </n-tabs>
<!-- 各个页面 --> <!-- 各个页面 -->
<div class="tabs-content go-mt-3"> <div class="go-mt-3">
<div v-if="tabValue !== RequestParamsTypeEnum.BODY"> <div v-if="tabValue !== RequestParamsTypeEnum.BODY">
<request-header-table :target="requestParams[tabValue]" @update="updateRequestParams"></request-header-table> <request-header-table :target="requestParams[tabValue]" @update="updateRequestParams"></request-header-table>
</div> </div>
@ -80,7 +80,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, toRefs } from 'vue' import { ref, toRefs } from 'vue'
import { MonacoEditor } from '@/components/Pages/MonacoEditor' import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'

View File

@ -1,55 +1,54 @@
<template> <template>
<n-scrollbar style="max-height: 250px"> <n-table class="go-request-header-table-box" :single-line="false" size="small">
<n-table class="go-request-header-table-box" :single-line="false" size="small"> <thead>
<thead> <tr>
<tr> <th></th>
<th></th> <th>Key</th>
<th>Key</th> <th>Value</th>
<th>Value</th> <th>操作</th>
<th>操作</th> <th>结果</th>
<th>结果</th> </tr>
</tr> </thead>
</thead> <tbody>
<tbody> <tr v-for="(item, index) in tableArray.content" :key="index">
<tr v-for="(item, index) in tableArray.content" :key="index"> <td>
<td> {{ index + 1 }}
{{ index + 1 }} </td>
</td> <td>
<td> <n-input v-model:value="item.key" :disabled="editDisabled" type="text" size="small" @blur="blur" />
<n-input v-model:value="item.key" type="text" size="small" @blur="blur" /> </td>
</td> <td>
<td> <n-input v-model:value="item.value" :disabled="editDisabled" type="text" size="small" @blur="blur" />
<n-input v-model:value="item.value" type="text" size="small" @blur="blur" /> </td>
</td> <td>
<td> <div style="width: 80px">
<div style="width: 80px"> <n-button class="go-ml-2" type="primary" size="small" ghost :disabled="editDisabled" @click="add(index)"
<n-button class="go-ml-2" type="primary" size="small" ghost @click="add(index)">+</n-button> >+</n-button
<n-button >
class="go-ml-2" <n-button
type="warning" class="go-ml-2"
size="small" type="warning"
ghost size="small"
:disabled="index === 0" ghost
@click="remove(index)" :disabled="index === 0 && editDisabled"
> @click="remove(index)"
- >
</n-button> -
</div> </n-button>
</td> </div>
<td> </td>
<n-button v-if="item.error" class="go-ml-2" text type="error"> 格式错误 </n-button> <td>
<n-button v-else class="go-ml-2" text type="success"> 格式通过 </n-button> <n-button v-if="item.error" class="go-ml-2" text type="error"> 格式错误 </n-button>
</td> <n-button v-else class="go-ml-2" text type="primary"> 格式通过 </n-button>
</tr> </td>
</tbody> </tr>
</n-table> </tbody>
</n-scrollbar> </n-table>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, reactive, ref, toRefs, watch } from 'vue' import { PropType, reactive, ref, toRefs, watch } from 'vue'
import { RequestBodyEnum, RequestParamsObjType } from '@/enums/httpEnum' import { RequestParamsObjType } from '@/enums/httpEnum'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
const emits = defineEmits(['update']) const emits = defineEmits(['update'])
@ -58,12 +57,14 @@ const props = defineProps({
type: Object as PropType<RequestParamsObjType>, type: Object as PropType<RequestParamsObjType>,
required: true, required: true,
default: () => {} default: () => {}
},
editDisabled: {
type: Boolean,
required: false,
default: false
} }
}) })
const { targetData } = useTargetData()
const { requestParams } = toRefs(targetData.value.request)
// //
const error = ref(false) const error = ref(false)

View File

@ -24,7 +24,7 @@
<n-input-number <n-input-number
v-model:value.trim="requestInterval" v-model:value.trim="requestInterval"
class="select-time-number" class="select-time-number"
min="5" min="1"
:show-button="false" :show-button="false"
placeholder="可以为空" placeholder="可以为空"
> >

View File

@ -3,19 +3,23 @@
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 800px"> <n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 800px">
<template #header></template> <template #header></template>
<template #header-extra> </template> <template #header-extra> </template>
<n-space vertical> <n-scrollbar style="max-height: 718px">
<request-global-config></request-global-config> <div class="go-pr-3">
<request-target-config></request-target-config> <n-space vertical>
</n-space> <request-global-config></request-global-config>
<request-target-config></request-target-config>
</n-space>
</div>
</n-scrollbar>
<!-- 底部 --> <!-- 底部 -->
<template #action> <template #action>
<n-space justify="space-between"> <n-space justify="space-between">
<div> <div>
<n-text> {{chartConfig.categoryName ||rename}} </n-text> <n-text> {{ chartConfig.categoryName || rename }} </n-text>
<n-text> </n-text> <n-text> </n-text>
<n-tag type="primary" :bordered="false"> {{requestContentTypeObj[requestContentType]}} </n-tag> <n-tag type="primary" :bordered="false"> {{ requestContentTypeObj[requestContentType] }} </n-tag>
</div> </div>
<n-button type="primary" ghost @click="closeHandle">关闭</n-button> <n-button type="primary" ghost @click="closeHandle">确认</n-button>
</n-space> </n-space>
</template> </template>
</n-card> </n-card>
@ -38,7 +42,7 @@ const { requestContentType } = toRefs(targetData.value.request)
const requestContentTypeObj = { const requestContentTypeObj = {
[RequestContentTypeEnum.DEFAULT]: '普通请求', [RequestContentTypeEnum.DEFAULT]: '普通请求',
[RequestContentTypeEnum.SQL]: 'SQL 请求', [RequestContentTypeEnum.SQL]: 'SQL 请求'
} }
defineProps({ defineProps({
@ -59,5 +63,10 @@ const closeHandle = () => {
.n-card-shallow { .n-card-shallow {
background-color: rgba(0, 0, 0, 0) !important; background-color: rgba(0, 0, 0, 0) !important;
} }
@include deep() {
& > .n-card__content {
padding-right: 0;
}
}
} }
</style> </style>