mirror of
https://gitee.com/dromara/go-view.git
synced 2026-07-15 03:51:07 +08:00
Compare commits
8 Commits
2e6611bf8b
...
f23439d31f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f23439d31f | ||
|
|
7b000f86c7 | ||
|
|
c3b7711f0a | ||
|
|
23625ec334 | ||
|
|
d0d601e836 | ||
|
|
0a775af9bb | ||
|
|
114285e791 | ||
|
|
af1775b6e7 |
@ -55,7 +55,7 @@ axiosInstance.interceptors.response.use(
|
||||
}
|
||||
const { code } = res.data as { code: number }
|
||||
|
||||
if (code === undefined || code === null) return Promise.resolve(res)
|
||||
if (code === undefined || code === null) return Promise.resolve(res.data)
|
||||
|
||||
// 成功
|
||||
if (code === ResultEnum.SUCCESS) {
|
||||
|
||||
@ -1,122 +1,123 @@
|
||||
import { ref, toRefs, toRaw, watch } from 'vue'
|
||||
import type VChart from 'vue-echarts'
|
||||
import { customizeHttp } from '@/api/http'
|
||||
import { useChartDataPondFetch } from '@/hooks/'
|
||||
import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { RequestDataTypeEnum } from '@/enums/httpEnum'
|
||||
import { isPreview, newFunctionHandle, intervalUnitHandle } from '@/utils'
|
||||
import { setOption } from '@/packages/public/chart'
|
||||
|
||||
// 获取类型
|
||||
type ChartEditStoreType = typeof useChartEditStore
|
||||
|
||||
/**
|
||||
* setdata 数据监听与更改
|
||||
* @param targetComponent
|
||||
* @param useChartEditStore 若直接引会报错,只能动态传递
|
||||
* @param updateCallback 自定义更新函数
|
||||
*/
|
||||
export const useChartDataFetch = (
|
||||
targetComponent: CreateComponentType,
|
||||
useChartEditStore: ChartEditStoreType,
|
||||
updateCallback?: (...args: any) => any
|
||||
) => {
|
||||
const vChartRef = ref<typeof VChart | null>(null)
|
||||
let fetchInterval: any = 0
|
||||
|
||||
// 数据池
|
||||
const { addGlobalDataInterface } = useChartDataPondFetch()
|
||||
|
||||
// 组件类型
|
||||
const { chartFrame } = targetComponent.chartConfig
|
||||
|
||||
// eCharts 组件配合 vChart 库更新方式
|
||||
const echartsUpdateHandle = (dataset: any) => {
|
||||
if (chartFrame === ChartFrameEnum.ECHARTS) {
|
||||
if (vChartRef.value) {
|
||||
setOption(vChartRef.value, { dataset: dataset })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const requestIntervalFn = () => {
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
// 全局数据
|
||||
const {
|
||||
requestOriginUrl,
|
||||
requestIntervalUnit: globalUnit,
|
||||
requestInterval: globalRequestInterval
|
||||
} = toRefs(chartEditStore.getRequestGlobalConfig)
|
||||
|
||||
// 目标组件
|
||||
const {
|
||||
requestDataType,
|
||||
requestUrl,
|
||||
requestIntervalUnit: targetUnit,
|
||||
requestInterval: targetInterval
|
||||
} = toRefs(targetComponent.request)
|
||||
|
||||
// 非请求类型
|
||||
if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
|
||||
|
||||
try {
|
||||
// 处理地址
|
||||
// @ts-ignore
|
||||
if (requestUrl?.value) {
|
||||
// requestOriginUrl 允许为空
|
||||
const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value
|
||||
if (!completePath) return
|
||||
|
||||
clearInterval(fetchInterval)
|
||||
|
||||
const fetchFn = async () => {
|
||||
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig))
|
||||
if (res) {
|
||||
try {
|
||||
const filter = targetComponent.filter
|
||||
echartsUpdateHandle(newFunctionHandle(res?.data, res, filter))
|
||||
// 更新回调函数
|
||||
if (updateCallback) {
|
||||
updateCallback(newFunctionHandle(res?.data, res, filter))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 普通初始化与组件交互处理监听
|
||||
watch(
|
||||
() => targetComponent.request,
|
||||
() => {
|
||||
fetchFn()
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
// 定时时间
|
||||
const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value
|
||||
// 单位
|
||||
const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value
|
||||
// 开启轮询
|
||||
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
if (isPreview()) {
|
||||
// 判断是否是数据池类型
|
||||
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
|
||||
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
|
||||
: requestIntervalFn()
|
||||
}
|
||||
return { vChartRef }
|
||||
}
|
||||
import { ref, toRefs, toRaw, watch } from 'vue'
|
||||
import type VChart from 'vue-echarts'
|
||||
import { customizeHttp } from '@/api/http'
|
||||
import { useChartDataPondFetch } from '@/hooks/'
|
||||
import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
import { RequestDataTypeEnum } from '@/enums/httpEnum'
|
||||
import { isPreview, newFunctionHandle, intervalUnitHandle } from '@/utils'
|
||||
import { setOption } from '@/packages/public/chart'
|
||||
|
||||
// 获取类型
|
||||
type ChartEditStoreType = typeof useChartEditStore
|
||||
|
||||
/**
|
||||
* setdata 数据监听与更改
|
||||
* @param targetComponent
|
||||
* @param useChartEditStore 若直接引会报错,只能动态传递
|
||||
* @param updateCallback 自定义更新函数
|
||||
*/
|
||||
export const useChartDataFetch = (
|
||||
targetComponent: CreateComponentType,
|
||||
useChartEditStore: ChartEditStoreType,
|
||||
updateCallback?: (...args: any) => any
|
||||
) => {
|
||||
const vChartRef = ref<typeof VChart | null>(null)
|
||||
let fetchInterval: any = 0
|
||||
|
||||
// 数据池
|
||||
const { addGlobalDataInterface } = useChartDataPondFetch()
|
||||
|
||||
// 组件类型
|
||||
const { chartFrame } = targetComponent.chartConfig
|
||||
|
||||
// eCharts 组件配合 vChart 库更新方式
|
||||
const echartsUpdateHandle = (dataset: any) => {
|
||||
if (chartFrame === ChartFrameEnum.ECHARTS) {
|
||||
if (vChartRef.value) {
|
||||
setOption(vChartRef.value, { dataset: dataset })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const requestIntervalFn = () => {
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
// 全局数据
|
||||
const {
|
||||
requestOriginUrl,
|
||||
requestIntervalUnit: globalUnit,
|
||||
requestInterval: globalRequestInterval
|
||||
} = toRefs(chartEditStore.getRequestGlobalConfig)
|
||||
|
||||
// 目标组件
|
||||
const {
|
||||
requestDataType,
|
||||
requestUrl,
|
||||
requestIntervalUnit: targetUnit,
|
||||
requestInterval: targetInterval
|
||||
} = toRefs(targetComponent.request)
|
||||
|
||||
// 非请求类型
|
||||
if (requestDataType.value !== RequestDataTypeEnum.AJAX) return
|
||||
|
||||
try {
|
||||
// 处理地址
|
||||
// @ts-ignore
|
||||
if (requestUrl?.value) {
|
||||
// requestOriginUrl 允许为空
|
||||
const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value
|
||||
if (!completePath) return
|
||||
|
||||
clearInterval(fetchInterval)
|
||||
|
||||
const fetchFn = async () => {
|
||||
const res = await customizeHttp(toRaw(targetComponent.request), toRaw(chartEditStore.getRequestGlobalConfig))
|
||||
if (res) {
|
||||
try {
|
||||
const filter = targetComponent.filter
|
||||
const { data } = res
|
||||
echartsUpdateHandle(newFunctionHandle(data, res, filter))
|
||||
// 更新回调函数
|
||||
if (updateCallback) {
|
||||
updateCallback(newFunctionHandle(data, res, filter))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 普通初始化与组件交互处理监听
|
||||
watch(
|
||||
() => targetComponent.request,
|
||||
() => {
|
||||
fetchFn()
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
// 定时时间
|
||||
const time = targetInterval && targetInterval.value ? targetInterval.value : globalRequestInterval.value
|
||||
// 单位
|
||||
const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value
|
||||
// 开启轮询
|
||||
if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
if (isPreview()) {
|
||||
// 判断是否是数据池类型
|
||||
targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
|
||||
? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
|
||||
: requestIntervalFn()
|
||||
}
|
||||
return { vChartRef }
|
||||
}
|
||||
|
||||
@ -1,77 +1,83 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ChartLayoutType, LayerModeEnum, ChartModeEnum } from './chartLayoutStore.d'
|
||||
import { setLocalStorage, getLocalStorage } from '@/utils'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
const { GO_CHART_LAYOUT_STORE } = StorageEnum
|
||||
|
||||
const storageChartLayout: Partial<ChartLayoutType> = getLocalStorage(GO_CHART_LAYOUT_STORE)
|
||||
|
||||
// 编辑区域布局和静态设置
|
||||
export const useChartLayoutStore = defineStore({
|
||||
id: 'useChartLayoutStore',
|
||||
state: (): ChartLayoutType => ({
|
||||
// 图层控制
|
||||
layers: true,
|
||||
// 图表组件
|
||||
charts: true,
|
||||
// 详情设置(收缩为true)
|
||||
details: false,
|
||||
// 组件列表展示类型(默认单列)
|
||||
chartType: ChartModeEnum.SINGLE,
|
||||
// 图层类型(默认图片)
|
||||
layerType: LayerModeEnum.THUMBNAIL,
|
||||
// 当前加载数量
|
||||
percentage: 0,
|
||||
// 是否重置当前画布位置
|
||||
rePositionCanvas: false,
|
||||
// 防止值不存在
|
||||
...storageChartLayout
|
||||
}),
|
||||
getters: {
|
||||
getLayers(): boolean {
|
||||
return this.layers
|
||||
},
|
||||
getCharts(): boolean {
|
||||
return this.charts
|
||||
},
|
||||
getDetails(): boolean {
|
||||
return this.details
|
||||
},
|
||||
getChartType(): ChartModeEnum {
|
||||
return this.chartType
|
||||
},
|
||||
getLayerType(): LayerModeEnum {
|
||||
return this.layerType
|
||||
},
|
||||
getPercentage(): number {
|
||||
return this.percentage
|
||||
},
|
||||
getRePositionCanvas(): boolean {
|
||||
return this.rePositionCanvas
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setItem<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(key: T, value: K): void {
|
||||
this.$patch(state => {
|
||||
state[key] = value
|
||||
})
|
||||
// 存储本地
|
||||
setLocalStorage(GO_CHART_LAYOUT_STORE, this.$state)
|
||||
// 这里需要标记重置画布位置
|
||||
this.rePositionCanvas = true;
|
||||
// 重新计算拖拽区域缩放比例
|
||||
setTimeout(() => {
|
||||
chartEditStore.computedScale()
|
||||
}, 500)
|
||||
},
|
||||
setItemUnHandle<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(key: T, value: K): void {
|
||||
this.$patch(state => {
|
||||
state[key] = value
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
import { defineStore } from 'pinia'
|
||||
import { ChartLayoutType, LayerModeEnum, ChartModeEnum } from './chartLayoutStore.d'
|
||||
import { setLocalStorage, getLocalStorage } from '@/utils'
|
||||
import { StorageEnum } from '@/enums/storageEnum'
|
||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||
|
||||
const chartEditStore = useChartEditStore()
|
||||
|
||||
const { GO_CHART_LAYOUT_STORE } = StorageEnum
|
||||
|
||||
const storageChartLayout: Partial<ChartLayoutType> = getLocalStorage(GO_CHART_LAYOUT_STORE)
|
||||
|
||||
// 编辑区域布局和静态设置
|
||||
export const useChartLayoutStore = defineStore({
|
||||
id: 'useChartLayoutStore',
|
||||
state: (): ChartLayoutType => ({
|
||||
// 图层控制
|
||||
layers: true,
|
||||
// 图表组件
|
||||
charts: true,
|
||||
// 详情设置(收缩为true)
|
||||
details: false,
|
||||
// 组件列表展示类型(默认单列)
|
||||
chartType: ChartModeEnum.SINGLE,
|
||||
// 图层类型(默认图片)
|
||||
layerType: LayerModeEnum.THUMBNAIL,
|
||||
// 当前加载数量
|
||||
percentage: 0,
|
||||
// 是否重置当前画布位置
|
||||
rePositionCanvas: false,
|
||||
// 防止值不存在
|
||||
...storageChartLayout
|
||||
}),
|
||||
getters: {
|
||||
getLayers(): boolean {
|
||||
return this.layers
|
||||
},
|
||||
getCharts(): boolean {
|
||||
return this.charts
|
||||
},
|
||||
getDetails(): boolean {
|
||||
return this.details
|
||||
},
|
||||
getChartType(): ChartModeEnum {
|
||||
return this.chartType
|
||||
},
|
||||
getLayerType(): LayerModeEnum {
|
||||
return this.layerType
|
||||
},
|
||||
getPercentage(): number {
|
||||
return this.percentage
|
||||
},
|
||||
getRePositionCanvas(): boolean {
|
||||
return this.rePositionCanvas
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setItem<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(
|
||||
key: T,
|
||||
value: K,
|
||||
computedScale = true
|
||||
): void {
|
||||
this.$patch(state => {
|
||||
state[key] = value
|
||||
})
|
||||
// 存储本地
|
||||
setLocalStorage(GO_CHART_LAYOUT_STORE, this.$state)
|
||||
// 这里需要标记重置画布位置
|
||||
this.rePositionCanvas = true;
|
||||
// 重新计算拖拽区域缩放比例
|
||||
if (computedScale) {
|
||||
setTimeout(() => {
|
||||
chartEditStore.computedScale()
|
||||
}, 500)
|
||||
}
|
||||
},
|
||||
setItemUnHandle<T extends keyof ChartLayoutType, K extends ChartLayoutType[T]>(key: T, value: K): void {
|
||||
this.$patch(state => {
|
||||
state[key] = value
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -1,92 +1,92 @@
|
||||
import { shallowReactive, ref } from 'vue'
|
||||
import { icon } from '@/plugins'
|
||||
import { renderLang, renderIcon } from '@/utils'
|
||||
import { themeColor, setItem, getCharts } from './useLayout.hook'
|
||||
import { PackagesCategoryEnum, PackagesCategoryName, PackagesType } from '@/packages/index.d'
|
||||
// 图表
|
||||
import { usePackagesStore } from '@/store/modules/packagesStore/packagesStore'
|
||||
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
|
||||
// 图标
|
||||
const { BarChartIcon } = icon.ionicons5
|
||||
const {
|
||||
TableSplitIcon,
|
||||
RoadmapIcon,
|
||||
SpellCheckIcon,
|
||||
GraphicalDataFlowIcon,
|
||||
} = icon.carbon
|
||||
|
||||
|
||||
// 图表
|
||||
export type MenuOptionsType = {
|
||||
key: string
|
||||
icon: ReturnType<typeof renderIcon>
|
||||
label: ReturnType<typeof renderLang>
|
||||
list: PackagesType
|
||||
}
|
||||
|
||||
const { getPackagesList } = usePackagesStore()
|
||||
const menuOptions: MenuOptionsType[] = []
|
||||
|
||||
const packagesListObj = {
|
||||
[PackagesCategoryEnum.CHARTS]: {
|
||||
icon: renderIcon(RoadmapIcon),
|
||||
label: PackagesCategoryName.CHARTS,
|
||||
},
|
||||
[PackagesCategoryEnum.INFORMATIONS]: {
|
||||
icon: renderIcon(SpellCheckIcon),
|
||||
label: PackagesCategoryName.INFORMATIONS,
|
||||
},
|
||||
[PackagesCategoryEnum.TABLES]: {
|
||||
icon: renderIcon(TableSplitIcon),
|
||||
label: PackagesCategoryName.TABLES,
|
||||
},
|
||||
[PackagesCategoryEnum.DECORATES]: {
|
||||
icon: renderIcon(GraphicalDataFlowIcon),
|
||||
label: PackagesCategoryName.DECORATES,
|
||||
},
|
||||
}
|
||||
|
||||
// 处理列表
|
||||
const handlePackagesList = () => {
|
||||
for (const val in getPackagesList) {
|
||||
menuOptions.push({
|
||||
key: val,
|
||||
// @ts-ignore
|
||||
icon: packagesListObj[val].icon,
|
||||
// @ts-ignore
|
||||
label: packagesListObj[val].label,
|
||||
// @ts-ignore
|
||||
list: getPackagesList[val],
|
||||
})
|
||||
}
|
||||
}
|
||||
handlePackagesList()
|
||||
|
||||
// 记录选中值
|
||||
let beforeSelect: string = menuOptions[0]['key']
|
||||
const selectValue = ref<string>(menuOptions[0]['key'])
|
||||
|
||||
// 选中的对象值
|
||||
const selectOptions = ref(menuOptions[0])
|
||||
|
||||
// 点击 item
|
||||
const clickItemHandle = (key: string, item: any) => {
|
||||
selectOptions.value = item
|
||||
// 处理折叠
|
||||
if (beforeSelect === key) {
|
||||
setItem(ChartLayoutStoreEnum.CHARTS, !getCharts.value)
|
||||
} else {
|
||||
setItem(ChartLayoutStoreEnum.CHARTS, true)
|
||||
}
|
||||
beforeSelect = key
|
||||
}
|
||||
|
||||
export {
|
||||
getCharts,
|
||||
BarChartIcon,
|
||||
themeColor,
|
||||
selectOptions,
|
||||
selectValue,
|
||||
clickItemHandle,
|
||||
menuOptions,
|
||||
}
|
||||
import { shallowReactive, ref } from 'vue'
|
||||
import { icon } from '@/plugins'
|
||||
import { renderLang, renderIcon } from '@/utils'
|
||||
import { themeColor, setItem, getCharts } from './useLayout.hook'
|
||||
import { PackagesCategoryEnum, PackagesCategoryName, PackagesType } from '@/packages/index.d'
|
||||
// 图表
|
||||
import { usePackagesStore } from '@/store/modules/packagesStore/packagesStore'
|
||||
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
|
||||
// 图标
|
||||
const { BarChartIcon } = icon.ionicons5
|
||||
const {
|
||||
TableSplitIcon,
|
||||
RoadmapIcon,
|
||||
SpellCheckIcon,
|
||||
GraphicalDataFlowIcon,
|
||||
} = icon.carbon
|
||||
|
||||
|
||||
// 图表
|
||||
export type MenuOptionsType = {
|
||||
key: string
|
||||
icon: ReturnType<typeof renderIcon>
|
||||
label: ReturnType<typeof renderLang>
|
||||
list: PackagesType
|
||||
}
|
||||
|
||||
const { getPackagesList } = usePackagesStore()
|
||||
const menuOptions: MenuOptionsType[] = []
|
||||
|
||||
const packagesListObj = {
|
||||
[PackagesCategoryEnum.CHARTS]: {
|
||||
icon: renderIcon(RoadmapIcon),
|
||||
label: PackagesCategoryName.CHARTS,
|
||||
},
|
||||
[PackagesCategoryEnum.INFORMATIONS]: {
|
||||
icon: renderIcon(SpellCheckIcon),
|
||||
label: PackagesCategoryName.INFORMATIONS,
|
||||
},
|
||||
[PackagesCategoryEnum.TABLES]: {
|
||||
icon: renderIcon(TableSplitIcon),
|
||||
label: PackagesCategoryName.TABLES,
|
||||
},
|
||||
[PackagesCategoryEnum.DECORATES]: {
|
||||
icon: renderIcon(GraphicalDataFlowIcon),
|
||||
label: PackagesCategoryName.DECORATES,
|
||||
},
|
||||
}
|
||||
|
||||
// 处理列表
|
||||
const handlePackagesList = () => {
|
||||
for (const val in getPackagesList) {
|
||||
menuOptions.push({
|
||||
key: val,
|
||||
// @ts-ignore
|
||||
icon: packagesListObj[val].icon,
|
||||
// @ts-ignore
|
||||
label: packagesListObj[val].label,
|
||||
// @ts-ignore
|
||||
list: getPackagesList[val],
|
||||
})
|
||||
}
|
||||
}
|
||||
handlePackagesList()
|
||||
|
||||
// 记录选中值
|
||||
let beforeSelect: string = menuOptions[0]['key']
|
||||
const selectValue = ref<string>(menuOptions[0]['key'])
|
||||
|
||||
// 选中的对象值
|
||||
const selectOptions = ref(menuOptions[0])
|
||||
|
||||
// 点击 item
|
||||
const clickItemHandle = (key: string, item: any) => {
|
||||
selectOptions.value = item
|
||||
// 处理折叠
|
||||
if (beforeSelect === key) {
|
||||
setItem(ChartLayoutStoreEnum.CHARTS, !getCharts.value, false)
|
||||
} else {
|
||||
setItem(ChartLayoutStoreEnum.CHARTS, true, false)
|
||||
}
|
||||
beforeSelect = key
|
||||
}
|
||||
|
||||
export {
|
||||
getCharts,
|
||||
BarChartIcon,
|
||||
themeColor,
|
||||
selectOptions,
|
||||
selectValue,
|
||||
clickItemHandle,
|
||||
menuOptions,
|
||||
}
|
||||
|
||||
@ -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> filter(data, res) {</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> filter(data, res) {
|
||||
</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> filter(data, res) {</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> filter(data, res) {
|
||||
</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>
|
||||
|
||||
@ -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')"
|
||||
>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user