Merge branch 'dev'

This commit is contained in:
奔跑的面条
2023-04-23 21:09:21 +08:00
5 changed files with 539 additions and 534 deletions
@@ -1,196 +1,197 @@
<template>
<div class="go-chart-configurations-data-ajax">
<n-card class="n-card-shallow">
<setting-item-box name="请求配置">
<setting-item name="类型">
<n-tag :bordered="false" type="primary" style="border-radius: 5px">
{{ targetData.request.requestContentType === RequestContentTypeEnum.DEFAULT ? '普通请求' : 'SQL请求' }}
</n-tag>
</setting-item>
<setting-item name="方式">
<n-input size="small" :placeholder="targetData.request.requestHttpType || '暂无'" :disabled="true"></n-input>
</setting-item>
<setting-item name="组件间隔">
<n-input size="small" :placeholder="`${targetData.request.requestInterval || '暂无'}`" :disabled="true">
<template #suffix> {{ SelectHttpTimeNameObj[targetData.request.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">
<n-input size="small" :placeholder="requestOriginUrl || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="PulseIcon" />
</template>
</n-input>
</setting-item-box>
<setting-item-box name="组件地址" :alone="true">
<n-input size="small" :placeholder="targetData.request.requestUrl || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="FlashIcon" />
</template>
</n-input>
</setting-item-box>
<div class="edit-text" @click="requestModelHandle">
<div class="go-absolute-center">
<n-button type="primary" secondary>编辑配置</n-button>
</div>
</div>
</n-card>
<setting-item-box :alone="true">
<template #name>
测试
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
默认赋值给 dataset 字段
</n-tooltip>
</template>
<n-button type="primary" ghost @click="sendHandle">
<template #icon>
<n-icon>
<flash-icon />
</n-icon>
</template>
发送请求
</n-button>
</setting-item-box>
<!-- 底部数据展示 -->
<chart-data-matching-and-show :show="showMatching && !loading" :ajax="true"></chart-data-matching-and-show>
<!-- 骨架图 -->
<go-skeleton :load="loading" :repeat="3"></go-skeleton>
<!-- 请求配置model -->
<chart-data-request
v-model:modelShow="requestShow"
:targetData="targetData"
@sendHandle="sendHandle"
></chart-data-request>
</div>
</template>
<script setup lang="ts">
import { ref, toRefs, computed, 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, RequestContentTypeEnum } from '@/enums/httpEnum'
import { chartDataUrl, rankListUrl, scrollBoardUrl, numberFloatUrl, numberIntUrl, textUrl, imageUrl } from '@/api/mock'
import { http, customizeHttp } from '@/api/http'
import { SelectHttpType } from '../../index.d'
import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { newFunctionHandle } from '@/utils'
const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData()
const {
requestOriginUrl,
requestInterval: GlobalRequestInterval,
requestIntervalUnit: GlobalRequestIntervalUnit
} = toRefs(chartEditStore.getRequestGlobalConfig)
const designStore = useDesignStore()
// 是否展示数据分析
const loading = ref(false)
const requestShow = ref(false)
const showMatching = ref(false)
let firstFocus = 0
let lastFilter: any = undefined
// 请求配置 model
const requestModelHandle = () => {
requestShow.value = true
}
// 发送请求
const sendHandle = async () => {
if (!targetData.value?.request) return
loading.value = true
try {
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
loading.value = false
if (res) {
if (!res?.data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
targetData.value.option.dataset = newFunctionHandle(res?.data, res, targetData.value.filter)
showMatching.value = true
return
}
window['$message'].warning('没有拿到返回值,请检查接口!')
} catch (error) {
console.error(error);
loading.value = false
window['$message'].warning('数据异常,请检查参数!')
}
}
// 颜色
const themeColor = computed(() => {
return designStore.getAppTheme
})
watchEffect(() => {
const filter = targetData.value?.filter
if (lastFilter !== filter && firstFocus) {
lastFilter = filter
sendHandle()
}
firstFocus++
})
onBeforeUnmount(() => {
lastFilter = null
})
</script>
<style lang="scss" scoped>
@include go('chart-configurations-data-ajax') {
.n-card-shallow {
&.n-card {
@extend .go-background-filter;
@include deep() {
.n-card__content {
padding: 10px;
}
}
}
.edit-text {
position: absolute;
top: 0px;
left: 0px;
width: 325px;
height: 270px;
cursor: pointer;
opacity: 0;
transition: all 0.3s;
@extend .go-background-filter;
backdrop-filter: blur(2px) !important;
}
&:hover {
border-color: v-bind('themeColor');
.edit-text {
opacity: 1;
}
}
}
}
</style>
<template>
<div class="go-chart-configurations-data-ajax">
<n-card class="n-card-shallow">
<setting-item-box name="请求配置">
<setting-item name="类型">
<n-tag :bordered="false" type="primary" style="border-radius: 5px">
{{ targetData.request.requestContentType === RequestContentTypeEnum.DEFAULT ? '普通请求' : 'SQL请求' }}
</n-tag>
</setting-item>
<setting-item name="方式">
<n-input size="small" :placeholder="targetData.request.requestHttpType || '暂无'" :disabled="true"></n-input>
</setting-item>
<setting-item name="组件间隔">
<n-input size="small" :placeholder="`${targetData.request.requestInterval || '暂无'}`" :disabled="true">
<template #suffix> {{ SelectHttpTimeNameObj[targetData.request.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">
<n-input size="small" :placeholder="requestOriginUrl || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="PulseIcon" />
</template>
</n-input>
</setting-item-box>
<setting-item-box name="组件地址" :alone="true">
<n-input size="small" :placeholder="targetData.request.requestUrl || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="FlashIcon" />
</template>
</n-input>
</setting-item-box>
<div class="edit-text" @click="requestModelHandle">
<div class="go-absolute-center">
<n-button type="primary" secondary>编辑配置</n-button>
</div>
</div>
</n-card>
<setting-item-box :alone="true">
<template #name>
测试
<n-tooltip trigger="hover">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
默认赋值给 dataset 字段
</n-tooltip>
</template>
<n-button type="primary" ghost @click="sendHandle">
<template #icon>
<n-icon>
<flash-icon />
</n-icon>
</template>
发送请求
</n-button>
</setting-item-box>
<!-- 底部数据展示 -->
<chart-data-matching-and-show :show="showMatching && !loading" :ajax="true"></chart-data-matching-and-show>
<!-- 骨架图 -->
<go-skeleton :load="loading" :repeat="3"></go-skeleton>
<!-- 请求配置model -->
<chart-data-request
v-model:modelShow="requestShow"
:targetData="targetData"
@sendHandle="sendHandle"
></chart-data-request>
</div>
</template>
<script setup lang="ts">
import { ref, toRefs, computed, 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, RequestContentTypeEnum } from '@/enums/httpEnum'
import { chartDataUrl, rankListUrl, scrollBoardUrl, numberFloatUrl, numberIntUrl, textUrl, imageUrl } from '@/api/mock'
import { http, customizeHttp } from '@/api/http'
import { SelectHttpType } from '../../index.d'
import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { newFunctionHandle } from '@/utils'
const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData()
const {
requestOriginUrl,
requestInterval: GlobalRequestInterval,
requestIntervalUnit: GlobalRequestIntervalUnit
} = toRefs(chartEditStore.getRequestGlobalConfig)
const designStore = useDesignStore()
// 是否展示数据分析
const loading = ref(false)
const requestShow = ref(false)
const showMatching = ref(false)
let firstFocus = 0
let lastFilter: any = undefined
// 请求配置 model
const requestModelHandle = () => {
requestShow.value = true
}
// 发送请求
const sendHandle = async () => {
if (!targetData.value?.request) return
loading.value = true
try {
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
loading.value = false
if (res) {
const { data } = res
if (!data && !targetData.value.filter) window['$message'].warning('您的数据不符合默认格式,请配置过滤器!')
targetData.value.option.dataset = newFunctionHandle(data, res, targetData.value.filter)
showMatching.value = true
return
}
window['$message'].warning('没有拿到返回值,请检查接口!')
} catch (error) {
console.error(error);
loading.value = false
window['$message'].warning('数据异常,请检查参数!')
}
}
// 颜色
const themeColor = computed(() => {
return designStore.getAppTheme
})
watchEffect(() => {
const filter = targetData.value?.filter
if (lastFilter !== filter && firstFocus) {
lastFilter = filter
sendHandle()
}
firstFocus++
})
onBeforeUnmount(() => {
lastFilter = null
})
</script>
<style lang="scss" scoped>
@include go('chart-configurations-data-ajax') {
.n-card-shallow {
&.n-card {
@extend .go-background-filter;
@include deep() {
.n-card__content {
padding: 10px;
}
}
}
.edit-text {
position: absolute;
top: 0px;
left: 0px;
width: 325px;
height: 270px;
cursor: pointer;
opacity: 0;
transition: all 0.3s;
@extend .go-background-filter;
backdrop-filter: blur(2px) !important;
}
&:hover {
border-color: v-bind('themeColor');
.edit-text {
opacity: 1;
}
}
}
}
</style>
@@ -1,215 +1,215 @@
<template>
<template v-if="targetData.filter">
<n-card>
<p><span class="func-keyword">function</span>&nbsp;&nbsp;filter(data, res)&nbsp;&nbsp;{</p>
<!-- 函数体 -->
<div class="go-ml-4">
<n-code :code="targetData.filter" language="typescript"></n-code>
</div>
<p>}</p>
<template #footer>
<n-space justify="end">
<n-button type="primary" tertiary size="small" @click="addFilter">
<template #icon>
<n-icon>
<filter-edit-icon />
</n-icon>
</template>
编辑
</n-button>
<n-button tertiary size="small" @click="delFilter"> 删除 </n-button>
</n-space>
</template>
</n-card>
</template>
<template v-else>
<n-button class="go-ml-3" @click="addFilter">
<template #icon>
<n-icon>
<filter-icon />
</n-icon>
</template>
新增过滤器
</n-button>
</template>
<!-- 弹窗 -->
<n-modal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false" :closeOnEsc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 600px">
<template #header>
<n-space>
<n-text>过滤器函数编辑器</n-text>
</n-space>
</template>
<template #header-extra> </template>
<n-space size="small" vertical>
<n-space justify="space-between">
<div>
<n-space vertical>
<n-tag type="info">
<span class="func-keyword">function</span>&nbsp;&nbsp;filter(data, res)&nbsp;&nbsp;{
</n-tag>
<monaco-editor v-model:modelValue="filter" width="460px" height="380px" language="javascript" />
<n-tag type="info">}</n-tag>
</n-space>
</div>
<n-divider vertical style="height: 480px" />
<n-scrollbar style="max-height: 480px">
<n-space :size="15" vertical>
<div class="editor-data-show">
<n-space>
<n-text depth="3">默认过滤数据(data)</n-text>
<n-code :code="toString(sourceData?.data) || '暂无'" language="json" :word-wrap="true"></n-code>
</n-space>
</div>
<div class="editor-data-show">
<n-space>
<n-text depth="3">接口返回数据(res)</n-text>
<n-code :code="toString(sourceData) || '暂无'" language="json" :word-wrap="true"></n-code>
</n-space>
</div>
<div class="editor-data-show">
<n-space>
<n-text depth="3">过滤器结果</n-text>
<n-code :code="filterRes || '暂无'" language="json" :word-wrap="true"></n-code>
</n-space>
</div>
</n-space>
</n-scrollbar>
</n-space>
</n-space>
<template #action>
<n-space justify="space-between">
<div class="go-flex-items-center">
<n-tag :bordered="false" type="primary">
<template #icon>
<n-icon :component="DocumentTextIcon" />
</template>
规则
</n-tag>
<n-text class="go-ml-2" depth="2">过滤器默认处理接口返回值的data字段</n-text>
</div>
<n-space>
<n-button size="medium" @click="closeFilter">取消</n-button>
<n-button size="medium" type="primary" @click="saveFilter">保存</n-button>
</n-space>
</n-space>
</template>
</n-card>
</n-modal>
</template>
<script lang="ts" setup>
import { ref, computed, watch, toRef, toRefs, toRaw, reactive } from 'vue'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { icon } from '@/plugins'
import { goDialog, toString } from '@/utils'
import { customizeHttp } from '@/api/http'
import cloneDeep from 'lodash/cloneDeep'
const { DocumentTextIcon } = icon.ionicons5
const { FilterIcon, FilterEditIcon } = icon.carbon
const { targetData, chartEditStore } = useTargetData()
const { requestDataType } = toRefs(targetData.value.request)
const { requestOriginUrl } = toRefs(chartEditStore.getRequestGlobalConfig)
// 受控弹窗
const showModal = ref(false)
// filter 函数模板
const filter = ref(targetData.value.filter || `return data`)
// 过滤错误标识
const errorFlag = ref(false)
// 目标静态/接口数据
const sourceData = ref<any>('')
// 动态获取数据
const fetchTargetData = async () => {
try {
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
if (res) {
sourceData.value = res
return
}
window['$message'].warning('没有拿到返回值,请检查接口!')
} catch (error) {
console.error(error);
window['$message'].warning('数据异常,请检查参数!')
}
}
// 过滤结果
const filterRes = computed(() => {
try {
const fn = new Function('data', 'res', filter.value)
const response = cloneDeep(sourceData.value)
const res = fn(response?.data, response)
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
errorFlag.value = false
return toString(res)
} catch (error) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
errorFlag.value = true
return `过滤函数错误,日志:${error}`
}
})
// 新增过滤器
const addFilter = () => {
showModal.value = true
}
// 删除过滤器
const delFilter = () => {
goDialog({
message: '是否删除过滤器',
onPositiveCallback: () => {
targetData.value.filter = undefined
}
})
}
// 关闭过滤器
const closeFilter = () => {
showModal.value = false
}
// 新增过滤器
const saveFilter = () => {
if (errorFlag.value) {
window['$message'].error('过滤函数错误,无法进行保存')
return
}
targetData.value.filter = filter.value
closeFilter()
}
watch(
() => showModal.value,
(newData: boolean) => {
if (newData) {
fetchTargetData()
filter.value = targetData.value.filter || `return data`
}
}
)
</script>
<style lang="scss" scoped>
.func-keyword {
color: #b478cf;
}
@include go('chart-data-monaco-editor') {
&.n-card.n-modal,
.n-card {
@extend .go-background-filter;
}
.editor-data-show {
@include fetch-bg-color('filter-color');
width: 420px;
padding: 20px;
border-radius: 5px;
}
}
</style>
<template>
<template v-if="targetData.filter">
<n-card>
<p><span class="func-keyword">function</span>&nbsp;&nbsp;filter(data, res)&nbsp;&nbsp;{</p>
<!-- 函数体 -->
<div class="go-ml-4">
<n-code :code="targetData.filter" language="typescript"></n-code>
</div>
<p>}</p>
<template #footer>
<n-space justify="end">
<n-button type="primary" tertiary size="small" @click="addFilter">
<template #icon>
<n-icon>
<filter-edit-icon />
</n-icon>
</template>
编辑
</n-button>
<n-button tertiary size="small" @click="delFilter"> 删除 </n-button>
</n-space>
</template>
</n-card>
</template>
<template v-else>
<n-button class="go-ml-3" @click="addFilter">
<template #icon>
<n-icon>
<filter-icon />
</n-icon>
</template>
新增过滤器
</n-button>
</template>
<!-- 弹窗 -->
<n-modal class="go-chart-data-monaco-editor" v-model:show="showModal" :mask-closable="false" :closeOnEsc="false">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 600px">
<template #header>
<n-space>
<n-text>过滤器函数编辑器</n-text>
</n-space>
</template>
<template #header-extra> </template>
<n-space size="small" vertical>
<n-space justify="space-between">
<div>
<n-space vertical>
<n-tag type="info">
<span class="func-keyword">function</span>&nbsp;&nbsp;filter(data, res)&nbsp;&nbsp;{
</n-tag>
<monaco-editor v-model:modelValue="filter" width="460px" height="380px" language="javascript" />
<n-tag type="info">}</n-tag>
</n-space>
</div>
<n-divider vertical style="height: 480px" />
<n-scrollbar style="max-height: 480px">
<n-space :size="15" vertical>
<div class="editor-data-show">
<n-space>
<n-text depth="3">默认过滤数据(data)</n-text>
<n-code :code="toString(sourceData?.data) || '暂无'" language="json" :word-wrap="true"></n-code>
</n-space>
</div>
<div class="editor-data-show">
<n-space>
<n-text depth="3">接口返回数据(res)</n-text>
<n-code :code="toString(sourceData) || '暂无'" language="json" :word-wrap="true"></n-code>
</n-space>
</div>
<div class="editor-data-show">
<n-space>
<n-text depth="3">过滤器结果</n-text>
<n-code :code="filterRes || '暂无'" language="json" :word-wrap="true"></n-code>
</n-space>
</div>
</n-space>
</n-scrollbar>
</n-space>
</n-space>
<template #action>
<n-space justify="space-between">
<div class="go-flex-items-center">
<n-tag :bordered="false" type="primary">
<template #icon>
<n-icon :component="DocumentTextIcon" />
</template>
规则
</n-tag>
<n-text class="go-ml-2" depth="2">过滤器默认处理接口返回值的data字段</n-text>
</div>
<n-space>
<n-button size="medium" @click="closeFilter">取消</n-button>
<n-button size="medium" type="primary" @click="saveFilter">保存</n-button>
</n-space>
</n-space>
</template>
</n-card>
</n-modal>
</template>
<script lang="ts" setup>
import { ref, computed, watch, toRef, toRefs, toRaw, reactive } from 'vue'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
import { icon } from '@/plugins'
import { goDialog, toString } from '@/utils'
import { customizeHttp } from '@/api/http'
import cloneDeep from 'lodash/cloneDeep'
const { DocumentTextIcon } = icon.ionicons5
const { FilterIcon, FilterEditIcon } = icon.carbon
const { targetData, chartEditStore } = useTargetData()
const { requestDataType } = toRefs(targetData.value.request)
const { requestOriginUrl } = toRefs(chartEditStore.getRequestGlobalConfig)
// 受控弹窗
const showModal = ref(false)
// filter 函数模板
const filter = ref(targetData.value.filter || `return data`)
// 过滤错误标识
const errorFlag = ref(false)
// 目标静态/接口数据
const sourceData = ref<any>('')
// 动态获取数据
const fetchTargetData = async () => {
try {
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.getRequestGlobalConfig))
if (res) {
sourceData.value = res
return
}
window['$message'].warning('没有拿到返回值,请检查接口!')
} catch (error) {
console.error(error);
window['$message'].warning('数据异常,请检查参数!')
}
}
// 过滤结果
const filterRes = computed(() => {
try {
const fn = new Function('data', 'res', filter.value)
const response = cloneDeep(sourceData.value)
const res = fn(response?.data, response)
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
errorFlag.value = false
return toString(res)
} catch (error) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
errorFlag.value = true
return `过滤函数错误,日志:${error}`
}
})
// 新增过滤器
const addFilter = () => {
showModal.value = true
}
// 删除过滤器
const delFilter = () => {
goDialog({
message: '是否删除过滤器',
onPositiveCallback: () => {
targetData.value.filter = undefined
}
})
}
// 关闭过滤器
const closeFilter = () => {
showModal.value = false
}
// 新增过滤器
const saveFilter = () => {
if (errorFlag.value) {
window['$message'].error('过滤函数错误,无法进行保存')
return
}
targetData.value.filter = filter.value
closeFilter()
}
watch(
() => showModal.value,
(newData: boolean) => {
if (newData) {
fetchTargetData()
filter.value = targetData.value.filter || `return data`
}
}
)
</script>
<style lang="scss" scoped>
.func-keyword {
color: #b478cf;
}
@include go('chart-data-monaco-editor') {
&.n-card.n-modal,
.n-card {
@extend .go-background-filter;
}
.editor-data-show {
@include fetch-bg-color('filter-color');
width: 420px;
padding: 20px;
border-radius: 5px;
}
}
</style>
+3
View File
@@ -59,6 +59,8 @@
<n-form-item path="username">
<n-input
v-model:value="formInline.username"
type="text"
maxlength="16"
:placeholder="$t('global.form_account')"
>
<template #prefix>
@@ -72,6 +74,7 @@
<n-input
v-model:value="formInline.password"
type="password"
maxlength="16"
show-password-on="click"
:placeholder="$t('global.form_password')"
>