Merge branch 'dev' into dev-feat-multi-select

This commit is contained in:
奔跑的面条
2022-08-05 08:42:47 +08:00
46 changed files with 1313 additions and 310 deletions
@@ -1,30 +0,0 @@
<template>
<div class="go-chart-data-setting">
<setting-item-box name="源地址" :alone="true">
<n-input
v-model:value.trim="chartEditStore.getRequestGlobalConfig.requestOriginUrl"
placeholder="源地址如: http://127.0.0.1"
></n-input>
</setting-item-box>
<setting-item-box name="更新间隔" :alone="true">
<n-input-number
v-model:value.trim="chartEditStore.getRequestGlobalConfig.requestInterval"
min="5"
:show-button="false"
placeholder="将应用全局组件"
>
<template #suffix>
</template>
</n-input-number>
</setting-item-box>
</div>
</template>
<script setup lang="ts">
import { SettingItemBox } from '@/components/Pages/ChartItemSetting'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
const chartEditStore = useChartEditStore()
</script>
@@ -135,7 +135,7 @@ import { PreviewScaleEnum } from '@/enums/styleEnum'
import { icon } from '@/plugins'
const { ColorPaletteIcon } = icon.ionicons5
const { ZAxisIcon, ScaleIcon, FitToScreenIcon, FitToHeightIcon, FitToWidthIcon } = icon.carbon
const { ScaleIcon, FitToScreenIcon, FitToHeightIcon, FitToWidthIcon } = icon.carbon
const chartEditStore = useChartEditStore()
const canvasConfig = chartEditStore.getEditCanvasConfig
@@ -147,9 +147,6 @@ const switchSelectColorLoading = ref(false)
const ChartThemeColor = loadAsyncComponent(() =>
import('./components/ChartThemeColor/index.vue')
)
const ChartDataSetting = loadAsyncComponent(() =>
import('./components/ChartDataSetting/index.vue')
)
// 北京默认展示颜色列表
const swatchesColors = [
@@ -169,12 +166,6 @@ const globalTabList = [
title: '主题颜色',
icon: ColorPaletteIcon,
render: ChartThemeColor
},
{
key: 'ChartSysSetting',
title: '数据配置',
icon: ZAxisIcon,
render: ChartDataSetting
}
]
@@ -1,44 +1,57 @@
<template>
<div class="go-chart-configurations-data-ajax">
<setting-item-box name="配置">
<setting-item name="类型">
<n-select v-model:value="targetData.request.requestHttpType" :options="selectOptions" />
</setting-item>
<setting-item name="默认使用全局间隔">
<n-input-number
v-model:value.trim="targetData.request.requestInterval"
min="5"
:show-button="false"
placeholder="可以为空"
>
<template #suffix> </template>
</n-input-number>
</setting-item>
</setting-item-box>
<n-card class="n-card-shallow">
<setting-item-box name="请求配置">
<setting-item name="类型">
<n-tag :bordered="false" type="primary" style="border-radius: 5px">
{{ requestContentType === RequestContentTypeEnum.DEFAULT ? '普通请求' : 'SQL请求' }}
</n-tag>
</setting-item>
<setting-item-box name="源地址:" :alone="true">
<n-text type="info">{{ requestOriginUrl || '暂无' }}</n-text>
</setting-item-box>
<setting-item name="方式">
<n-input size="small" :placeholder="requestHttpType || '暂无'" :disabled="true"></n-input>
</setting-item>
<setting-item-box :alone="true">
<template #name>
地址
<n-tooltip trigger="hover" v-if="isDev()">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
<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">
<n-input size="small" :placeholder="requestOriginUrl || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="PulseIcon" />
</template>
<ul class="go-pl-0">
开发环境使用 mock 数据请输入
<li v-for="item in apiList" :key="item.value">
<n-text type="info"> {{ item.value }} </n-text>
</li>
</ul>
</n-tooltip>
</template>
<n-input v-model:value.trim="targetData.request.requestUrl" :min="1" placeholder="请输入地址(去除源)" />
</setting-item-box>
</n-input>
</setting-item-box>
<setting-item-box name="组件地址" :alone="true">
<n-input size="small" :placeholder="requestUrl || '暂无'" :disabled="true">
<template #prefix>
<n-icon :component="FlashIcon" />
</template>
</n-input>
</setting-item-box>
<n-space justify="end">
<n-text depth="3" style="font-size: 12px">更新内容请点击展示区域</n-text>
</n-space>
<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>
测试
@@ -51,105 +64,91 @@
默认赋值给 dataset 字段
</n-tooltip>
</template>
<n-space>
<n-button @click="sendHandle">
<template #icon>
<n-icon>
<flash-icon />
</n-icon>
</template>
发送请求
</n-button>
</n-space>
<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"></chart-data-request>
</div>
</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 { RequestHttpEnum, ResultEnum } from '@/enums/httpEnum'
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 } from '@/api/http'
import { http, customizeHttp } from '@/api/http'
import { SelectHttpType } from '../../index.d'
import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { isDev, newFunctionHandle } from '@/utils'
const { HelpOutlineIcon, FlashIcon } = icon.ionicons5
const { HelpOutlineIcon, FlashIcon, PulseIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData()
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)
// 是否展示数据分析
const loading = ref(false)
const requestShow = ref(false)
const showMatching = ref(false)
let firstFocus = 0
let lastFilter: any = undefined
const apiList = [
{
value: `【图表】${chartDataUrl}`
},
{
value: `【文本】${textUrl}`
},
{
value: `【0~100 整数】${numberIntUrl}`
},
{
value: `【0~1小数】${numberFloatUrl}`
},
{
value: `【图片地址】${imageUrl}`
},
{
value: `【排名列表】${rankListUrl}`
},
{
value: `【滚动表格】${scrollBoardUrl}`
}
]
// 选项
const selectOptions: SelectHttpType[] = [
{
label: RequestHttpEnum.GET,
value: RequestHttpEnum.GET
},
{
label: RequestHttpEnum.POST,
value: RequestHttpEnum.POST
}
]
// 请求配置 model
const requestModelHandle = () => {
requestShow.value = true
}
// 发送请求
const sendHandle = async () => {
if(!targetData.value?.request) return
loading.value = true
if (!targetData.value) return
const { requestUrl, requestHttpType } = targetData.value.request
if (!requestUrl) {
window['$message'].warning('请求参数不正确,请检查!')
return
try {
const res = await customizeHttp(toRaw(targetData.value.request), toRaw(chartEditStore.requestGlobalConfig))
loading.value = false
if (res && res.data) {
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('数据异常,请检查参数!')
}
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
}
window['$message'].warning('数据异常,请检查接口数据!')
}
watchEffect(() => {
const filter = targetData.value?.filter
if (lastFilter !== filter) {
if (lastFilter !== filter && firstFocus) {
lastFilter = filter
sendHandle()
}
firstFocus ++
})
onBeforeUnmount(() => {
@@ -159,5 +158,33 @@ onBeforeUnmount(() => {
<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: 292px;
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>
@@ -72,7 +72,7 @@
</div>
</n-space>
<n-card size="small">
<n-code :code="filterRes(source)" language="json"></n-code>
<n-code :code="toString(source)" language="json"></n-code>
</n-card>
</n-space>
</n-timeline-item>
@@ -81,7 +81,7 @@
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { CreateComponentType, PackagesCategoryEnum } from '@/packages/index.d'
import { PackagesCategoryEnum } from '@/packages/index.d'
import { RequestDataTypeEnum } from '@/enums/httpEnum'
import { icon } from '@/plugins'
import { DataResultEnum, TimelineTitleEnum } from '../../index.d'
@@ -89,7 +89,6 @@ import { ChartDataMonacoEditor } from '../ChartDataMonacoEditor'
import { useFile } from '../../hooks/useFile.hooks'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import isObject from 'lodash/isObject'
import cloneDeep from 'lodash/cloneDeep'
import { toString } from '@/utils'
const { targetData } = useTargetData()
@@ -163,20 +162,6 @@ const dimensionsAndSourceHandle = () => {
}
}
// 过滤结果
const filterRes = (data: any) => {
try {
if(targetData.value.filter) {
const fn = new Function('data', targetData.value.filter)
const res = fn(cloneDeep(data))
return toString(res)
}
return toString(cloneDeep(data))
} catch (error) {
return '过滤函数错误'
}
}
watch(
() => targetData.value?.option?.dataset,
(
@@ -17,15 +17,13 @@
</template>
编辑
</n-button>
<n-button tertiary size="small" @click="delFilter">
删除
</n-button>
<n-button tertiary size="small" @click="delFilter"> 删除 </n-button>
</n-space>
</template>
</n-card>
</template>
<template v-else>
<n-button @click="addFilter">
<n-button class="go-ml-3" @click="addFilter">
<template #icon>
<n-icon>
<filter-icon />
@@ -97,13 +95,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,20 +122,14 @@ const sourceData = ref<any>('')
// 动态获取数据
const fetchTargetData = async () => {
try {
const { requestUrl, requestHttpType } = targetData.value.request
if (!requestUrl) {
window['$message'].warning('请求参数不正确,请检查!')
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.data) {
sourceData.value = res.data
return
}
window['$message'].warning('数据异常,请检查参数!')
} catch (error) {
window['$message'].warning('数据异常,请检查接口数据')
window['$message'].warning('数据异常,请检查参数')
}
}
@@ -0,0 +1,3 @@
import RequestGlobalConfig from './index.vue'
export { RequestGlobalConfig }
@@ -0,0 +1,105 @@
<template>
<!-- 全局配置 -->
<n-card class="n-card-shallow">
<n-tag type="info" :bordered="false" style="border-radius: 5px"> 全局配置 </n-tag>
<setting-item-box
name="服务"
:itemRightStyle="{
gridTemplateColumns: '5fr 2fr 1fr'
}"
>
<!-- 源地址 -->
<setting-item name="前置 URL">
<n-input v-model:value.trim="requestOriginUrl" :disabled="editDisabled" placeholder="例:http://127.0.0.1/"></n-input>
</setting-item>
<setting-item name="更新间隔,为 0 只会初始化">
<n-input-group>
<n-input-number
class="select-time-number"
v-model:value.trim="requestInterval"
min="0"
:show-button="false"
:disabled="editDisabled"
placeholder="请输入数字"
>
</n-input-number>
<!-- 单位 -->
<n-select
class="select-time-options"
v-model:value="requestIntervalUnit"
:options="selectTimeOptions"
:disabled="editDisabled"
/>
</n-input-group>
</setting-item>
<n-button v-show="editDisabled" type="primary" ghost @click="editDisabled = false">
<template #icon>
<n-icon>
<pencil-icon />
</n-icon>
</template>
编辑配置
</n-button>
</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>
</template>
<script setup lang="ts">
import { ref, toRefs } from 'vue'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { selectTypeOptions, selectTimeOptions } from '@/views/chart/ContentConfigurations/components/ChartData/index.d'
import { RequestGlobalHeaderTable } from '../RequestGlobalHeaderTable'
import { icon } from '@/plugins'
const { PencilIcon, ChevronDownOutlineIcon, ChevronUpOutlineIcon } = icon.ionicons5
const { chartEditStore } = useTargetData()
const { requestOriginUrl, requestInterval, requestIntervalUnit } = toRefs(chartEditStore.getRequestGlobalConfig)
const editDisabled = ref(true)
const designStore = useDesignStore()
const themeColor = ref(designStore.getAppTheme)
const showTable = ref(false)
</script>
<style lang="scss" scoped>
.n-card-shallow {
&:hover {
border-color: v-bind('themeColor');
}
}
.down {
cursor: pointer;
&:hover {
color: v-bind('themeColor');
}
}
.select-time-number {
width: 100%;
}
.select-time-options {
width: 100px;
}
</style>
@@ -0,0 +1,3 @@
import RequestGlobalHeaderTable from './index.vue'
export { RequestGlobalHeaderTable }
@@ -0,0 +1,45 @@
<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">
<!-- 这里的 v-if 是为了处理打包 ts 错类型误 -->
<request-header-table
v-if="tabValue === RequestParamsTypeEnum.HEADER"
:editDisabled="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'
defineProps({
editDisabled: {
type: Boolean,
default: true
}
})
const { chartEditStore } = useTargetData()
const { requestParams } = toRefs(chartEditStore.getRequestGlobalConfig)
const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.HEADER)
const tabs = [RequestParamsTypeEnum.HEADER]
// 更新表格参数
const updateRequestParams = (paramsObj: RequestParamsObjType) => {
if (tabValue.value === RequestParamsTypeEnum.HEADER) {
requestParams.value[tabValue.value] = paramsObj
}
}
</script>
<style lang="scss" scoped></style>
@@ -0,0 +1,3 @@
import RequestHeader from './index.vue'
export { RequestHeader }
@@ -0,0 +1,134 @@
<template>
<n-space vertical>
<div style="width: 600px">
<n-tabs v-model:value="requestContentType" type="segment" size="small">
<n-tab :name="RequestContentTypeEnum.DEFAULT" tab="普通请求"> </n-tab>
<n-tab :name="RequestContentTypeEnum.SQL" tab="SQL 请求"> </n-tab>
</n-tabs>
</div>
<div v-show="requestContentType === RequestContentTypeEnum.DEFAULT">
<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="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 go-pb-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">
<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>
<script setup lang="ts">
import { ref, toRefs } from 'vue'
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,
RequestHttpEnum
} from '@/enums/httpEnum'
const { targetData } = useTargetData()
const { requestHttpType, requestContentType, requestSQLContent, requestParams, requestParamsBodyType } = toRefs(targetData.value.request)
const tabValue = ref<RequestParamsTypeEnum>(RequestParamsTypeEnum.PARAMS)
// 更新参数表格数据
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>
.select-type {
width: 300px;
}
</style>
@@ -0,0 +1,3 @@
import RequestHeaderTable from './index.vue'
export { RequestHeaderTable }
@@ -0,0 +1,161 @@
<template>
<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" :disabled="editDisabled" type="text" size="small" @blur="blur" />
</td>
<td>
<n-input v-model:value="item.value" :disabled="editDisabled" type="text" size="small" @blur="blur" />
</td>
<td>
<div style="width: 80px">
<n-button class="go-ml-2" type="primary" size="small" ghost :disabled="editDisabled" @click="add(index)"
>+</n-button
>
<n-button
class="go-ml-2"
type="warning"
size="small"
ghost
:disabled="index === 0 && editDisabled"
@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="primary"> 格式通过 </n-button>
</td>
</tr>
</tbody>
</n-table>
</template>
<script setup lang="ts">
import { PropType, reactive, ref, toRefs, watch } from 'vue'
import { RequestParamsObjType } from '@/enums/httpEnum'
const emits = defineEmits(['update'])
const props = defineProps({
target: {
type: Object as PropType<RequestParamsObjType>,
required: true,
default: () => {}
},
editDisabled: {
type: Boolean,
required: false,
default: false
}
})
// 错误标识
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">
@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>
@@ -0,0 +1,3 @@
import RequestTargetConfig from './index.vue'
export { RequestTargetConfig }
@@ -0,0 +1,107 @@
<template>
<!-- 组件配置 -->
<n-divider class="go-my-3" title-placement="left"></n-divider>
<setting-item-box
:itemRightStyle="{
gridTemplateColumns: '5fr 2fr 1fr'
}"
>
<template #name>
地址
<n-tooltip trigger="hover" v-if="isDev()">
<template #trigger>
<n-icon size="21" :depth="3">
<help-outline-icon></help-outline-icon>
</n-icon>
</template>
<ul class="go-pl-0">
开发环境使用 mock 数据请输入
<li v-for="item in apiList" :key="item.value">
<n-text type="info"> {{ item.value }} </n-text>
</li>
</ul>
</n-tooltip>
</template>
<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="请输入地址(去除前置URL">
<template #prefix>
<n-text>{{ requestOriginUrl }}</n-text>
<n-divider vertical />
</template>
</n-input>
</n-input-group>
<!-- 组件url -->
</setting-item>
<setting-item name="更新间隔,为 0 只会初始化">
<n-input-group>
<n-input-number
v-model:value.trim="requestInterval"
class="select-time-number"
min="0"
:show-button="false"
placeholder="默认使用全局数据"
>
</n-input-number>
<!-- 单位 -->
<n-select class="select-time-options" v-model:value="requestIntervalUnit" :options="selectTimeOptions" />
</n-input-group>
</setting-item>
</setting-item-box>
<setting-item-box name="选择方式" class="go-mt-0">
<request-header></request-header>
</setting-item-box>
</template>
<script setup lang="ts">
import { ref, toRefs } from 'vue'
import { SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { useTargetData } from '@/views/chart/ContentConfigurations/components/hooks/useTargetData.hook'
import { selectTypeOptions, selectTimeOptions } from '@/views/chart/ContentConfigurations/components/ChartData/index.d'
import { RequestHeader } from '../RequestHeader'
import { isDev } from '@/utils'
import { icon } from '@/plugins'
import { chartDataUrl, rankListUrl, scrollBoardUrl, numberFloatUrl, numberIntUrl, textUrl, imageUrl } from '@/api/mock'
const { HelpOutlineIcon } = icon.ionicons5
const { targetData, chartEditStore } = useTargetData()
const { requestOriginUrl } = toRefs(chartEditStore.getRequestGlobalConfig)
const { requestInterval, requestIntervalUnit, requestHttpType, requestUrl } = toRefs(targetData.value.request)
const apiList = [
{
value: `【图表】${chartDataUrl}`
},
{
value: `【文本】${textUrl}`
},
{
value: `【0~100 整数】${numberIntUrl}`
},
{
value: `【0~1小数】${numberFloatUrl}`
},
{
value: `【图片地址】${imageUrl}`
},
{
value: `【排名列表】${rankListUrl}`
},
{
value: `【滚动表格】${scrollBoardUrl}`
}
]
</script>
<style lang="scss" scoped>
.select-time-number {
width: 100%;
}
.select-time-options {
width: 100px;
}
.select-type-options {
width: 120px;
}
</style>
@@ -0,0 +1,3 @@
import ChartDataRequest from './index.vue'
export { ChartDataRequest }
@@ -0,0 +1,75 @@
<template>
<n-modal class="go-chart-data-request" v-model:show="modelShow" :mask-closable="false" @afterLeave="closeHandle">
<n-card :bordered="false" role="dialog" size="small" aria-modal="true" style="width: 1000px; height: 800px">
<template #header></template>
<template #header-extra> </template>
<n-scrollbar style="max-height: 718px">
<div class="go-pr-3">
<n-space vertical>
<request-global-config></request-global-config>
<request-target-config></request-target-config>
</n-space>
</div>
</n-scrollbar>
<!-- 底部 -->
<template #action>
<n-space justify="space-between">
<div>
<n-text> {{ chartConfig.categoryName || rename }} </n-text>
<n-text> </n-text>
<n-tag type="primary" :bordered="false" style="border-radius: 5px"> {{ requestContentTypeObj[requestContentType] }} </n-tag>
</div>
<n-button type="primary" @click="closeHandle">确认</n-button>
</n-space>
</template>
</n-card>
</n-modal>
</template>
<script script lang="ts" setup>
import { toRefs } from 'vue'
import { RequestContentTypeEnum } from '@/enums/httpEnum'
import { useTargetData } from '../../../hooks/useTargetData.hook'
import { RequestGlobalConfig } from './components/RequestGlobalConfig'
import { RequestTargetConfig } from './components/RequestTargetConfig'
const emit = defineEmits(['update:modelShow'])
const { targetData } = useTargetData()
// 解构基础配置
const { chartConfig, rename } = toRefs(targetData.value)
const { requestContentType } = toRefs(targetData.value.request)
const requestContentTypeObj = {
[RequestContentTypeEnum.DEFAULT]: '普通请求',
[RequestContentTypeEnum.SQL]: 'SQL 请求'
}
defineProps({
modelShow: Boolean
})
const closeHandle = () => {
emit('update:modelShow', false)
}
</script>
<style lang="scss" scoped>
@include go('chart-data-request') {
&.n-card.n-modal,
.n-card {
@extend .go-background-filter;
}
.n-card-shallow {
background-color: rgba(0, 0, 0, 0) !important;
}
@include deep() {
& > .n-card__content {
padding-right: 0;
}
.n-card__content {
padding-bottom: 5px;
}
}
}
</style>
@@ -1,4 +1,4 @@
import { RequestHttpEnum, RequestDataTypeEnum } from '@/enums/httpEnum'
import { RequestHttpEnum, RequestHttpIntervalEnum, RequestDataTypeEnum, SelectHttpTimeNameObj } from '@/enums/httpEnum'
// 匹配结果
export enum DataResultEnum {
@@ -24,9 +24,81 @@ export interface SelectCreateDataType {
disabled?: boolean
}
// ajax 请求
// ajax 请求类型
export interface SelectHttpType {
label: RequestHttpEnum
value: RequestHttpEnum
disabled?: boolean
style?: object
}
// 类型选项
export const selectTypeOptions: SelectHttpType[] = [
{
label: RequestHttpEnum.GET,
value: RequestHttpEnum.GET,
style: {
color: 'greenyellow',
fontWeight: 'bold'
}
},
{
label: RequestHttpEnum.POST,
value: RequestHttpEnum.POST,
style: {
color: 'skyblue',
fontWeight: 'bold'
}
},
{
label: RequestHttpEnum.PUT,
value: RequestHttpEnum.PUT,
style: {
color: 'goldenrod',
fontWeight: 'bold'
}
},
{
label: RequestHttpEnum.PATCH,
value: RequestHttpEnum.PATCH,
style: {
color: 'violet',
fontWeight: 'bold'
}
},
{
label: RequestHttpEnum.DELETE,
value: RequestHttpEnum.DELETE,
disabled: true,
style: {
fontWeight: 'bold'
}
},
]
// ajax 请求间隔
export interface SelectHttpTimeType {
label: string
value: RequestHttpIntervalEnum
disabled?: boolean
}
// 时间选项
export const selectTimeOptions: SelectHttpTimeType[] = [
{
label: SelectHttpTimeNameObj[RequestHttpIntervalEnum.SECOND],
value: RequestHttpIntervalEnum.SECOND
},
{
label: SelectHttpTimeNameObj[RequestHttpIntervalEnum.MINUTE],
value: RequestHttpIntervalEnum.MINUTE
},
{
label: SelectHttpTimeNameObj[RequestHttpIntervalEnum.HOUR],
value: RequestHttpIntervalEnum.HOUR
},
{
label: SelectHttpTimeNameObj[RequestHttpIntervalEnum.DAY],
value: RequestHttpIntervalEnum.DAY
},
]
@@ -7,8 +7,6 @@
/>
</setting-item-box>
<n-divider style="margin: 10px 0;"></n-divider>
<!-- 静态 -->
<chart-data-static
v-if="targetData.request.requestDataType === RequestDataTypeEnum.STATIC"
@@ -1,13 +0,0 @@
<template>
<div>
事件
</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
</style>
@@ -1,9 +1,5 @@
<template>
<div
class="go-edit-range go-transition"
:style="rangeStyle"
@mousedown="mousedownHandleUnStop($event, undefined)"
>
<div class="go-edit-range go-transition" :style="rangeStyle" @mousedown="mousedownHandleUnStop($event, undefined)">
<slot></slot>
<!-- 水印 -->
<edit-watermark></edit-watermark>
@@ -41,18 +37,8 @@ const rangeStyle = computed(() => {
const scale = {
transform: `scale(${getEditCanvas.value.scale})`
}
// 设置背景色和图片背景
const background = getEditCanvasConfig.value.background
const backgroundImage = getEditCanvasConfig.value.backgroundImage
const selectColor = getEditCanvasConfig.value.selectColor
const backgroundColor = background ? background : undefined
const computedBackground = selectColor
? { background: backgroundColor }
: { background: `url(${backgroundImage}) no-repeat center/100% !important` }
// @ts-ignore
return { ...useSizeStyle(size.value), ...computedBackground, ...scale }
return { ...useSizeStyle(size.value), ...scale }
})
// 模态层
+1 -1
View File
@@ -112,7 +112,7 @@ const rangeStyle = computed(() => {
const computedBackground = selectColor
? { background: backgroundColor }
: { background: `url(${backgroundImage}) no-repeat center/100% !important` }
: { background: `url(${backgroundImage}) no-repeat center center / cover !important` }
// @ts-ignore
return {
+6 -15
View File
@@ -1,7 +1,5 @@
<template>
<div
:class="`go-preview ${localStorageInfo.editCanvasConfig.previewScaleType}`"
>
<div :class="`go-preview ${localStorageInfo.editCanvasConfig.previewScaleType}`">
<template v-if="showEntity">
<!-- 实体区域 -->
<div ref="entityRef" class="go-preview-entity">
@@ -10,9 +8,7 @@
<!-- 展示层 -->
<div :style="previewRefStyle" v-if="show">
<!-- 渲染层 -->
<preview-render-list
:localStorageInfo="localStorageInfo"
></preview-render-list>
<preview-render-list :localStorageInfo="localStorageInfo"></preview-render-list>
</div>
</div>
</div>
@@ -23,9 +19,7 @@
<!-- 展示层 -->
<div :style="previewRefStyle" v-if="show">
<!-- 渲染层 -->
<preview-render-list
:localStorageInfo="localStorageInfo"
></preview-render-list>
<preview-render-list :localStorageInfo="localStorageInfo"></preview-render-list>
</div>
</div>
</template>
@@ -43,21 +37,18 @@ import { useStore } from './hooks/useStore.hook'
import { PreviewScaleEnum } from '@/enums/styleEnum'
import type { ChartEditStorageType } from './index.d'
const localStorageInfo: ChartEditStorageType =
getSessionStorageInfo() as ChartEditStorageType
const localStorageInfo: ChartEditStorageType = getSessionStorageInfo() as ChartEditStorageType
const previewRefStyle = computed(() => {
return {
...getEditCanvasConfigStyle(localStorageInfo.editCanvasConfig),
...getFilterStyle(localStorageInfo.editCanvasConfig),
...getFilterStyle(localStorageInfo.editCanvasConfig)
}
})
const showEntity = computed(() => {
const type = localStorageInfo.editCanvasConfig.previewScaleType
return (
type === PreviewScaleEnum.SCROLL_Y || type === PreviewScaleEnum.SCROLL_X
)
return type === PreviewScaleEnum.SCROLL_Y || type === PreviewScaleEnum.SCROLL_X
})
useStore(localStorageInfo)
+1 -1
View File
@@ -28,7 +28,7 @@ export const getEditCanvasConfigStyle = (canvas: EditCanvasConfigType) => {
const computedBackground = canvas.selectColor
? { background: canvas.background }
: {
background: `url(${canvas.backgroundImage}) no-repeat center/100% !important`
background: `url(${canvas.backgroundImage}) center center / cover no-repeat !important`
}
return {
position: 'relative' as const,